diff --git a/.changeset/icy-mammals-cover.md b/.changeset/icy-mammals-cover.md new file mode 100644 index 000000000..025752957 --- /dev/null +++ b/.changeset/icy-mammals-cover.md @@ -0,0 +1,5 @@ +--- +'eslint-plugin-svelte': patch +--- + +feat(no-navigation-without-resolve): added support for ResolvedPathname types diff --git a/packages/eslint-plugin-svelte/src/rules/no-navigation-without-resolve.ts b/packages/eslint-plugin-svelte/src/rules/no-navigation-without-resolve.ts index 0beb2aa71..f6ef1a622 100644 --- a/packages/eslint-plugin-svelte/src/rules/no-navigation-without-resolve.ts +++ b/packages/eslint-plugin-svelte/src/rules/no-navigation-without-resolve.ts @@ -5,6 +5,7 @@ import { FindVariableContext } from '../utils/ast-utils.js'; import { findVariable } from '../utils/ast-utils.js'; import type { RuleContext } from '../types.js'; import type { AST } from 'svelte-eslint-parser'; +import { type TSTools, getTypeScriptTools } from 'src/utils/ts-utils/index.js'; export default createRule('no-navigation-without-resolve', { meta: { @@ -48,6 +49,8 @@ export default createRule('no-navigation-without-resolve', { ] }, create(context) { + const tsTools = getTypeScriptTools(context); + let resolveReferences: Set = new Set(); return { Program() { @@ -60,7 +63,7 @@ export default createRule('no-navigation-without-resolve', { } = extractFunctionCallReferences(referenceTracker); if (context.options[0]?.ignoreGoto !== true) { for (const gotoCall of gotoCalls) { - checkGotoCall(context, gotoCall, resolveReferences); + checkGotoCall(context, gotoCall, resolveReferences, tsTools); } } if (context.options[0]?.ignorePushState !== true) { @@ -69,6 +72,7 @@ export default createRule('no-navigation-without-resolve', { context, pushStateCall, resolveReferences, + tsTools, 'pushStateWithoutResolve' ); } @@ -79,6 +83,7 @@ export default createRule('no-navigation-without-resolve', { context, replaceStateCall, resolveReferences, + tsTools, 'replaceStateWithoutResolve' ); } @@ -105,7 +110,8 @@ export default createRule('no-navigation-without-resolve', { !isResolveCall( new FindVariableContext(context), node.value[0].expression, - resolveReferences + resolveReferences, + tsTools )) ) { context.report({ loc: node.value[0].loc, messageId: 'linkWithoutResolve' }); @@ -190,13 +196,14 @@ function extractFunctionCallReferences(referenceTracker: ReferenceTracker): { function checkGotoCall( context: RuleContext, call: TSESTree.CallExpression, - resolveReferences: Set + resolveReferences: Set, + tsTools: TSTools | null ): void { if (call.arguments.length < 1) { return; } const url = call.arguments[0]; - if (!isResolveCall(new FindVariableContext(context), url, resolveReferences)) { + if (!isResolveCall(new FindVariableContext(context), url, resolveReferences, tsTools)) { context.report({ loc: url.loc, messageId: 'gotoWithoutResolve' }); } } @@ -205,6 +212,7 @@ function checkShallowNavigationCall( context: RuleContext, call: TSESTree.CallExpression, resolveReferences: Set, + tsTools: TSTools | null, messageId: string ): void { if (call.arguments.length < 1) { @@ -213,7 +221,7 @@ function checkShallowNavigationCall( const url = call.arguments[0]; if ( !expressionIsEmpty(url) && - !isResolveCall(new FindVariableContext(context), url, resolveReferences) + !isResolveCall(new FindVariableContext(context), url, resolveReferences, tsTools) ) { context.report({ loc: url.loc, messageId }); } @@ -224,7 +232,8 @@ function checkShallowNavigationCall( function isResolveCall( ctx: FindVariableContext, node: TSESTree.CallExpressionArgument, - resolveReferences: Set + resolveReferences: Set, + tsTools: TSTools | null ): boolean { if ( node.type === 'CallExpression' && @@ -235,9 +244,13 @@ function isResolveCall( ) { return true; } - if (node.type !== 'Identifier') { + if (node.type !== 'Identifier' || tsTools === null) { return false; } + const tsNode = tsTools.service.esTreeNodeToTSNodeMap.get(node); + console.log(tsNode); + console.log(tsTools.service.program.getTypeChecker().getTypeAtLocation(tsNode)); + /* const variable = ctx.findVariable(node); if ( variable === null || @@ -248,6 +261,7 @@ function isResolveCall( return false; } return isResolveCall(ctx, variable.identifiers[0].parent.init, resolveReferences); + */ } function expressionIsEmpty(url: TSESTree.CallExpressionArgument): boolean { diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/valid/goto-resolved-pathname01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/valid/goto-resolved-pathname01-input.svelte new file mode 100644 index 000000000..1e9130638 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/valid/goto-resolved-pathname01-input.svelte @@ -0,0 +1,12 @@ + diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/valid/goto-resolved01-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/valid/goto-resolved01-input.svelte index e29e15798..f380109c5 100644 --- a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/valid/goto-resolved01-input.svelte +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-navigation-without-resolve/valid/goto-resolved01-input.svelte @@ -1,4 +1,4 @@ -