diff --git a/internal/fourslash/_scripts/convertFourslash.mts b/internal/fourslash/_scripts/convertFourslash.mts index c8e1d679bf..1863762cdd 100644 --- a/internal/fourslash/_scripts/convertFourslash.mts +++ b/internal/fourslash/_scripts/convertFourslash.mts @@ -86,13 +86,20 @@ function parseFileContent(filename: string, content: string): GoTest | undefined }; for (const statement of statements) { const result = parseFourslashStatement(statement); + if (result === SKIP_STATEMENT) { + // Skip this statement but continue parsing + continue; + } if (!result) { + // Could not parse this statement - mark file as unparsed unparsedFiles.push(filename); return undefined; } - else { - goTest.commands.push(...result); - } + goTest.commands.push(...result); + } + // Skip tests that have no commands (e.g., only syntactic classifications) + if (goTest.commands.length === 0) { + return undefined; } return goTest; } @@ -135,11 +142,22 @@ function getTestInput(content: string): string { return `\`${testInput.join("\n")}\``; } +// Sentinel value to indicate a statement should be skipped but parsing should continue +const SKIP_STATEMENT: unique symbol = Symbol("SKIP_STATEMENT"); +type SkipStatement = typeof SKIP_STATEMENT; + /** * Parses a Strada fourslash statement and returns the corresponding Corsa commands. - * @returns an array of commands if the statement is a valid fourslash command, or `undefined` if the statement could not be parsed. + * @returns an array of commands if the statement is a valid fourslash command, + * SKIP_STATEMENT if the statement should be skipped but parsing should continue, + * or `undefined` if the statement could not be parsed and the file should be marked as unparsed. */ -function parseFourslashStatement(statement: ts.Statement): Cmd[] | undefined { +function parseFourslashStatement(statement: ts.Statement): Cmd[] | SkipStatement | undefined { + // Skip empty statements (bare semicolons) + if (ts.isEmptyStatement(statement)) { + return SKIP_STATEMENT; + } + if (ts.isVariableStatement(statement)) { // variable declarations (for ranges and markers), e.g. `const range = test.ranges()[0];` return []; @@ -237,6 +255,10 @@ function parseFourslashStatement(statement: ts.Statement): Cmd[] | undefined { case "outliningSpansInCurrentFile": case "outliningHintSpansInCurrentFile": return parseOutliningSpansArgs(callExpression.arguments); + case "semanticClassificationsAre": + return parseSemanticClassificationsAre(callExpression.arguments); + case "syntacticClassificationsAre": + return SKIP_STATEMENT; } } // `goTo....` @@ -2084,6 +2106,71 @@ function parseOutliningSpansArgs(args: readonly ts.Expression[]): [VerifyOutlini }]; } +function parseSemanticClassificationsAre(args: readonly ts.Expression[]): [VerifySemanticClassificationsCmd] | SkipStatement | undefined { + if (args.length < 1) { + console.error("semanticClassificationsAre requires at least a format argument"); + return undefined; + } + + const formatArg = args[0]; + if (!ts.isStringLiteralLike(formatArg)) { + console.error("semanticClassificationsAre first argument must be a string literal"); + return undefined; + } + + const format = formatArg.text; + + // Only handle "2020" format for semantic tokens + if (format !== "2020") { + // Skip other formats like "original" - return sentinel to continue parsing + return SKIP_STATEMENT; + } + + const tokens: Array<{ type: string; text: string; }> = []; + + // Parse the classification tokens (c2.semanticToken("type", "text")) + for (let i = 1; i < args.length; i++) { + const arg = args[i]; + if (!ts.isCallExpression(arg)) { + console.error(`Expected call expression for token at index ${i}`); + return undefined; + } + + if (!ts.isPropertyAccessExpression(arg.expression) || arg.expression.name.text !== "semanticToken") { + console.error(`Expected semanticToken call at index ${i}`); + return undefined; + } + + if (arg.arguments.length < 2) { + console.error(`semanticToken requires 2 arguments at index ${i}`); + return undefined; + } + + const typeArg = arg.arguments[0]; + const textArg = arg.arguments[1]; + + if (!ts.isStringLiteralLike(typeArg) || !ts.isStringLiteralLike(textArg)) { + console.error(`semanticToken arguments must be string literals at index ${i}`); + return undefined; + } + + // Map TypeScript's internal "member" type to LSP's "method" type + let tokenType = typeArg.text; + tokenType = tokenType.replace(/\bmember\b/g, "method"); + + tokens.push({ + type: tokenType, + text: textArg.text, + }); + } + + return [{ + kind: "verifySemanticClassifications", + format, + tokens, + }]; +} + function parseKind(expr: ts.Expression): string | undefined { if (!ts.isStringLiteral(expr)) { console.error(`Expected string literal for kind, got ${expr.getText()}`); @@ -2567,6 +2654,12 @@ interface VerifyOutliningSpansCmd { foldingRangeKind?: string; } +interface VerifySemanticClassificationsCmd { + kind: "verifySemanticClassifications"; + format: string; + tokens: Array<{ type: string; text: string; }>; +} + type Cmd = | VerifyCompletionsCmd | VerifyApplyCodeActionFromCompletionCmd @@ -2591,6 +2684,7 @@ type Cmd = | VerifyImportFixAtPositionCmd | VerifyDiagnosticsCmd | VerifyBaselineDiagnosticsCmd + | VerifySemanticClassificationsCmd | VerifyOutliningSpansCmd; function generateVerifyOutliningSpans({ foldingRangeKind }: VerifyOutliningSpansCmd): string { @@ -2834,6 +2928,14 @@ function generateNavigateTo({ args }: VerifyNavToCmd): string { return `f.VerifyWorkspaceSymbol(t, []*fourslash.VerifyWorkspaceSymbolCase{\n${args.join(", ")}})`; } +function generateSemanticClassifications({ format, tokens }: VerifySemanticClassificationsCmd): string { + const tokensStr = tokens.map(t => `{Type: ${getGoStringLiteral(t.type)}, Text: ${getGoStringLiteral(t.text)}}`).join(",\n\t\t"); + const maybeComma = tokens.length > 0 ? "," : ""; + return `f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + ${tokensStr}${maybeComma} + })`; +} + function generateCmd(cmd: Cmd): string { switch (cmd.kind) { case "verifyCompletions": @@ -2894,6 +2996,8 @@ function generateCmd(cmd: Cmd): string { return generateNoSignatureHelpForTriggerReason(cmd); case "verifyOutliningSpans": return generateVerifyOutliningSpans(cmd); + case "verifySemanticClassifications": + return generateSemanticClassifications(cmd); default: let neverCommand: never = cmd; throw new Error(`Unknown command kind: ${neverCommand as Cmd["kind"]}`); diff --git a/internal/fourslash/_scripts/manualTests.txt b/internal/fourslash/_scripts/manualTests.txt index c86bec5d29..c319399044 100644 --- a/internal/fourslash/_scripts/manualTests.txt +++ b/internal/fourslash/_scripts/manualTests.txt @@ -12,6 +12,7 @@ parserCorruptionAfterMapInClass quickInfoForOverloadOnConst1 renameDefaultKeyword renameForDefaultExport01 +semanticModernClassificationFunctions tsxCompletion12 jsDocFunctionSignatures2 jsDocFunctionSignatures12 diff --git a/internal/fourslash/fourslash.go b/internal/fourslash/fourslash.go index b9e223b88d..089ff441de 100644 --- a/internal/fourslash/fourslash.go +++ b/internal/fourslash/fourslash.go @@ -69,6 +69,10 @@ type FourslashTest struct { // Async message handling pendingRequests map[lsproto.ID]chan *lsproto.ResponseMessage pendingRequestsMu sync.Mutex + + // Semantic token configuration + semanticTokenTypes []string + semanticTokenModifiers []string } type scriptInfo struct { @@ -228,17 +232,19 @@ func NewFourslash(t *testing.T, capabilities *lsproto.ClientCapabilities, conten }) f := &FourslashTest{ - server: server, - in: inputWriter, - out: outputReader, - testData: &testData, - userPreferences: lsutil.NewDefaultUserPreferences(), // !!! parse default preferences for fourslash case? - vfs: fs, - scriptInfos: scriptInfos, - converters: converters, - baselines: make(map[baselineCommand]*strings.Builder), - openFiles: make(map[string]struct{}), - pendingRequests: make(map[lsproto.ID]chan *lsproto.ResponseMessage), + server: server, + in: inputWriter, + out: outputReader, + testData: &testData, + userPreferences: lsutil.NewDefaultUserPreferences(), // !!! parse default preferences for fourslash case? + vfs: fs, + scriptInfos: scriptInfos, + converters: converters, + baselines: make(map[baselineCommand]*strings.Builder), + openFiles: make(map[string]struct{}), + pendingRequests: make(map[lsproto.ID]chan *lsproto.ResponseMessage), + semanticTokenTypes: defaultSemanticTokenTypes(), + semanticTokenModifiers: defaultSemanticTokenModifiers(), } ctx, cancel := context.WithCancel(t.Context()) @@ -452,6 +458,50 @@ func (f *FourslashTest) initialize(t *testing.T, capabilities *lsproto.ClientCap <-f.server.InitComplete() } +func defaultSemanticTokenTypes() []string { + return []string{ + string(lsproto.SemanticTokenTypeNamespace), + string(lsproto.SemanticTokenTypeClass), + string(lsproto.SemanticTokenTypeEnum), + string(lsproto.SemanticTokenTypeInterface), + string(lsproto.SemanticTokenTypeStruct), + string(lsproto.SemanticTokenTypeTypeParameter), + string(lsproto.SemanticTokenTypeType), + string(lsproto.SemanticTokenTypeParameter), + string(lsproto.SemanticTokenTypeVariable), + string(lsproto.SemanticTokenTypeProperty), + string(lsproto.SemanticTokenTypeEnumMember), + string(lsproto.SemanticTokenTypeDecorator), + string(lsproto.SemanticTokenTypeEvent), + string(lsproto.SemanticTokenTypeFunction), + string(lsproto.SemanticTokenTypeMethod), + string(lsproto.SemanticTokenTypeMacro), + string(lsproto.SemanticTokenTypeLabel), + string(lsproto.SemanticTokenTypeComment), + string(lsproto.SemanticTokenTypeString), + string(lsproto.SemanticTokenTypeKeyword), + string(lsproto.SemanticTokenTypeNumber), + string(lsproto.SemanticTokenTypeRegexp), + string(lsproto.SemanticTokenTypeOperator), + } +} + +func defaultSemanticTokenModifiers() []string { + return []string{ + string(lsproto.SemanticTokenModifierDeclaration), + string(lsproto.SemanticTokenModifierDefinition), + string(lsproto.SemanticTokenModifierReadonly), + string(lsproto.SemanticTokenModifierStatic), + string(lsproto.SemanticTokenModifierDeprecated), + string(lsproto.SemanticTokenModifierAbstract), + string(lsproto.SemanticTokenModifierAsync), + string(lsproto.SemanticTokenModifierModification), + string(lsproto.SemanticTokenModifierDocumentation), + string(lsproto.SemanticTokenModifierDefaultLibrary), + "local", + } +} + var ( ptrTrue = ptrTo(true) defaultCompletionCapabilities = &lsproto.CompletionClientCapabilities{ @@ -517,6 +567,18 @@ func getCapabilitiesWithDefaults(capabilities *lsproto.ClientCapabilities) *lspr }, } } + if capabilitiesWithDefaults.TextDocument.SemanticTokens == nil { + capabilitiesWithDefaults.TextDocument.SemanticTokens = &lsproto.SemanticTokensClientCapabilities{ + Requests: &lsproto.ClientSemanticTokensRequestOptions{ + Full: &lsproto.BooleanOrClientSemanticTokensRequestFullDelta{ + Boolean: ptrTrue, + }, + }, + TokenTypes: defaultSemanticTokenTypes(), + TokenModifiers: defaultSemanticTokenModifiers(), + Formats: []lsproto.TokenFormat{lsproto.TokenFormatRelative}, + } + } if capabilitiesWithDefaults.Workspace == nil { capabilitiesWithDefaults.Workspace = &lsproto.WorkspaceClientCapabilities{} } diff --git a/internal/fourslash/semantictokens.go b/internal/fourslash/semantictokens.go new file mode 100644 index 0000000000..bb69d03682 --- /dev/null +++ b/internal/fourslash/semantictokens.go @@ -0,0 +1,130 @@ +package fourslash + +import ( + "fmt" + "strings" + "testing" + + "github.com/microsoft/typescript-go/internal/ls/lsconv" + "github.com/microsoft/typescript-go/internal/lsp/lsproto" +) + +type SemanticToken struct { + Type string + Text string +} + +func (f *FourslashTest) VerifySemanticTokens(t *testing.T, expected []SemanticToken) { + t.Helper() + + params := &lsproto.SemanticTokensParams{ + TextDocument: lsproto.TextDocumentIdentifier{ + Uri: lsconv.FileNameToDocumentURI(f.activeFilename), + }, + } + + result := sendRequest(t, f, lsproto.TextDocumentSemanticTokensFullInfo, params) + + if result.SemanticTokens == nil { + if len(expected) == 0 { + return + } + t.Fatal("Expected semantic tokens but got nil") + } + + // Decode the semantic tokens using token types/modifiers from the test configuration + actual := decodeSemanticTokens(f, result.SemanticTokens.Data, f.semanticTokenTypes, f.semanticTokenModifiers) + + // Compare with expected + if len(actual) != len(expected) { + t.Fatalf("Expected %d semantic tokens, got %d\n\nExpected:\n%s\n\nActual:\n%s", + len(expected), len(actual), + formatSemanticTokens(expected), + formatSemanticTokens(actual)) + } + + for i, exp := range expected { + act := actual[i] + if exp.Type != act.Type || exp.Text != act.Text { + t.Errorf("Token %d mismatch:\n Expected: {Type: %q, Text: %q}\n Actual: {Type: %q, Text: %q}", + i, exp.Type, exp.Text, act.Type, act.Text) + } + } +} + +func decodeSemanticTokens(f *FourslashTest, data []uint32, tokenTypes, tokenModifiers []string) []SemanticToken { + if len(data)%5 != 0 { + panic(fmt.Sprintf("Invalid semantic tokens data length: %d", len(data))) + } + + scriptInfo := f.scriptInfos[f.activeFilename] + converters := lsconv.NewConverters(lsproto.PositionEncodingKindUTF8, func(_ string) *lsconv.LSPLineMap { + return scriptInfo.lineMap + }) + + var tokens []SemanticToken + prevLine := uint32(0) + prevChar := uint32(0) + + for i := 0; i < len(data); i += 5 { + deltaLine := data[i] + deltaChar := data[i+1] + length := data[i+2] + tokenTypeIdx := data[i+3] + tokenModifierMask := data[i+4] + + // Calculate absolute position + line := prevLine + deltaLine + var char uint32 + if deltaLine == 0 { + char = prevChar + deltaChar + } else { + char = deltaChar + } + + // Get token type + if int(tokenTypeIdx) >= len(tokenTypes) { + panic(fmt.Sprintf("Token type index out of range: %d", tokenTypeIdx)) + } + tokenType := tokenTypes[tokenTypeIdx] + + // Get modifiers + var modifiers []string + for i, mod := range tokenModifiers { + if tokenModifierMask&(1< 0 { + typeStr = typeStr + "." + strings.Join(modifiers, ".") + } + + // Get the text + startPos := lsproto.Position{Line: line, Character: char} + endPos := lsproto.Position{Line: line, Character: char + length} + startOffset := int(converters.LineAndCharacterToPosition(scriptInfo, startPos)) + endOffset := int(converters.LineAndCharacterToPosition(scriptInfo, endPos)) + text := scriptInfo.content[startOffset:endOffset] + + tokens = append(tokens, SemanticToken{ + Type: typeStr, + Text: text, + }) + + prevLine = line + prevChar = char + } + + return tokens +} + +func formatSemanticTokens(tokens []SemanticToken) string { + var lines []string + for i, tok := range tokens { + lines = append(lines, fmt.Sprintf(" [%d] {Type: %q, Text: %q}", i, tok.Type, tok.Text)) + } + return strings.Join(lines, "\n") +} diff --git a/internal/fourslash/tests/gen/incrementalJsDocAdjustsLengthsRight_test.go b/internal/fourslash/tests/gen/incrementalJsDocAdjustsLengthsRight_test.go new file mode 100644 index 0000000000..b8c56f2b3d --- /dev/null +++ b/internal/fourslash/tests/gen/incrementalJsDocAdjustsLengthsRight_test.go @@ -0,0 +1,25 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestIncrementalJsDocAdjustsLengthsRight(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @noLib: true + +/** + * Pad ` + "`" + `str` + "`" + ` to ` + "`" + `width` + "`" + `. + * + * @param {String} str + * @param {Number} wid/*1*/` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.GoToMarker(t, "1") + f.Insert(t, "th\n@") +} diff --git a/internal/fourslash/tests/gen/renameDefaultImport_test.go b/internal/fourslash/tests/gen/renameDefaultImport_test.go new file mode 100644 index 0000000000..48c89a009d --- /dev/null +++ b/internal/fourslash/tests/gen/renameDefaultImport_test.go @@ -0,0 +1,28 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestRenameDefaultImport(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @Filename: B.ts +[|export default class /*1*/[|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 0 |}B|] { + test() { + } +}|] +// @Filename: A.ts +[|import /*2*/[|{| "isWriteAccess": true, "isDefinition": true, "contextRangeIndex": 2 |}B|] from "./B";|] +let b = new [|B|](); +b.test();` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyBaselineFindAllReferences(t, "1", "2") + f.VerifyBaselineRename(t, nil /*preferences*/, f.Ranges()[1], f.Ranges()[3], f.Ranges()[4]) + f.VerifyBaselineDocumentHighlights(t, nil /*preferences*/, "1") +} diff --git a/internal/fourslash/tests/gen/semanticClassification1_test.go b/internal/fourslash/tests/gen/semanticClassification1_test.go new file mode 100644 index 0000000000..62f1400620 --- /dev/null +++ b/internal/fourslash/tests/gen/semanticClassification1_test.go @@ -0,0 +1,28 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticClassification1(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `module /*0*/M { + export interface /*1*/I { + } +} +interface /*2*/X extends /*3*/M./*4*/I { }` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "namespace.declaration", Text: "M"}, + {Type: "interface.declaration", Text: "I"}, + {Type: "interface.declaration", Text: "X"}, + {Type: "namespace", Text: "M"}, + {Type: "interface", Text: "I"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticClassification2_test.go b/internal/fourslash/tests/gen/semanticClassification2_test.go new file mode 100644 index 0000000000..f234de1f9e --- /dev/null +++ b/internal/fourslash/tests/gen/semanticClassification2_test.go @@ -0,0 +1,29 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticClassification2(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `interface /*0*/Thing { + toExponential(): number; +} + +var Thing = 0; +Thing.toExponential();` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "interface.declaration", Text: "Thing"}, + {Type: "method.declaration", Text: "toExponential"}, + {Type: "variable.declaration", Text: "Thing"}, + {Type: "variable", Text: "Thing"}, + {Type: "method.defaultLibrary", Text: "toExponential"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticClassificationAlias_test.go b/internal/fourslash/tests/gen/semanticClassificationAlias_test.go new file mode 100644 index 0000000000..1c456e5061 --- /dev/null +++ b/internal/fourslash/tests/gen/semanticClassificationAlias_test.go @@ -0,0 +1,28 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticClassificationAlias(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @Filename: /a.ts +export type x = number; +export class y {}; +// @Filename: /b.ts +import { /*0*/x, /*1*/y } from "./a"; +const v: /*2*/x = /*3*/y;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.GoToFile(t, "/b.ts") + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "variable.declaration.readonly", Text: "v"}, + {Type: "type", Text: "x"}, + {Type: "class", Text: "y"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticClassificationClassExpression_test.go b/internal/fourslash/tests/gen/semanticClassificationClassExpression_test.go new file mode 100644 index 0000000000..dfbec34356 --- /dev/null +++ b/internal/fourslash/tests/gen/semanticClassificationClassExpression_test.go @@ -0,0 +1,26 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticClassificationClassExpression(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `var x = class /*0*/C {} +class /*1*/C {} +class /*2*/D extends class /*3*/B{} { }` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "class.declaration", Text: "x"}, + {Type: "class", Text: "C"}, + {Type: "class.declaration", Text: "C"}, + {Type: "class.declaration", Text: "D"}, + {Type: "class", Text: "B"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticClassificationInTemplateExpressions_test.go b/internal/fourslash/tests/gen/semanticClassificationInTemplateExpressions_test.go new file mode 100644 index 0000000000..7fb58dcb71 --- /dev/null +++ b/internal/fourslash/tests/gen/semanticClassificationInTemplateExpressions_test.go @@ -0,0 +1,38 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticClassificationInTemplateExpressions(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `module /*0*/M { + export class /*1*/C { + static x; + } + export enum /*2*/E { + E1 = 0 + } +} +` + "`" + `abcd${ /*3*/M./*4*/C.x + /*5*/M./*6*/E.E1}efg` + "`" + `` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "namespace.declaration", Text: "M"}, + {Type: "class.declaration", Text: "C"}, + {Type: "property.declaration.static", Text: "x"}, + {Type: "enum.declaration", Text: "E"}, + {Type: "enumMember.declaration.readonly", Text: "E1"}, + {Type: "namespace", Text: "M"}, + {Type: "class", Text: "C"}, + {Type: "property.static", Text: "x"}, + {Type: "namespace", Text: "M"}, + {Type: "enum", Text: "E"}, + {Type: "enumMember.readonly", Text: "E1"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticClassificationInstantiatedModuleWithVariableOfSameName1_test.go b/internal/fourslash/tests/gen/semanticClassificationInstantiatedModuleWithVariableOfSameName1_test.go new file mode 100644 index 0000000000..0f1fb3b8e3 --- /dev/null +++ b/internal/fourslash/tests/gen/semanticClassificationInstantiatedModuleWithVariableOfSameName1_test.go @@ -0,0 +1,43 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticClassificationInstantiatedModuleWithVariableOfSameName1(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `module /*0*/M { + export interface /*1*/I { + } + var x = 10; +} + +var /*2*/M = { + foo: 10, + bar: 20 +} + +var v: /*3*/M./*4*/I; + +var x = /*5*/M;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "namespace.declaration", Text: "M"}, + {Type: "interface.declaration", Text: "I"}, + {Type: "variable.declaration.local", Text: "x"}, + {Type: "variable.declaration", Text: "M"}, + {Type: "property.declaration", Text: "foo"}, + {Type: "property.declaration", Text: "bar"}, + {Type: "variable.declaration", Text: "v"}, + {Type: "namespace", Text: "M"}, + {Type: "interface", Text: "I"}, + {Type: "variable.declaration", Text: "x"}, + {Type: "namespace", Text: "M"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticClassificationInstantiatedModuleWithVariableOfSameName2_test.go b/internal/fourslash/tests/gen/semanticClassificationInstantiatedModuleWithVariableOfSameName2_test.go new file mode 100644 index 0000000000..469e967535 --- /dev/null +++ b/internal/fourslash/tests/gen/semanticClassificationInstantiatedModuleWithVariableOfSameName2_test.go @@ -0,0 +1,47 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticClassificationInstantiatedModuleWithVariableOfSameName2(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `module /*0*/M { + export interface /*1*/I { + } +} + +module /*2*/M { + var x = 10; +} + +var /*3*/M = { + foo: 10, + bar: 20 +} + +var v: /*4*/M./*5*/I; + +var x = /*6*/M;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "namespace.declaration", Text: "M"}, + {Type: "interface.declaration", Text: "I"}, + {Type: "namespace.declaration", Text: "M"}, + {Type: "variable.declaration.local", Text: "x"}, + {Type: "variable.declaration", Text: "M"}, + {Type: "property.declaration", Text: "foo"}, + {Type: "property.declaration", Text: "bar"}, + {Type: "variable.declaration", Text: "v"}, + {Type: "namespace", Text: "M"}, + {Type: "interface", Text: "I"}, + {Type: "variable.declaration", Text: "x"}, + {Type: "namespace", Text: "M"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticClassificationModules_test.go b/internal/fourslash/tests/gen/semanticClassificationModules_test.go new file mode 100644 index 0000000000..7092a35c18 --- /dev/null +++ b/internal/fourslash/tests/gen/semanticClassificationModules_test.go @@ -0,0 +1,36 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticClassificationModules(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `module /*0*/M { + export var v; + export interface /*1*/I { + } +} + +var x: /*2*/M./*3*/I = /*4*/M.v; +var y = /*5*/M;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "namespace.declaration", Text: "M"}, + {Type: "variable.declaration.local", Text: "v"}, + {Type: "interface.declaration", Text: "I"}, + {Type: "variable.declaration", Text: "x"}, + {Type: "namespace", Text: "M"}, + {Type: "interface", Text: "I"}, + {Type: "namespace", Text: "M"}, + {Type: "variable.local", Text: "v"}, + {Type: "variable.declaration", Text: "y"}, + {Type: "namespace", Text: "M"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticClassificationUninstantiatedModuleWithVariableOfSameName1_test.go b/internal/fourslash/tests/gen/semanticClassificationUninstantiatedModuleWithVariableOfSameName1_test.go new file mode 100644 index 0000000000..1684f3acf2 --- /dev/null +++ b/internal/fourslash/tests/gen/semanticClassificationUninstantiatedModuleWithVariableOfSameName1_test.go @@ -0,0 +1,29 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticClassificationUninstantiatedModuleWithVariableOfSameName1(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `declare module /*0*/M { + interface /*1*/I { + + } +} + +var M = { I: 10 };` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "variable", Text: "M"}, + {Type: "interface.declaration", Text: "I"}, + {Type: "variable.declaration", Text: "M"}, + {Type: "property.declaration", Text: "I"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticClassificationUninstantiatedModuleWithVariableOfSameName2_test.go b/internal/fourslash/tests/gen/semanticClassificationUninstantiatedModuleWithVariableOfSameName2_test.go new file mode 100644 index 0000000000..fe780f2699 --- /dev/null +++ b/internal/fourslash/tests/gen/semanticClassificationUninstantiatedModuleWithVariableOfSameName2_test.go @@ -0,0 +1,41 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticClassificationUninstantiatedModuleWithVariableOfSameName2(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `module /*0*/M { + export interface /*1*/I { + } +} + +var /*2*/M = { + foo: 10, + bar: 20 +} + +var v: /*3*/M./*4*/I; + +var x = /*5*/M;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "variable", Text: "M"}, + {Type: "interface.declaration", Text: "I"}, + {Type: "variable.declaration", Text: "M"}, + {Type: "property.declaration", Text: "foo"}, + {Type: "property.declaration", Text: "bar"}, + {Type: "variable.declaration", Text: "v"}, + {Type: "variable", Text: "M"}, + {Type: "interface", Text: "I"}, + {Type: "variable.declaration", Text: "x"}, + {Type: "variable", Text: "M"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticClassificationWithUnionTypes_test.go b/internal/fourslash/tests/gen/semanticClassificationWithUnionTypes_test.go new file mode 100644 index 0000000000..fad3f93a75 --- /dev/null +++ b/internal/fourslash/tests/gen/semanticClassificationWithUnionTypes_test.go @@ -0,0 +1,42 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticClassificationWithUnionTypes(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `module /*0*/M { + export interface /*1*/I { + } +} + +interface /*2*/I { +} +class /*3*/C { +} + +var M: /*4*/M./*5*/I | /*6*/I | /*7*/C; +var I: typeof M | typeof /*8*/C;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "variable", Text: "M"}, + {Type: "interface.declaration", Text: "I"}, + {Type: "interface.declaration", Text: "I"}, + {Type: "class.declaration", Text: "C"}, + {Type: "variable.declaration", Text: "M"}, + {Type: "variable", Text: "M"}, + {Type: "interface", Text: "I"}, + {Type: "interface", Text: "I"}, + {Type: "class", Text: "C"}, + {Type: "class.declaration", Text: "I"}, + {Type: "variable", Text: "M"}, + {Type: "class", Text: "C"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticClassificatonTypeAlias_test.go b/internal/fourslash/tests/gen/semanticClassificatonTypeAlias_test.go new file mode 100644 index 0000000000..126103f2f3 --- /dev/null +++ b/internal/fourslash/tests/gen/semanticClassificatonTypeAlias_test.go @@ -0,0 +1,31 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticClassificatonTypeAlias(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `type /*0*/Alias = number +var x: /*1*/Alias; +var y = {}; +function f(x: /*3*/Alias): /*4*/Alias { return undefined; }` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "type.declaration", Text: "Alias"}, + {Type: "variable.declaration", Text: "x"}, + {Type: "type", Text: "Alias"}, + {Type: "variable.declaration", Text: "y"}, + {Type: "type", Text: "Alias"}, + {Type: "function.declaration", Text: "f"}, + {Type: "parameter.declaration", Text: "x"}, + {Type: "type", Text: "Alias"}, + {Type: "type", Text: "Alias"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticModernClassificationCallableVariables2_test.go b/internal/fourslash/tests/gen/semanticModernClassificationCallableVariables2_test.go new file mode 100644 index 0000000000..b34f95b45d --- /dev/null +++ b/internal/fourslash/tests/gen/semanticModernClassificationCallableVariables2_test.go @@ -0,0 +1,39 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticModernClassificationCallableVariables2(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `import "node"; +var fs = require("fs") +require.resolve('react'); +require.resolve.paths; +interface LanguageMode { getFoldingRanges?: (d: string) => number[]; }; +function (mode: LanguageMode | undefined) { if (mode && mode.getFoldingRanges) { return mode.getFoldingRanges('a'); }}; +function b(a: () => void) { a(); };` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "variable.declaration", Text: "fs"}, + {Type: "interface.declaration", Text: "LanguageMode"}, + {Type: "method.declaration", Text: "getFoldingRanges"}, + {Type: "parameter.declaration", Text: "d"}, + {Type: "parameter.declaration", Text: "mode"}, + {Type: "interface", Text: "LanguageMode"}, + {Type: "parameter", Text: "mode"}, + {Type: "parameter", Text: "mode"}, + {Type: "method", Text: "getFoldingRanges"}, + {Type: "parameter", Text: "mode"}, + {Type: "method", Text: "getFoldingRanges"}, + {Type: "function.declaration", Text: "b"}, + {Type: "function.declaration", Text: "a"}, + {Type: "function", Text: "a"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticModernClassificationCallableVariables_test.go b/internal/fourslash/tests/gen/semanticModernClassificationCallableVariables_test.go new file mode 100644 index 0000000000..1bf378905c --- /dev/null +++ b/internal/fourslash/tests/gen/semanticModernClassificationCallableVariables_test.go @@ -0,0 +1,45 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticModernClassificationCallableVariables(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `class A { onEvent: () => void; } +const x = new A().onEvent; +const match = (s: any) => x(); +const other = match; +match({ other }); +interface B = { (): string; }; var b: B +var s: String; +var t: { (): string; foo: string};` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "class.declaration", Text: "A"}, + {Type: "method.declaration", Text: "onEvent"}, + {Type: "function.declaration.readonly", Text: "x"}, + {Type: "class", Text: "A"}, + {Type: "method", Text: "onEvent"}, + {Type: "function.declaration.readonly", Text: "match"}, + {Type: "parameter.declaration", Text: "s"}, + {Type: "function.readonly", Text: "x"}, + {Type: "function.declaration.readonly", Text: "other"}, + {Type: "function.readonly", Text: "match"}, + {Type: "function.readonly", Text: "match"}, + {Type: "method.declaration", Text: "other"}, + {Type: "interface.declaration", Text: "B"}, + {Type: "variable.declaration", Text: "b"}, + {Type: "interface", Text: "B"}, + {Type: "variable.declaration", Text: "s"}, + {Type: "interface.defaultLibrary", Text: "String"}, + {Type: "variable.declaration", Text: "t"}, + {Type: "property.declaration", Text: "foo"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticModernClassificationClassProperties_test.go b/internal/fourslash/tests/gen/semanticModernClassificationClassProperties_test.go new file mode 100644 index 0000000000..66e1d798a9 --- /dev/null +++ b/internal/fourslash/tests/gen/semanticModernClassificationClassProperties_test.go @@ -0,0 +1,35 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticModernClassificationClassProperties(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `class A { + private y: number; + constructor(public x : number, _y : number) { this.y = _y; } + get z() : number { return this.x + this.y; } + set a(v: number) { } +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "class.declaration", Text: "A"}, + {Type: "property.declaration", Text: "y"}, + {Type: "parameter.declaration", Text: "x"}, + {Type: "parameter.declaration", Text: "_y"}, + {Type: "property", Text: "y"}, + {Type: "parameter", Text: "_y"}, + {Type: "property.declaration", Text: "z"}, + {Type: "property", Text: "x"}, + {Type: "property", Text: "y"}, + {Type: "property.declaration", Text: "a"}, + {Type: "parameter.declaration", Text: "v"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticModernClassificationConstructorTypes_test.go b/internal/fourslash/tests/gen/semanticModernClassificationConstructorTypes_test.go new file mode 100644 index 0000000000..3e14ff408c --- /dev/null +++ b/internal/fourslash/tests/gen/semanticModernClassificationConstructorTypes_test.go @@ -0,0 +1,27 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticModernClassificationConstructorTypes(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `Object.create(null); +const x = Promise.resolve(Number.MAX_VALUE); +if (x instanceof Promise) {}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "class.defaultLibrary", Text: "Object"}, + {Type: "method.defaultLibrary", Text: "create"}, + {Type: "variable.declaration.readonly", Text: "x"}, + {Type: "class.defaultLibrary", Text: "Number"}, + {Type: "property.readonly.defaultLibrary", Text: "MAX_VALUE"}, + {Type: "variable.readonly", Text: "x"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticModernClassificationInfinityAndNaN_test.go b/internal/fourslash/tests/gen/semanticModernClassificationInfinityAndNaN_test.go new file mode 100644 index 0000000000..5592cb7a77 --- /dev/null +++ b/internal/fourslash/tests/gen/semanticModernClassificationInfinityAndNaN_test.go @@ -0,0 +1,49 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticModernClassificationInfinityAndNaN(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = ` Infinity; + NaN; + +// Regular properties + +const obj1 = { + Infinity: 100, + NaN: 200, + "-Infinity": 300 +}; + +obj1.Infinity; +obj1.NaN; +obj1["-Infinity"]; + +// Shorthand properties + +const obj2 = { + Infinity, + NaN, +} + +obj2.Infinity; +obj2.NaN;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "variable.declaration.readonly", Text: "obj1"}, + {Type: "variable.readonly", Text: "obj1"}, + {Type: "variable.readonly", Text: "obj1"}, + {Type: "variable.readonly", Text: "obj1"}, + {Type: "variable.declaration.readonly", Text: "obj2"}, + {Type: "variable.readonly", Text: "obj2"}, + {Type: "variable.readonly", Text: "obj2"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticModernClassificationInterfaces_test.go b/internal/fourslash/tests/gen/semanticModernClassificationInterfaces_test.go new file mode 100644 index 0000000000..60ccb399f4 --- /dev/null +++ b/internal/fourslash/tests/gen/semanticModernClassificationInterfaces_test.go @@ -0,0 +1,35 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticModernClassificationInterfaces(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `interface Pos { x: number, y: number }; +const p = { x: 1, y: 2 } as Pos; +const foo = (o: Pos) => o.x + o.y;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "interface.declaration", Text: "Pos"}, + {Type: "property.declaration", Text: "x"}, + {Type: "property.declaration", Text: "y"}, + {Type: "variable.declaration.readonly", Text: "p"}, + {Type: "property.declaration", Text: "x"}, + {Type: "property.declaration", Text: "y"}, + {Type: "interface", Text: "Pos"}, + {Type: "function.declaration.readonly", Text: "foo"}, + {Type: "parameter.declaration", Text: "o"}, + {Type: "interface", Text: "Pos"}, + {Type: "parameter", Text: "o"}, + {Type: "property", Text: "x"}, + {Type: "parameter", Text: "o"}, + {Type: "property", Text: "y"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticModernClassificationMembers_test.go b/internal/fourslash/tests/gen/semanticModernClassificationMembers_test.go new file mode 100644 index 0000000000..8718308366 --- /dev/null +++ b/internal/fourslash/tests/gen/semanticModernClassificationMembers_test.go @@ -0,0 +1,38 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticModernClassificationMembers(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `class A { + static x = 9; + f = 9; + async m() { return A.x + await this.m(); }; + get s() { return this.f; + static t() { return new A().f; }; + constructor() {} +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "class.declaration", Text: "A"}, + {Type: "property.declaration.static", Text: "x"}, + {Type: "property.declaration", Text: "f"}, + {Type: "method.declaration.async", Text: "m"}, + {Type: "class", Text: "A"}, + {Type: "property.static", Text: "x"}, + {Type: "method.async", Text: "m"}, + {Type: "property.declaration", Text: "s"}, + {Type: "property", Text: "f"}, + {Type: "method.declaration.static", Text: "t"}, + {Type: "class", Text: "A"}, + {Type: "property", Text: "f"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticModernClassificationObjectProperties_test.go b/internal/fourslash/tests/gen/semanticModernClassificationObjectProperties_test.go new file mode 100644 index 0000000000..ef23980226 --- /dev/null +++ b/internal/fourslash/tests/gen/semanticModernClassificationObjectProperties_test.go @@ -0,0 +1,27 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticModernClassificationObjectProperties(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `let x = 1, y = 1; +const a1 = { e: 1 }; +var a2 = { x };` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "variable.declaration", Text: "x"}, + {Type: "variable.declaration", Text: "y"}, + {Type: "variable.declaration.readonly", Text: "a1"}, + {Type: "property.declaration", Text: "e"}, + {Type: "variable.declaration", Text: "a2"}, + {Type: "property.declaration", Text: "x"}, + }) +} diff --git a/internal/fourslash/tests/gen/semanticModernClassificationVariables_test.go b/internal/fourslash/tests/gen/semanticModernClassificationVariables_test.go new file mode 100644 index 0000000000..330c34f2a1 --- /dev/null +++ b/internal/fourslash/tests/gen/semanticModernClassificationVariables_test.go @@ -0,0 +1,33 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticModernClassificationVariables(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = ` var x = 9, y1 = [x]; + try { + for (const s of y1) { x = s } + } catch (e) { + throw y1; + }` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "variable.declaration", Text: "x"}, + {Type: "variable.declaration", Text: "y1"}, + {Type: "variable", Text: "x"}, + {Type: "variable.declaration.readonly.local", Text: "s"}, + {Type: "variable", Text: "y1"}, + {Type: "variable", Text: "x"}, + {Type: "variable.readonly.local", Text: "s"}, + {Type: "variable.declaration.local", Text: "e"}, + {Type: "variable", Text: "y1"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationForJSDocTemplateTag_test.go b/internal/fourslash/tests/gen/syntacticClassificationForJSDocTemplateTag_test.go new file mode 100644 index 0000000000..ffa389989c --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationForJSDocTemplateTag_test.go @@ -0,0 +1,24 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationForJSDocTemplateTag(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `/** @template T baring strait */ +function ident: T { +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "function.declaration", Text: "ident"}, + {Type: "typeParameter.declaration", Text: "T"}, + {Type: "typeParameter", Text: "T"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationWithErrors_test.go b/internal/fourslash/tests/gen/syntacticClassificationWithErrors_test.go new file mode 100644 index 0000000000..653754a8db --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationWithErrors_test.go @@ -0,0 +1,24 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationWithErrors(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `class A { + a: +} +c =` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "class.declaration", Text: "A"}, + {Type: "property.declaration", Text: "a"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassifications1_test.go b/internal/fourslash/tests/gen/syntacticClassifications1_test.go new file mode 100644 index 0000000000..fa6103955e --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassifications1_test.go @@ -0,0 +1,44 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassifications1(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// comment +module M { + var v = 0 + 1; + var s = "string"; + + class C { + } + + enum E { + } + + interface I { + } + + module M1.M2 { + } +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "namespace.declaration", Text: "M"}, + {Type: "variable.declaration.local", Text: "v"}, + {Type: "variable.declaration.local", Text: "s"}, + {Type: "class.declaration", Text: "C"}, + {Type: "typeParameter.declaration", Text: "T"}, + {Type: "enum.declaration", Text: "E"}, + {Type: "interface.declaration", Text: "I"}, + {Type: "namespace.declaration", Text: "M1"}, + {Type: "namespace.declaration", Text: "M2"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationsConflictDiff3Markers1_test.go b/internal/fourslash/tests/gen/syntacticClassificationsConflictDiff3Markers1_test.go new file mode 100644 index 0000000000..db4c7ecaf3 --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationsConflictDiff3Markers1_test.go @@ -0,0 +1,29 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationsConflictDiff3Markers1(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `class C { +<<<<<<< HEAD + v = 1; +||||||| merged common ancestors + v = 3; +======= + v = 2; +>>>>>>> Branch - a +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "class.declaration", Text: "C"}, + {Type: "property.declaration", Text: "v"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationsConflictDiff3Markers2_test.go b/internal/fourslash/tests/gen/syntacticClassificationsConflictDiff3Markers2_test.go new file mode 100644 index 0000000000..422796556a --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationsConflictDiff3Markers2_test.go @@ -0,0 +1,26 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationsConflictDiff3Markers2(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `<<<<<<< HEAD +class C { } +||||||| merged common ancestors +class E { } +======= +class D { } +>>>>>>> Branch - a` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "class.declaration", Text: "C"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationsConflictMarkers1_test.go b/internal/fourslash/tests/gen/syntacticClassificationsConflictMarkers1_test.go new file mode 100644 index 0000000000..f3a719254b --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationsConflictMarkers1_test.go @@ -0,0 +1,27 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationsConflictMarkers1(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `class C { +<<<<<<< HEAD + v = 1; +======= + v = 2; +>>>>>>> Branch - a +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "class.declaration", Text: "C"}, + {Type: "property.declaration", Text: "v"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationsConflictMarkers2_test.go b/internal/fourslash/tests/gen/syntacticClassificationsConflictMarkers2_test.go new file mode 100644 index 0000000000..49fdd6b7a6 --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationsConflictMarkers2_test.go @@ -0,0 +1,24 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationsConflictMarkers2(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `<<<<<<< HEAD +class C { } +======= +class D { } +>>>>>>> Branch - a` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "class.declaration", Text: "C"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationsDocComment1_test.go b/internal/fourslash/tests/gen/syntacticClassificationsDocComment1_test.go new file mode 100644 index 0000000000..42579a3844 --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationsDocComment1_test.go @@ -0,0 +1,21 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationsDocComment1(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `/** @type {number} */ +var v;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "variable.declaration", Text: "v"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationsDocComment2_test.go b/internal/fourslash/tests/gen/syntacticClassificationsDocComment2_test.go new file mode 100644 index 0000000000..45f3042556 --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationsDocComment2_test.go @@ -0,0 +1,21 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationsDocComment2(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `/** @param foo { function(x): string } */ +var v;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "variable.declaration", Text: "v"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationsDocComment3_test.go b/internal/fourslash/tests/gen/syntacticClassificationsDocComment3_test.go new file mode 100644 index 0000000000..8cf1bafb2d --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationsDocComment3_test.go @@ -0,0 +1,21 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationsDocComment3(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `/** @param foo { number /* } */ +var v;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "variable.declaration", Text: "v"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationsDocComment4_test.go b/internal/fourslash/tests/gen/syntacticClassificationsDocComment4_test.go new file mode 100644 index 0000000000..eca4eadeba --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationsDocComment4_test.go @@ -0,0 +1,22 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationsDocComment4(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `/** @param {number} p1 */ +function foo(p1) {}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "function.declaration", Text: "foo"}, + {Type: "parameter.declaration", Text: "p1"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationsForOfKeyword2_test.go b/internal/fourslash/tests/gen/syntacticClassificationsForOfKeyword2_test.go new file mode 100644 index 0000000000..55d03e46a6 --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationsForOfKeyword2_test.go @@ -0,0 +1,21 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationsForOfKeyword2(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `for (var of in of) { }` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "variable.declaration", Text: "of"}, + {Type: "variable", Text: "of"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationsForOfKeyword3_test.go b/internal/fourslash/tests/gen/syntacticClassificationsForOfKeyword3_test.go new file mode 100644 index 0000000000..989054d6ca --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationsForOfKeyword3_test.go @@ -0,0 +1,22 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationsForOfKeyword3(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `for (var of; of; of) { }` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "variable.declaration", Text: "of"}, + {Type: "variable", Text: "of"}, + {Type: "variable", Text: "of"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationsForOfKeyword_test.go b/internal/fourslash/tests/gen/syntacticClassificationsForOfKeyword_test.go new file mode 100644 index 0000000000..89738b704b --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationsForOfKeyword_test.go @@ -0,0 +1,21 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationsForOfKeyword(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `for (var of of of) { }` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "variable.declaration", Text: "of"}, + {Type: "variable", Text: "of"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationsFunctionWithComments_test.go b/internal/fourslash/tests/gen/syntacticClassificationsFunctionWithComments_test.go new file mode 100644 index 0000000000..41d0a64904 --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationsFunctionWithComments_test.go @@ -0,0 +1,32 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationsFunctionWithComments(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `/** + * This is my function. + * There are many like it, but this one is mine. + */ +function myFunction(/* x */ x: any) { + var y = x ? x++ : ++x; +} +// end of file` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "function.declaration", Text: "myFunction"}, + {Type: "parameter.declaration", Text: "x"}, + {Type: "variable.declaration.local", Text: "y"}, + {Type: "parameter", Text: "x"}, + {Type: "parameter", Text: "x"}, + {Type: "parameter", Text: "x"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationsJsx1_test.go b/internal/fourslash/tests/gen/syntacticClassificationsJsx1_test.go new file mode 100644 index 0000000000..8dc70a55d5 --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationsJsx1_test.go @@ -0,0 +1,26 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationsJsx1(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @Filename: file1.tsx +let x =
+ some jsx text +
; + +let y = ` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "variable.declaration", Text: "x"}, + {Type: "variable.declaration", Text: "y"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationsJsx2_test.go b/internal/fourslash/tests/gen/syntacticClassificationsJsx2_test.go new file mode 100644 index 0000000000..99fb1f6cba --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationsJsx2_test.go @@ -0,0 +1,26 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationsJsx2(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @Filename: file1.tsx +let x = + some jsx text +; + +let y = ` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "variable.declaration", Text: "x"}, + {Type: "variable.declaration", Text: "y"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationsMergeConflictMarker1_test.go b/internal/fourslash/tests/gen/syntacticClassificationsMergeConflictMarker1_test.go new file mode 100644 index 0000000000..ff84ecc5e3 --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationsMergeConflictMarker1_test.go @@ -0,0 +1,22 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationsMergeConflictMarker1(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `<<<<<<< HEAD +"AAAA" +======= +"BBBB" +>>>>>>> Feature` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{}) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationsObjectLiteral_test.go b/internal/fourslash/tests/gen/syntacticClassificationsObjectLiteral_test.go new file mode 100644 index 0000000000..6c35d0056f --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationsObjectLiteral_test.go @@ -0,0 +1,39 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationsObjectLiteral(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `var v = 10e0; +var x = { + p1: 1, + p2: 2, + any: 3, + function: 4, + var: 5, + void: void 0, + v: v += v, +};` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "variable.declaration", Text: "v"}, + {Type: "variable.declaration", Text: "x"}, + {Type: "property.declaration", Text: "p1"}, + {Type: "property.declaration", Text: "p2"}, + {Type: "property.declaration", Text: "any"}, + {Type: "property.declaration", Text: "function"}, + {Type: "property.declaration", Text: "var"}, + {Type: "property.declaration", Text: "void"}, + {Type: "property.declaration", Text: "v"}, + {Type: "variable", Text: "v"}, + {Type: "variable", Text: "v"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationsTemplates1_test.go b/internal/fourslash/tests/gen/syntacticClassificationsTemplates1_test.go new file mode 100644 index 0000000000..94105dfc78 --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationsTemplates1_test.go @@ -0,0 +1,27 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationsTemplates1(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `var v = 10e0; +var x = { + p1: ` + "`" + `hello world` + "`" + `, + p2: ` + "`" + `goodbye ${0} cruel ${0} world` + "`" + `, +};` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "variable.declaration", Text: "v"}, + {Type: "variable.declaration", Text: "x"}, + {Type: "property.declaration", Text: "p1"}, + {Type: "property.declaration", Text: "p2"}, + }) +} diff --git a/internal/fourslash/tests/gen/syntacticClassificationsTemplates2_test.go b/internal/fourslash/tests/gen/syntacticClassificationsTemplates2_test.go new file mode 100644 index 0000000000..48281b9a55 --- /dev/null +++ b/internal/fourslash/tests/gen/syntacticClassificationsTemplates2_test.go @@ -0,0 +1,22 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSyntacticClassificationsTemplates2(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `var tiredOfCanonicalExamples = +` + "`" + `goodbye "${ ` + "`" + `hello world` + "`" + ` }" +and ${ ` + "`" + `good${ " " }riddance` + "`" + ` }` + "`" + `;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "variable.declaration", Text: "tiredOfCanonicalExamples"}, + }) +} diff --git a/internal/fourslash/tests/manual/semanticModernClassificationFunctions_test.go b/internal/fourslash/tests/manual/semanticModernClassificationFunctions_test.go new file mode 100644 index 0000000000..75e4d9d813 --- /dev/null +++ b/internal/fourslash/tests/manual/semanticModernClassificationFunctions_test.go @@ -0,0 +1,35 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticModernClassificationFunctions(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `function foo(p1) { + return foo(Math.abs(p1)) +} +` + "`" + `/${window.location}` + "`" + `.split("/").forEach(s => foo(s));` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "function.declaration", Text: "foo"}, + {Type: "parameter.declaration", Text: "p1"}, + {Type: "function", Text: "foo"}, + {Type: "variable.defaultLibrary", Text: "Math"}, + {Type: "method.defaultLibrary", Text: "abs"}, + {Type: "parameter", Text: "p1"}, + {Type: "variable.defaultLibrary", Text: "window"}, + {Type: "property.defaultLibrary", Text: "location"}, + {Type: "method.defaultLibrary", Text: "split"}, + {Type: "method.defaultLibrary", Text: "forEach"}, + {Type: "parameter.declaration", Text: "s"}, + {Type: "function", Text: "foo"}, + {Type: "parameter", Text: "s"}, + }) +} diff --git a/internal/fourslash/tests/semanticClassificationJSX_test.go b/internal/fourslash/tests/semanticClassificationJSX_test.go new file mode 100644 index 0000000000..de4a5462b0 --- /dev/null +++ b/internal/fourslash/tests/semanticClassificationJSX_test.go @@ -0,0 +1,26 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestSemanticClassificationJSX(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @Filename: /a.tsx +const Component = () =>
Hello
; +const afterJSX = 42; +const alsoAfterJSX = "test";` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.GoToFile(t, "/a.tsx") + f.VerifySemanticTokens(t, []fourslash.SemanticToken{ + {Type: "function.declaration.readonly", Text: "Component"}, + {Type: "variable.declaration.readonly", Text: "afterJSX"}, + {Type: "variable.declaration.readonly", Text: "alsoAfterJSX"}, + }) +} diff --git a/internal/ls/semantictokens.go b/internal/ls/semantictokens.go new file mode 100644 index 0000000000..9b9147a81d --- /dev/null +++ b/internal/ls/semantictokens.go @@ -0,0 +1,572 @@ +package ls + +import ( + "context" + "fmt" + "slices" + + "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/checker" + "github.com/microsoft/typescript-go/internal/compiler" + "github.com/microsoft/typescript-go/internal/core" + "github.com/microsoft/typescript-go/internal/ls/lsconv" + "github.com/microsoft/typescript-go/internal/lsp/lsproto" + "github.com/microsoft/typescript-go/internal/scanner" + "github.com/microsoft/typescript-go/internal/tspath" +) + +// tokenTypes defines the order of token types for encoding +var tokenTypes = []lsproto.SemanticTokenType{ + lsproto.SemanticTokenTypeNamespace, + lsproto.SemanticTokenTypeClass, + lsproto.SemanticTokenTypeEnum, + lsproto.SemanticTokenTypeInterface, + lsproto.SemanticTokenTypeStruct, + lsproto.SemanticTokenTypeTypeParameter, + lsproto.SemanticTokenTypeType, + lsproto.SemanticTokenTypeParameter, + lsproto.SemanticTokenTypeVariable, + lsproto.SemanticTokenTypeProperty, + lsproto.SemanticTokenTypeEnumMember, + lsproto.SemanticTokenTypeDecorator, + lsproto.SemanticTokenTypeEvent, + lsproto.SemanticTokenTypeFunction, + lsproto.SemanticTokenTypeMethod, + lsproto.SemanticTokenTypeMacro, + lsproto.SemanticTokenTypeLabel, + lsproto.SemanticTokenTypeComment, + lsproto.SemanticTokenTypeString, + lsproto.SemanticTokenTypeKeyword, + lsproto.SemanticTokenTypeNumber, + lsproto.SemanticTokenTypeRegexp, + lsproto.SemanticTokenTypeOperator, +} + +// tokenModifiers defines the order of token modifiers for encoding +var tokenModifiers = []lsproto.SemanticTokenModifier{ + lsproto.SemanticTokenModifierDeclaration, + lsproto.SemanticTokenModifierDefinition, + lsproto.SemanticTokenModifierReadonly, + lsproto.SemanticTokenModifierStatic, + lsproto.SemanticTokenModifierDeprecated, + lsproto.SemanticTokenModifierAbstract, + lsproto.SemanticTokenModifierAsync, + lsproto.SemanticTokenModifierModification, + lsproto.SemanticTokenModifierDocumentation, + lsproto.SemanticTokenModifierDefaultLibrary, + "local", +} + +type tokenType int + +const ( + tokenTypeNamespace tokenType = iota + tokenTypeClass + tokenTypeEnum + tokenTypeInterface + tokenTypeStruct + tokenTypeTypeParameter + tokenTypeType + tokenTypeParameter + tokenTypeVariable + tokenTypeProperty + tokenTypeEnumMember + tokenTypeDecorator + tokenTypeEvent + tokenTypeFunction + tokenTypeMethod // Previously called "member" in TypeScript + tokenTypeMacro + tokenTypeLabel + tokenTypeComment + tokenTypeString + tokenTypeKeyword + tokenTypeNumber + tokenTypeRegexp + tokenTypeOperator +) + +type tokenModifier int + +const ( + tokenModifierDeclaration tokenModifier = 1 << iota + tokenModifierDefinition + tokenModifierReadonly + tokenModifierStatic + tokenModifierDeprecated + tokenModifierAbstract + tokenModifierAsync + tokenModifierModification + tokenModifierDocumentation + tokenModifierDefaultLibrary + tokenModifierLocal +) + +// SemanticTokensLegend returns the legend describing the token types and modifiers. +// If clientCapabilities is provided, it filters the legend to only include types and modifiers +// that the client supports. +func SemanticTokensLegend(clientCapabilities lsproto.ResolvedSemanticTokensClientCapabilities) *lsproto.SemanticTokensLegend { + types := make([]string, 0, len(tokenTypes)) + for _, t := range tokenTypes { + if slices.Contains(clientCapabilities.TokenTypes, string(t)) { + types = append(types, string(t)) + } + } + modifiers := make([]string, 0, len(tokenModifiers)) + for _, m := range tokenModifiers { + if slices.Contains(clientCapabilities.TokenModifiers, string(m)) { + modifiers = append(modifiers, string(m)) + } + } + return &lsproto.SemanticTokensLegend{ + TokenTypes: types, + TokenModifiers: modifiers, + } +} + +func (l *LanguageService) ProvideSemanticTokens(ctx context.Context, documentURI lsproto.DocumentUri) (lsproto.SemanticTokensResponse, error) { + program, file := l.getProgramAndFile(documentURI) + + c, done := program.GetTypeCheckerForFile(ctx, file) + defer done() + + tokens := l.collectSemanticTokens(ctx, c, file, program) + + if len(tokens) == 0 { + return lsproto.SemanticTokensOrNull{}, nil + } + + // Convert to LSP format (relative encoding) + encoded := encodeSemanticTokens(ctx, tokens, file, l.converters) + + return lsproto.SemanticTokensOrNull{ + SemanticTokens: &lsproto.SemanticTokens{ + Data: encoded, + }, + }, nil +} + +func (l *LanguageService) ProvideSemanticTokensRange(ctx context.Context, documentURI lsproto.DocumentUri, rang lsproto.Range) (lsproto.SemanticTokensRangeResponse, error) { + program, file := l.getProgramAndFile(documentURI) + + c, done := program.GetTypeCheckerForFile(ctx, file) + defer done() + + start := int(l.converters.LineAndCharacterToPosition(file, rang.Start)) + end := int(l.converters.LineAndCharacterToPosition(file, rang.End)) + + tokens := l.collectSemanticTokensInRange(ctx, c, file, program, start, end) + + if len(tokens) == 0 { + return lsproto.SemanticTokensOrNull{}, nil + } + + // Convert to LSP format (relative encoding) + encoded := encodeSemanticTokens(ctx, tokens, file, l.converters) + + return lsproto.SemanticTokensOrNull{ + SemanticTokens: &lsproto.SemanticTokens{ + Data: encoded, + }, + }, nil +} + +type semanticToken struct { + node *ast.Node + tokenType tokenType + tokenModifier tokenModifier +} + +func (l *LanguageService) collectSemanticTokens(ctx context.Context, c *checker.Checker, file *ast.SourceFile, program *compiler.Program) []semanticToken { + return l.collectSemanticTokensInRange(ctx, c, file, program, file.Pos(), file.End()) +} + +func (l *LanguageService) collectSemanticTokensInRange(ctx context.Context, c *checker.Checker, file *ast.SourceFile, program *compiler.Program, spanStart, spanEnd int) []semanticToken { + tokens := []semanticToken{} + + inJSXElement := false + + var visit func(*ast.Node) bool + visit = func(node *ast.Node) bool { + // Check for cancellation + if ctx.Err() != nil { + return false + } + + if node == nil { + return false + } + nodeEnd := node.End() + if node.Pos() >= spanEnd || nodeEnd <= spanStart { + return false + } + + prevInJSXElement := inJSXElement + if ast.IsJsxElement(node) || ast.IsJsxSelfClosingElement(node) { + inJSXElement = true + } else if ast.IsJsxExpression(node) { + inJSXElement = false + } + + if ast.IsIdentifier(node) && node.Text() != "" && !inJSXElement && !isInImportClause(node) && !isInfinityOrNaNString(node.Text()) { + symbol := c.GetSymbolAtLocation(node) + if symbol != nil { + // Resolve aliases + if symbol.Flags&ast.SymbolFlagsAlias != 0 { + symbol = c.GetAliasedSymbol(symbol) + } + + tokenType, ok := classifySymbol(symbol, getMeaningFromLocation(node)) + if ok { + tokenModifier := tokenModifier(0) + + // Check if this is a declaration + parent := node.Parent + if parent != nil { + parentIsDeclaration := ast.IsBindingElement(parent) || tokenFromDeclarationMapping(parent.Kind) == tokenType + if parentIsDeclaration && parent.Name() == node { + tokenModifier |= tokenModifierDeclaration + } + } + + // Property declaration in constructor: reclassify parameters as properties in property access context + if tokenType == tokenTypeParameter && ast.IsRightSideOfQualifiedNameOrPropertyAccess(node) { + tokenType = tokenTypeProperty + } + + // Type-based reclassification + tokenType = reclassifyByType(c, node, tokenType) + + // Get the value declaration to check modifiers + if decl := symbol.ValueDeclaration; decl != nil { + modifiers := ast.GetCombinedModifierFlags(decl) + nodeFlags := ast.GetCombinedNodeFlags(decl) + + if modifiers&ast.ModifierFlagsStatic != 0 { + tokenModifier |= tokenModifierStatic + } + if modifiers&ast.ModifierFlagsAsync != 0 { + tokenModifier |= tokenModifierAsync + } + if tokenType != tokenTypeClass && tokenType != tokenTypeInterface { + if (modifiers&ast.ModifierFlagsReadonly != 0) || (nodeFlags&ast.NodeFlagsConst != 0) || (symbol.Flags&ast.SymbolFlagsEnumMember != 0) { + tokenModifier |= tokenModifierReadonly + } + } + if (tokenType == tokenTypeVariable || tokenType == tokenTypeFunction) && isLocalDeclaration(decl, file) { + tokenModifier |= tokenModifierLocal + } + declSourceFile := ast.GetSourceFileOfNode(decl) + if declSourceFile != nil && program.IsSourceFileDefaultLibrary(tspath.Path(declSourceFile.FileName())) { + tokenModifier |= tokenModifierDefaultLibrary + } + } else if symbol.Declarations != nil { + for _, decl := range symbol.Declarations { + declSourceFile := ast.GetSourceFileOfNode(decl) + if declSourceFile != nil && program.IsSourceFileDefaultLibrary(tspath.Path(declSourceFile.FileName())) { + tokenModifier |= tokenModifierDefaultLibrary + break + } + } + } + + tokens = append(tokens, semanticToken{ + node: node, + tokenType: tokenType, + tokenModifier: tokenModifier, + }) + } + } + } + + node.ForEachChild(visit) + inJSXElement = prevInJSXElement + return false + } + + visit(file.AsNode()) + + // Check for cancellation after collection + if ctx.Err() != nil { + return nil + } + + return tokens +} + +func classifySymbol(symbol *ast.Symbol, meaning ast.SemanticMeaning) (tokenType, bool) { + flags := symbol.Flags + if flags&ast.SymbolFlagsClass != 0 { + return tokenTypeClass, true + } + if flags&ast.SymbolFlagsEnum != 0 { + return tokenTypeEnum, true + } + if flags&ast.SymbolFlagsTypeAlias != 0 { + return tokenTypeType, true + } + if flags&ast.SymbolFlagsInterface != 0 { + if meaning&ast.SemanticMeaningType != 0 { + return tokenTypeInterface, true + } + } + if flags&ast.SymbolFlagsTypeParameter != 0 { + return tokenTypeTypeParameter, true + } + + // Check the value declaration + decl := symbol.ValueDeclaration + if decl == nil && len(symbol.Declarations) > 0 { + decl = symbol.Declarations[0] + } + if decl != nil { + if ast.IsBindingElement(decl) { + decl = getDeclarationForBindingElement(decl) + } + if tokenType := tokenFromDeclarationMapping(decl.Kind); tokenType >= 0 { + return tokenType, true + } + } + + return 0, false +} + +func tokenFromDeclarationMapping(kind ast.Kind) tokenType { + switch kind { + case ast.KindVariableDeclaration: + return tokenTypeVariable + case ast.KindParameter: + return tokenTypeParameter + case ast.KindPropertyDeclaration: + return tokenTypeProperty + case ast.KindModuleDeclaration: + return tokenTypeNamespace + case ast.KindEnumDeclaration: + return tokenTypeEnum + case ast.KindEnumMember: + return tokenTypeEnumMember + case ast.KindClassDeclaration: + return tokenTypeClass + case ast.KindMethodDeclaration: + return tokenTypeMethod + case ast.KindFunctionDeclaration, ast.KindFunctionExpression: + return tokenTypeFunction + case ast.KindMethodSignature: + return tokenTypeMethod + case ast.KindGetAccessor, ast.KindSetAccessor: + return tokenTypeProperty + case ast.KindPropertySignature: + return tokenTypeProperty + case ast.KindInterfaceDeclaration: + return tokenTypeInterface + case ast.KindTypeAliasDeclaration: + return tokenTypeType + case ast.KindTypeParameter: + return tokenTypeTypeParameter + case ast.KindPropertyAssignment, ast.KindShorthandPropertyAssignment: + return tokenTypeProperty + default: + return -1 + } +} + +func reclassifyByType(c *checker.Checker, node *ast.Node, tt tokenType) tokenType { + // Type-based reclassification for variables, properties, and parameters + if tt == tokenTypeVariable || tt == tokenTypeProperty || tt == tokenTypeParameter { + typ := c.GetTypeAtLocation(node) + if typ != nil { + test := func(condition func(*checker.Type) bool) bool { + if condition(typ) { + return true + } + if typ.Flags()&checker.TypeFlagsUnion != 0 { + if slices.ContainsFunc(typ.AsUnionType().Types(), condition) { + return true + } + } + return false + } + + // Check for constructor signatures (class-like) + if tt != tokenTypeParameter && test(func(t *checker.Type) bool { + return len(c.GetSignaturesOfType(t, checker.SignatureKindConstruct)) > 0 + }) { + return tokenTypeClass + } + + // Check for call signatures (function-like) + // Must have call signatures AND (no properties OR be used in call context) + hasCallSignatures := test(func(t *checker.Type) bool { + return len(c.GetSignaturesOfType(t, checker.SignatureKindCall)) > 0 + }) + if hasCallSignatures { + hasNoProperties := !test(func(t *checker.Type) bool { + objType := t.AsObjectType() + return objType != nil && len(objType.Properties()) > 0 + }) + if hasNoProperties || isExpressionInCallExpression(node) { + if tt == tokenTypeProperty { + return tokenTypeMethod + } + return tokenTypeFunction + } + } + } + } + return tt +} + +func isLocalDeclaration(decl *ast.Node, sourceFile *ast.SourceFile) bool { + if ast.IsBindingElement(decl) { + decl = getDeclarationForBindingElement(decl) + } + if ast.IsVariableDeclaration(decl) { + parent := decl.Parent + // Check if this is a catch clause parameter + if parent != nil && ast.IsCatchClause(parent) { + return ast.GetSourceFileOfNode(decl) == sourceFile + } + if parent != nil && ast.IsVariableDeclarationList(parent) { + grandparent := parent.Parent + if grandparent != nil { + greatGrandparent := grandparent.Parent + return (!ast.IsSourceFile(greatGrandparent) || ast.IsCatchClause(grandparent)) && + ast.GetSourceFileOfNode(decl) == sourceFile + } + } + } else if ast.IsFunctionDeclaration(decl) { + parent := decl.Parent + return parent != nil && !ast.IsSourceFile(parent) && ast.GetSourceFileOfNode(decl) == sourceFile + } + return false +} + +func getDeclarationForBindingElement(element *ast.Node) *ast.Node { + for { + parent := element.Parent + if parent != nil && ast.IsBindingPattern(parent) { + grandparent := parent.Parent + if grandparent != nil && ast.IsBindingElement(grandparent) { + element = grandparent + continue + } + return parent.Parent + } + return element + } +} + +func isInImportClause(node *ast.Node) bool { + parent := node.Parent + return parent != nil && (ast.IsImportClause(parent) || ast.IsImportSpecifier(parent) || ast.IsNamespaceImport(parent)) +} + +func isExpressionInCallExpression(node *ast.Node) bool { + for ast.IsRightSideOfQualifiedNameOrPropertyAccess(node) { + node = node.Parent + } + parent := node.Parent + return parent != nil && ast.IsCallExpression(parent) && parent.Expression() == node +} + +func isInfinityOrNaNString(text string) bool { + return text == "Infinity" || text == "NaN" +} + +// encodeSemanticTokens encodes tokens into the LSP format using relative positioning. +// It filters tokens based on client capabilities, only including types and modifiers that the client supports. +func encodeSemanticTokens(ctx context.Context, tokens []semanticToken, file *ast.SourceFile, converters *lsconv.Converters) []uint32 { + // Build mapping from server token types/modifiers to client indices + typeMapping := make(map[tokenType]uint32) + modifierMapping := make(map[lsproto.SemanticTokenModifier]uint32) + + clientCapabilities := lsproto.GetClientCapabilities(ctx).TextDocument.SemanticTokens + + // Map server token types to client-supported indices + clientIdx := uint32(0) + for i, serverType := range tokenTypes { + if slices.Contains(clientCapabilities.TokenTypes, string(serverType)) { + typeMapping[tokenType(i)] = clientIdx + clientIdx++ + } + } + + // Map server token modifiers to client-supported bit positions + clientBit := uint32(0) + for _, serverModifier := range tokenModifiers { + if slices.Contains(clientCapabilities.TokenModifiers, string(serverModifier)) { + modifierMapping[serverModifier] = clientBit + clientBit++ + } + } + + // Each token encodes 5 uint32 values: deltaLine, deltaChar, length, tokenType, tokenModifiers + encoded := make([]uint32, 0, len(tokens)*5) + prevLine := uint32(0) + prevChar := uint32(0) + + for _, token := range tokens { + // Skip tokens with types not supported by the client + clientTypeIdx, typeSupported := typeMapping[token.tokenType] + if !typeSupported { + continue + } + + // Map modifiers to client-supported bit mask + clientModifierMask := uint32(0) + for i, serverModifier := range tokenModifiers { + if token.tokenModifier&(1< 0 && (line < prevLine || (line == prevLine && char <= prevChar)) { + panic(fmt.Sprintf("semantic tokens: positions must be strictly increasing: prev=(%d,%d) current=(%d,%d) for token at offset %d", + prevLine, prevChar, line, char, tokenStart)) + } + + // Encode as: [deltaLine, deltaChar, length, tokenType, tokenModifiers] + deltaLine := line - prevLine + var deltaChar uint32 + if deltaLine == 0 { + deltaChar = char - prevChar + } else { + deltaChar = char + } + + encoded = append(encoded, + deltaLine, + deltaChar, + tokenLength, + clientTypeIdx, + clientModifierMask, + ) + + prevLine = line + prevChar = char + } + + return encoded +} diff --git a/internal/lsp/server.go b/internal/lsp/server.go index 87d031fb11..45e9ae2827 100644 --- a/internal/lsp/server.go +++ b/internal/lsp/server.go @@ -565,6 +565,8 @@ var handlers = sync.OnceValue(func() handlerMap { registerRequestHandler(handlers, lsproto.WorkspaceSymbolInfo, (*Server).handleWorkspaceSymbol) registerRequestHandler(handlers, lsproto.CompletionItemResolveInfo, (*Server).handleCompletionItemResolve) registerRequestHandler(handlers, lsproto.CodeLensResolveInfo, (*Server).handleCodeLensResolve) + registerLanguageServiceDocumentRequestHandler(handlers, lsproto.TextDocumentSemanticTokensFullInfo, (*Server).handleSemanticTokensFull) + registerLanguageServiceDocumentRequestHandler(handlers, lsproto.TextDocumentSemanticTokensRangeInfo, (*Server).handleSemanticTokensRange) return handlers }) @@ -1003,6 +1005,17 @@ func (s *Server) handleInitialize(ctx context.Context, params *lsproto.Initializ CallHierarchyProvider: &lsproto.BooleanOrCallHierarchyOptionsOrCallHierarchyRegistrationOptions{ Boolean: ptrTo(true), }, + SemanticTokensProvider: &lsproto.SemanticTokensOptionsOrRegistrationOptions{ + Options: &lsproto.SemanticTokensOptions{ + Legend: ls.SemanticTokensLegend(s.clientCapabilities.TextDocument.SemanticTokens), + Full: &lsproto.BooleanOrSemanticTokensFullDelta{ + Boolean: ptrTo(true), + }, + Range: &lsproto.BooleanOrEmptyObject{ + Boolean: ptrTo(true), + }, + }, + }, }, } @@ -1387,6 +1400,14 @@ func (s *Server) handleCallHierarchyOutgoingCalls( return languageService.ProvideCallHierarchyOutgoingCalls(ctx, params.Item) } +func (s *Server) handleSemanticTokensFull(ctx context.Context, ls *ls.LanguageService, params *lsproto.SemanticTokensParams) (lsproto.SemanticTokensResponse, error) { + return ls.ProvideSemanticTokens(ctx, params.TextDocument.Uri) +} + +func (s *Server) handleSemanticTokensRange(ctx context.Context, ls *ls.LanguageService, params *lsproto.SemanticTokensRangeParams) (lsproto.SemanticTokensRangeResponse, error) { + return ls.ProvideSemanticTokensRange(ctx, params.TextDocument.Uri, params.Range) +} + func (s *Server) Log(msg ...any) { fmt.Fprintln(s.stderr, msg...) } diff --git a/testdata/baselines/reference/fourslash/documentHighlights/renameDefaultImport.baseline.jsonc b/testdata/baselines/reference/fourslash/documentHighlights/renameDefaultImport.baseline.jsonc new file mode 100644 index 0000000000..0f348b352d --- /dev/null +++ b/testdata/baselines/reference/fourslash/documentHighlights/renameDefaultImport.baseline.jsonc @@ -0,0 +1,6 @@ +// === documentHighlights === +// === /B.ts === +// export default class /*HIGHLIGHTS*/[|B|] { +// test() { +// } +// } \ No newline at end of file diff --git a/testdata/baselines/reference/fourslash/findAllReferences/renameDefaultImport.baseline.jsonc b/testdata/baselines/reference/fourslash/findAllReferences/renameDefaultImport.baseline.jsonc new file mode 100644 index 0000000000..6933ed8935 --- /dev/null +++ b/testdata/baselines/reference/fourslash/findAllReferences/renameDefaultImport.baseline.jsonc @@ -0,0 +1,25 @@ +// === findAllReferences === +// === /A.ts === +// import [|B|] from "./B"; +// let b = new [|B|](); +// b.test(); + +// === /B.ts === +// export default class /*FIND ALL REFS*/[|B|] { +// test() { +// } +// } + + + +// === findAllReferences === +// === /A.ts === +// import /*FIND ALL REFS*/[|B|] from "./B"; +// let b = new [|B|](); +// b.test(); + +// === /B.ts === +// export default class [|B|] { +// test() { +// } +// } \ No newline at end of file diff --git a/testdata/baselines/reference/submodule/fourslash/findRenameLocations/renameDefaultImport.baseline.jsonc b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/renameDefaultImport.baseline.jsonc new file mode 100644 index 0000000000..55265b7c8e --- /dev/null +++ b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/renameDefaultImport.baseline.jsonc @@ -0,0 +1,27 @@ +// === findRenameLocations === +// === /A.ts === +// import [|BRENAME|] from "./B"; +// let b = new [|BRENAME|](); +// b.test(); + +// === /B.ts === +// export default class /*RENAME*/[|BRENAME|] { +// test() { +// } +// } + + + +// === findRenameLocations === +// === /A.ts === +// import /*RENAME*/[|BRENAME|] from "./B"; +// let b = new [|BRENAME|](); +// b.test(); + + + +// === findRenameLocations === +// === /A.ts === +// import [|BRENAME|] from "./B"; +// let b = new /*RENAME*/[|BRENAME|](); +// b.test(); \ No newline at end of file diff --git a/testdata/baselines/reference/submodule/fourslash/findRenameLocations/renameDefaultImport.baseline.jsonc.diff b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/renameDefaultImport.baseline.jsonc.diff new file mode 100644 index 0000000000..dcb8fa2700 --- /dev/null +++ b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/renameDefaultImport.baseline.jsonc.diff @@ -0,0 +1,21 @@ +--- old.renameDefaultImport.baseline.jsonc ++++ new.renameDefaultImport.baseline.jsonc +@@= skipped -0, +0 lines =@@ + // === findRenameLocations === ++// === /A.ts === ++// import [|BRENAME|] from "./B"; ++// let b = new [|BRENAME|](); ++// b.test(); ++ + // === /B.ts === + // export default class /*RENAME*/[|BRENAME|] { + // test() { + // } + // } +- +-// === /A.ts === +-// import [|BRENAME|] from "./B"; +-// let b = new [|BRENAME|](); +-// b.test(); + +