Skip to content

Commit

Permalink
ESLint plugin - initial refactor + reintroduce test of graph with a s…
Browse files Browse the repository at this point in the history
…ubgraph (#141)

* Move tests to a dedicated folder

* Build obsidian before eslint plugin + fix tsconfig in eslint plugin

* Move testUtils to tests folder + fix eslint warning in IDE

* Properly exclude tests from dist

* oopsie woopsie

* Mock file path resolving in tests + reintroduce subgraph test
  • Loading branch information
guyca authored Jun 16, 2024
1 parent 00f2304 commit 76b5dba
Show file tree
Hide file tree
Showing 16 changed files with 97 additions and 48 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"scripts": {
"test": "yarn workspaces foreach run test --colors",
"lint": "yarn workspaces foreach run lint",
"build": "yarn workspaces foreach run build"
"build": "yarn workspace react-obsidian build && yarn workspace eslint-plugin-obsidian build"
},
"workspaces": [
"packages/*"
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin-obsidian/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const config = {
resetMocks: true,
resetModules: true,
roots: [
'rules',
'tests'
],
testEnvironment: 'jsdom',
};
Expand Down
6 changes: 3 additions & 3 deletions packages/eslint-plugin-obsidian/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"main": "dist/index.js",
"version": "2.5.0",
"scripts": {
"build": "npx tsc",
"build": "npx tsc --project tsconfig.prod.json",
"test": "npx jest",
"lint": "eslint rules --ignore-pattern '*.d.ts' --ext .ts,.tsx,.js"
},
Expand All @@ -15,7 +15,8 @@
"LICENSE"
],
"peerDependencies": {
"eslint": "8.x.x"
"eslint": "8.x.x",
"react-obsidian": "2.x.x"
},
"dependencies": {
"@typescript-eslint/parser": "6.6.x",
Expand Down Expand Up @@ -48,7 +49,6 @@
"eslint-plugin-unused-imports": "3.1.x",
"jest": "29.5.x",
"jest-extended": "^4.0.0",
"react-obsidian": "2.x.x",
"typescript": "^4.5.4"
},
"keywords": [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { RuleContext } from '@typescript-eslint/utils/ts-eslint';
import path = require('path') ;

export class PathResolver {
public resolve(context: RuleContext<any, any>, relativeFilePath: string) {
return path.join(path.dirname(context.getFilename()), `${relativeFilePath}.ts`);
}
}
4 changes: 2 additions & 2 deletions packages/eslint-plugin-obsidian/rules/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { unresolvedProviderDependencies } = require('./unresolvedProviderDependencies');
const { unresolvedProviderDependenciesGenerator } = require('./unresolvedProviderDependencies');

module.exports = {
rules: {
'unresolved-provider-dependencies': unresolvedProviderDependencies,
'unresolved-provider-dependencies': unresolvedProviderDependenciesGenerator(),
},
};
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { TSESTree } from '@typescript-eslint/types';
import * as fs from 'fs';
import { parse } from '@typescript-eslint/parser';
import path = require('path') ;
import type { RuleContext } from '@typescript-eslint/utils/ts-eslint';
import { PathResolver } from '../framework/pathResolver';

export type MessageIds = 'unresolved-provider-dependencies';

Expand Down Expand Up @@ -30,6 +30,7 @@ export function getDependenciesFromSubgraphs(
imports: TSESTree.ImportDeclaration[],
subGraphs:string[],
context:RuleContext<'unresolved-provider-dependencies', []>,
pathResolver: PathResolver,
) {
const paths:Record<string, string>[] = [];
const dependencies: string[] = [];
Expand All @@ -42,8 +43,8 @@ export function getDependenciesFromSubgraphs(
});
paths.forEach((el) => {
// eslint-disable-next-line dot-notation
const filePath = path.join(path.dirname(context.getFilename()), `${el['path']}.ts`);
const fileContent = fs.readFileSync(filePath, 'utf8');
const filePath = pathResolver.resolve(context, el['path']);
const fileContent = fs.readFileSync(filePath, { encoding: 'utf8'});
const fileAST = parse(
fileContent,
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ import {
getDecoratorName,
getPropertyDeclarations,
} from './ASTFunctions';
import type { PathResolver } from '../framework/pathResolver';

export function create(context: RuleContext<'unresolved-provider-dependencies', []>) {
export function create(
context: RuleContext<'unresolved-provider-dependencies', []>,
pathResolver: PathResolver,
) {
const imports:TSESTree.ImportDeclaration[] = [];
const dependencies:string[] = [];

Expand All @@ -24,7 +28,7 @@ export function create(context: RuleContext<'unresolved-provider-dependencies',
if (decoratorNames.includes('Graph')) {
const subGraphs = getSubGraphs(decorators);
if (subGraphs.length > 0) {
dependencies.push(...getDependenciesFromSubgraphs(imports, subGraphs, context));
dependencies.push(...getDependenciesFromSubgraphs(imports, subGraphs, context, pathResolver));
}
dependencies.push(...mapFunctions(node));
dependencies.push(...getPropertyDeclarations(node));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
import { ESLintUtils, type TSESLint } from '@typescript-eslint/utils';
import { create } from './createFunction';
import type { RuleContext } from '@typescript-eslint/utils/ts-eslint';
import { create } from './createRule';
import { PathResolver } from '../framework/pathResolver';

type Rule = TSESLint.RuleModule<'unresolved-provider-dependencies', []>;

const createRule = ESLintUtils.RuleCreator(
(name) => `https://wix-incubator.github.io/obsidian/docs/documentation/meta/eslint#${name}`,
);

type Rule = TSESLint.RuleModule<'unresolved-provider-dependencies', []>;


export const unresolvedProviderDependencies: Rule = createRule({
create,
name: 'unresolved-provider-dependencies',
meta: {
docs: {
description: 'Dependencies must be defined in the graph or its subgraphs.',
recommended: 'strict',
export const unresolvedProviderDependenciesGenerator = (
pathResolver: PathResolver = new PathResolver(),
) => {
return createRule({
create: (context: RuleContext<'unresolved-provider-dependencies', []>) => {
return create(context, pathResolver);
},
messages: {
'unresolved-provider-dependencies': 'Dependency {{ dependencyName }} is unresolved.',
name: 'unresolved-provider-dependencies',
meta: {
docs: {
description: 'Dependencies must be defined in the graph or its subgraphs.',
recommended: 'strict',
},
messages: {
'unresolved-provider-dependencies': 'Dependency {{ dependencyName }} is unresolved.',
},
schema: [],
type: 'problem',
},
schema: [],
type: 'problem',
},
defaultOptions: [],
});
defaultOptions: [],
}) satisfies Rule;
};

This file was deleted.

14 changes: 14 additions & 0 deletions packages/eslint-plugin-obsidian/tests/stubs/PathResolverStub.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { RuleContext } from '@typescript-eslint/utils/ts-eslint';
import path = require('path') ;
import { PathResolver } from '../../rules/framework/pathResolver';

export class PathResolverStub implements PathResolver {
public resolve(context: RuleContext<any, any>, relativeFilePath: string): string {
switch(relativeFilePath) {
case './subgraph':
return `${context.cwd}/tests/unresolvedProviderDependencies/testUtils/subgraph.ts`;
default:
return path.join(path.dirname(context.getFilename()), `${relativeFilePath}.ts`);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { RuleTester } from '@typescript-eslint/rule-tester';
import { validGraphSimple, validGraphWithSubgraph } from './testUtils/validGraphs';
import { unresolvedProviderDependenciesGenerator } from '../../rules/unresolvedProviderDependencies';
import { invalidGraph } from '../../rules/unresolvedProviderDependencies/invalidGraphs';
import { PathResolverStub } from '../stubs/PathResolverStub';

const ruleTester = new RuleTester();

ruleTester.run(
'unresolved-provider-dependencies',
unresolvedProviderDependenciesGenerator(new PathResolverStub()),
{
valid: [validGraphSimple, validGraphWithSubgraph],
invalid: [
{
code: invalidGraph,
errors: [{
messageId: 'unresolved-provider-dependencies',
}],
},
],
}
);
1 change: 1 addition & 0 deletions packages/eslint-plugin-obsidian/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"include": [
"rules/**/*",
"tests/**/*",
".eslintrc.js",
],
"exclude": [
Expand Down
7 changes: 7 additions & 0 deletions packages/eslint-plugin-obsidian/tsconfig.prod.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "./tsconfig.json",
"exclude": [
"**/*.test.*",
"tests"
]
}
4 changes: 2 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4054,10 +4054,10 @@ __metadata:
jest: 29.5.x
jest-extended: ^4.0.0
lodash: ^4.17.21
react-obsidian: 2.x.x
typescript: ^4.5.4
peerDependencies:
eslint: 8.x.x
react-obsidian: 2.x.x
languageName: unknown
linkType: soft

Expand Down Expand Up @@ -6836,7 +6836,7 @@ __metadata:
languageName: node
linkType: hard

"react-obsidian@2.x.x, react-obsidian@workspace:packages/react-obsidian":
"react-obsidian@workspace:packages/react-obsidian":
version: 0.0.0-use.local
resolution: "react-obsidian@workspace:packages/react-obsidian"
dependencies:
Expand Down

0 comments on commit 76b5dba

Please sign in to comment.