microsoft / microsoft/TypeScript

internal/ls: getContextNodeForNodeEntry returns nil for module-specifier literals (stock returns the enclosing import statement)

Open
#63,872 0 comments 0 reactions 1 assignee Claimed by @gabritto View on GitHub
Needs Investigation
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

Description

Stock's `getContextNodeForNodeEntry` ([src/services/findAllReferences.ts:338](https://github.com/microsoft/TypeScript/blob/v6.0.3/src/services/findAllReferences.ts#L338)) returns the enclosing import statement for a module-specifier string literal; tsgo returns nil. One visible effect: Go To Implementation on an import path returns a LocationLink whose target range is just the string literal instead of the whole import statement.

## Minimal repro

Run `go test ./internal/ls/ -run TestModuleSpecifierContextNode`:

```go
package ls

import (
"testing"

"github.com/microsoft/typescript-go/internal/ast"
"github.com/microsoft/typescript-go/internal/core"
"github.com/microsoft/typescript-go/internal/parser"
)

func TestModuleSpecifierContextNode(t *testing.T) {
t.Parallel()
text := "import { x } from \"./b\";\nx;\n"
sourceFile := parser.ParseSourceFile(ast.SourceFileParseOptions{
FileName: "/a.ts",
Path: "/a.ts",
}, text, core.ScriptKindTS)

var literal *ast.Node
for _, stmt := range sourceFile.Statements.Nodes {
if ast.IsImportDeclaration(stmt) {
literal = stmt.AsImportDeclaration().ModuleSpecifier
}
}
if literal == nil || literal.Kind != ast.KindStringLiteral {
t.Fatalf("module specifier literal not found: %v", literal)
}
if ctx := getContextNodeForNodeEntry(literal); ctx == nil {
t.Fatal("getContextNodeForNodeEntry(module specifier) = nil; want the enclosing import statement")
}
}
```

Fails with `getContextNodeForNodeEntry(module specifier) = nil` on a pristine checkout (v7.0.2, `2bd066d8`).

The string-literal special case diverges from stock's version ([findAllReferences.ts:371](https://github.com/microsoft/TypeScript/blob/v6.0.3/src/services/findAllReferences.ts#L371)): the case keys on `node.Parent.Kind` instead of the node itself, the `FindAncestor` predicate closes over the outer `node` instead of testing its parameter, and the outer gate's `IsDeclaration(ImportDeclaration)` is true in tsgo but false in stock. Same result for the other forms `TryGetImportFromModuleSpecifier` handles (`export … from`, `import()`/`require()`, …).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.