Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/icy-mammals-cover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'eslint-plugin-svelte': patch
---

feat(no-navigation-without-resolve): added support for ResolvedPathname types
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -48,6 +49,8 @@ export default createRule('no-navigation-without-resolve', {
]
},
create(context) {
const tsTools = getTypeScriptTools(context);

let resolveReferences: Set<TSESTree.Identifier> = new Set<TSESTree.Identifier>();
return {
Program() {
Expand All @@ -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) {
Expand All @@ -69,6 +72,7 @@ export default createRule('no-navigation-without-resolve', {
context,
pushStateCall,
resolveReferences,
tsTools,
'pushStateWithoutResolve'
);
}
Expand All @@ -79,6 +83,7 @@ export default createRule('no-navigation-without-resolve', {
context,
replaceStateCall,
resolveReferences,
tsTools,
'replaceStateWithoutResolve'
);
}
Expand All @@ -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' });
Expand Down Expand Up @@ -190,13 +196,14 @@ function extractFunctionCallReferences(referenceTracker: ReferenceTracker): {
function checkGotoCall(
context: RuleContext,
call: TSESTree.CallExpression,
resolveReferences: Set<TSESTree.Identifier>
resolveReferences: Set<TSESTree.Identifier>,
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' });
}
}
Expand All @@ -205,6 +212,7 @@ function checkShallowNavigationCall(
context: RuleContext,
call: TSESTree.CallExpression,
resolveReferences: Set<TSESTree.Identifier>,
tsTools: TSTools | null,
messageId: string
): void {
if (call.arguments.length < 1) {
Expand All @@ -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 });
}
Expand All @@ -224,7 +232,8 @@ function checkShallowNavigationCall(
function isResolveCall(
ctx: FindVariableContext,
node: TSESTree.CallExpressionArgument,
resolveReferences: Set<TSESTree.Identifier>
resolveReferences: Set<TSESTree.Identifier>,
tsTools: TSTools | null
): boolean {
if (
node.type === 'CallExpression' &&
Expand All @@ -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 ||
Expand All @@ -248,6 +261,7 @@ function isResolveCall(
return false;
}
return isResolveCall(ctx, variable.identifiers[0].parent.init, resolveReferences);
*/
}

function expressionIsEmpty(url: TSESTree.CallExpressionArgument): boolean {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script lang="ts">
import { type ResolvedPathname } from '$app/types';
import { goto } from '$app/navigation';

interface Props {
href: ResolvedPathname;
}

const { href }: Props = $props();

goto(href);
</script>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<script>
<script lang="ts">
import { resolve } from '$app/paths';
import { goto } from '$app/navigation';

Expand Down
Loading