From f975ffd533d87f3c7e3e94220b207d049c700cea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 27 May 2026 01:42:09 +0000 Subject: [PATCH 1/2] deps(deps): bump microsoft/typescript-go from `2b43ca0` to `c54ff7c` Bumps [microsoft/typescript-go](https://github.com/microsoft/typescript-go) from `2b43ca0` to `c54ff7c`. - [Commits](https://github.com/microsoft/typescript-go/compare/2b43ca072d8e9ba7cefb006520b47d7dfc642066...c54ff7cc5528734fd303461719b54b70115f5445) --- updated-dependencies: - dependency-name: microsoft/typescript-go dependency-version: c54ff7cc5528734fd303461719b54b70115f5445 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- microsoft/typescript-go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsoft/typescript-go b/microsoft/typescript-go index 2b43ca072..c54ff7cc5 160000 --- a/microsoft/typescript-go +++ b/microsoft/typescript-go @@ -1 +1 @@ -Subproject commit 2b43ca072d8e9ba7cefb006520b47d7dfc642066 +Subproject commit c54ff7cc5528734fd303461719b54b70115f5445 From b6c62a482f29f4ad0aeefbfd04f0ca8a4be45acd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 27 May 2026 01:51:08 +0000 Subject: [PATCH 2/2] chore(sync): mirror internal packages into pkg/ (auto) --- pkg/checker/nodebuilderimpl.go | 35 ++- pkg/checker/nodecopy.go | 48 ++-- pkg/checker/printer.go | 24 +- pkg/checker/pseudotypenodebuilder.go | 10 +- .../tests/pathCompletionsPartialPath_test.go | 206 ++++++++++++++++++ ...quickinfoVerbosityIncreaseDecrease_test.go | 64 ++++++ pkg/ls/string_completions.go | 14 +- .../declarationEmitKeywordPropertyNames.js | 45 ++++ ...eclarationEmitKeywordPropertyNames.symbols | 56 +++++ .../declarationEmitKeywordPropertyNames.types | 72 ++++++ ...uickinfoVerbosityIncreaseDecrease.baseline | 179 +++++++++++++++ .../submodule/compiler/emitMethodCalledNew.js | 2 +- .../compiler/emitMethodCalledNew.js.diff | 9 - testdata/submoduleAccepted.txt | 1 - .../declarationEmitKeywordPropertyNames.ts | 22 ++ 15 files changed, 728 insertions(+), 59 deletions(-) create mode 100644 pkg/fourslash/tests/pathCompletionsPartialPath_test.go create mode 100644 pkg/fourslash/tests/quickinfoVerbosityIncreaseDecrease_test.go create mode 100644 testdata/baselines/reference/compiler/declarationEmitKeywordPropertyNames.js create mode 100644 testdata/baselines/reference/compiler/declarationEmitKeywordPropertyNames.symbols create mode 100644 testdata/baselines/reference/compiler/declarationEmitKeywordPropertyNames.types create mode 100644 testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityIncreaseDecrease.baseline delete mode 100644 testdata/baselines/reference/submoduleAccepted/compiler/emitMethodCalledNew.js.diff create mode 100644 testdata/tests/cases/compiler/declarationEmitKeywordPropertyNames.ts diff --git a/pkg/checker/nodebuilderimpl.go b/pkg/checker/nodebuilderimpl.go index a0b79d066..794fd8c09 100644 --- a/pkg/checker/nodebuilderimpl.go +++ b/pkg/checker/nodebuilderimpl.go @@ -2281,16 +2281,33 @@ func (b *NodeBuilderImpl) trackComputedName(accessExpression *ast.Node, enclosin } } +type propertyNameNodeKind int + +const ( + propertyNameNodeKindIdentifier propertyNameNodeKind = iota + propertyNameNodeKindNumericLiteral + propertyNameNodeKindStringLiteral +) + +func classifyPropertyName(name string, stringNamed bool, isMethod bool) propertyNameNodeKind { + if isMethod && name == "new" { + return propertyNameNodeKindStringLiteral + } + if scanner.IsIdentifierText(name, core.LanguageVariantStandard) { + return propertyNameNodeKindIdentifier + } + return core.IfElse(!stringNamed && isNumericLiteralName(name) && jsnum.FromString(name) >= 0, propertyNameNodeKindNumericLiteral, propertyNameNodeKindStringLiteral) +} + func (b *NodeBuilderImpl) createPropertyNameNodeForIdentifierOrLiteral(name string, singleQuote bool, stringNamed bool, isMethod bool, symbol *ast.Symbol) *ast.Node { - isMethodNamedNew := isMethod && name == "new" - if !isMethodNamedNew && scanner.IsIdentifierText(name, core.LanguageVariantStandard) { + switch classifyPropertyName(name, stringNamed, isMethod) { + case propertyNameNodeKindIdentifier: return b.newIdentifier(name, symbol) - } - if !stringNamed && !isMethodNamedNew && isNumericLiteralName(name) && jsnum.FromString(name) >= 0 { + case propertyNameNodeKindNumericLiteral: return b.f.NewNumericLiteral(name, ast.TokenFlagsNone) + default: + return b.f.NewStringLiteral(name, core.IfElse(singleQuote, ast.TokenFlagsSingleQuote, ast.TokenFlagsNone)) } - result := b.f.NewStringLiteral(name, core.IfElse(singleQuote, ast.TokenFlagsSingleQuote, ast.TokenFlagsNone)) - return result } func (b *NodeBuilderImpl) isStringNamed(d *ast.Declaration) bool { @@ -3000,7 +3017,9 @@ func (b *NodeBuilderImpl) visitAndTransformType(t *Type, transform func(b *NodeB // of types allows us to catch circular references to instantiations of the same anonymous type key := CompositeTypeCacheIdentity{typeId, b.ctx.flags, b.ctx.internalFlags} - if b.ctx.maxExpansionDepth <= 0 && b.ctx.enclosingDeclaration != nil && b.links.Has(b.ctx.enclosingDeclaration) { + // Don't rely on type cache if we're expanding a type, because we need to compute `canIncreaseExpansionDepth`. + canUseCache := b.ctx.maxExpansionDepth < 0 + if canUseCache && b.ctx.enclosingDeclaration != nil && b.links.Has(b.ctx.enclosingDeclaration) { links := b.links.Get(b.ctx.enclosingDeclaration) cachedResult, ok := links.serializedTypes[key] if ok { @@ -3030,7 +3049,7 @@ func (b *NodeBuilderImpl) visitAndTransformType(t *Type, transform func(b *NodeB startLength := b.ctx.approximateLength result := transform(b, t) addedLength := b.ctx.approximateLength - startLength - if !b.ctx.reportedDiagnostic && !b.ctx.encounteredError { + if canUseCache && !b.ctx.reportedDiagnostic && !b.ctx.encounteredError { links := b.links.Get(b.ctx.enclosingDeclaration) if links.serializedTypes == nil { links.serializedTypes = make(map[CompositeTypeCacheIdentity]*SerializedTypeEntry) diff --git a/pkg/checker/nodecopy.go b/pkg/checker/nodecopy.go index bc7bbf217..e05ac0b49 100644 --- a/pkg/checker/nodecopy.go +++ b/pkg/checker/nodecopy.go @@ -7,7 +7,6 @@ import ( "github.com/buke/typescript-go-internal/pkg/core" "github.com/buke/typescript-go-internal/pkg/nodebuilder" "github.com/buke/typescript-go-internal/pkg/printer" - "github.com/buke/typescript-go-internal/pkg/scanner" ) func (b *NodeBuilderImpl) reuseNode(node *ast.Node) *ast.Node { @@ -22,35 +21,36 @@ func (b *NodeBuilderImpl) tryJSTypeNodeToTypeNode(node *ast.Node) *ast.Node { return b.reuseNode(node) } -// a wrapper around `reuseNode` for property names. It handles renaming `new` to `"new"` so we don't -// accidentally emit constructor signatures when we don't mean to, and normalizes string-literal -// property names whose text is a valid identifier into identifiers, matching the behavior of -// `createPropertyNameNodeForIdentifierOrLiteral` used when constructing fresh property name nodes -// (so that reused names emit consistently regardless of whether their containing type was reused -// from source or rebuilt from a type). -func (b *NodeBuilderImpl) reuseName(node *ast.Node) *ast.Node { +func (b *NodeBuilderImpl) reuseName(node *ast.Node, isMethod bool) *ast.Node { res := b.reuseNode(node) if res == nil { return res } - if res.Kind == ast.KindIdentifier && node.AsIdentifier().Text == "new" { - str := b.f.NewStringLiteral("new", ast.TokenFlagsNone) - b.e.SetOriginal(str, res) - return b.setTextRange(str, res) + + text, ok := ast.TryGetTextOfPropertyName(res) + if !ok { + return res } - if res.Kind == ast.KindStringLiteral { - text := res.AsStringLiteral().Text - // Skip normalization for "new" so that reused names like `"new"(): void` on a - // method signature are not converted to an identifier (which would become a - // construct signature). This mirrors the `isMethodNamedNew` guard in - // createPropertyNameNodeForIdentifierOrLiteral. - if text != "new" && scanner.IsIdentifierText(text, core.LanguageVariantStandard) { - ident := b.newIdentifier(text, nil) - b.e.SetOriginal(ident, res) - return b.setTextRange(ident, res) - } + + kind := classifyPropertyName(text, ast.IsStringLiteral(res), isMethod) + if ast.IsIdentifier(res) && kind == propertyNameNodeKindIdentifier { + return res } - return res + if ast.IsStringLiteral(res) && kind == propertyNameNodeKindStringLiteral { + return res + } + + var renamed *ast.Node + switch kind { + case propertyNameNodeKindIdentifier: + renamed = b.newIdentifier(text, nil) + case propertyNameNodeKindStringLiteral: + renamed = b.f.NewStringLiteral(text, ast.TokenFlagsNone) + default: + return res + } + b.e.SetOriginal(renamed, res) + return b.setTextRange(renamed, res) } func (b *NodeBuilderImpl) reuseTypeNode(node *ast.Node) *ast.Node { diff --git a/pkg/checker/printer.go b/pkg/checker/printer.go index 29d8af1e3..871780304 100644 --- a/pkg/checker/printer.go +++ b/pkg/checker/printer.go @@ -198,9 +198,11 @@ func (c *Checker) typeToStringEx(t *Type, enclosingDeclaration *ast.Node, flags combinedFlags = combinedFlags | nodebuilder.FlagsNoTruncation } nodeBuilder := c.getNodeBuilder() - if vc != nil { - nodeBuilder.verbosity = vc - } + oldVerbosity := nodeBuilder.verbosity + nodeBuilder.verbosity = vc + defer func() { + nodeBuilder.verbosity = oldVerbosity + }() typeNode := nodeBuilder.TypeToTypeNode(t, enclosingDeclaration, combinedFlags, nodebuilder.InternalFlagsNone, nil) if typeNode == nil { panic("should always get typenode") @@ -320,9 +322,11 @@ func (c *Checker) signatureToStringEx(signature *Signature, enclosingDeclaration } nodeBuilder := c.getNodeBuilder() - if vc != nil { - nodeBuilder.verbosity = vc - } + oldVerbosity := nodeBuilder.verbosity + nodeBuilder.verbosity = vc + defer func() { + nodeBuilder.verbosity = oldVerbosity + }() combinedFlags := toNodeBuilderFlags(flags) | nodebuilder.FlagsIgnoreErrors | nodebuilder.FlagsWriteTypeParametersInQualifiedName sig := nodeBuilder.SignatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, combinedFlags, nodebuilder.InternalFlagsNone, nil) p := createPrinterWithRemoveCommentsOmitTrailingSemicolonNeverAsciiEscape(nodeBuilder.EmitContext()) @@ -412,7 +416,11 @@ func (c *Checker) SignatureToSignatureDeclaration(signature *Signature, kind ast // ExpandSymbolForHover produces declaration strings for a symbol with verbosity support for expandable hover. func (c *Checker) ExpandSymbolForHover(symbol *ast.Symbol, meaning ast.SymbolFlags, vc *VerbosityContext) string { nodeBuilder := c.getNodeBuilder() + oldVerbosity := nodeBuilder.verbosity nodeBuilder.verbosity = vc + defer func() { + nodeBuilder.verbosity = oldVerbosity + }() nodes := nodeBuilder.ExpandSymbolForHover(symbol, meaning) if len(nodes) == 0 { return "" @@ -435,7 +443,11 @@ func (c *Checker) ExpandSymbolForHover(symbol *ast.Symbol, meaning ast.SymbolFla // TypeParameterToStringEx renders a type parameter declaration (e.g. "T extends Foo") with optional verbosity support. func (c *Checker) TypeParameterToStringEx(t *Type, enclosingDeclaration *ast.Node, vc *VerbosityContext) string { nodeBuilder := c.getNodeBuilder() + oldVerbosity := nodeBuilder.verbosity nodeBuilder.verbosity = vc + defer func() { + nodeBuilder.verbosity = oldVerbosity + }() typeParamNode := nodeBuilder.TypeParameterToDeclaration(t, enclosingDeclaration, nodebuilder.FlagsIgnoreErrors, nodebuilder.InternalFlagsNone, nil) if typeParamNode == nil { return c.TypeToString(t) diff --git a/pkg/checker/pseudotypenodebuilder.go b/pkg/checker/pseudotypenodebuilder.go index 3a267ed4c..c1f369c0e 100644 --- a/pkg/checker/pseudotypenodebuilder.go +++ b/pkg/checker/pseudotypenodebuilder.go @@ -224,7 +224,7 @@ func (b *NodeBuilderImpl) pseudoTypeToNode(t *pseudochecker.PseudoType) *ast.Nod if isConst { newProp = b.f.NewPropertySignatureDeclaration( modifiers, - b.reuseName(e.Name), + b.reuseName(e.Name, false /*isMethod*/), nil, b.f.NewFunctionTypeNode( typeParams, @@ -237,7 +237,7 @@ func (b *NodeBuilderImpl) pseudoTypeToNode(t *pseudochecker.PseudoType) *ast.Nod } newProp = b.f.NewMethodSignatureDeclaration( modifiers, - b.reuseName(e.Name), + b.reuseName(e.Name, true /*isMethod*/), nil, typeParams, b.pseudoParametersToNodeList(d.Parameters), @@ -247,7 +247,7 @@ func (b *NodeBuilderImpl) pseudoTypeToNode(t *pseudochecker.PseudoType) *ast.Nod d := e.AsPseudoPropertyAssignment() newProp = b.f.NewPropertySignatureDeclaration( modifiers, - b.reuseName(e.Name), + b.reuseName(e.Name, false /*isMethod*/), nil, b.pseudoTypeToNode(d.Type), nil, @@ -256,7 +256,7 @@ func (b *NodeBuilderImpl) pseudoTypeToNode(t *pseudochecker.PseudoType) *ast.Nod d := e.AsPseudoSetAccessor() newProp = b.f.NewSetAccessorDeclaration( nil, - b.reuseName(e.Name), + b.reuseName(e.Name, false /*isMethod*/), nil, b.f.NewNodeList([]*ast.Node{b.pseudoParameterToNode(d.Parameter)}), nil, @@ -267,7 +267,7 @@ func (b *NodeBuilderImpl) pseudoTypeToNode(t *pseudochecker.PseudoType) *ast.Nod d := e.AsPseudoGetAccessor() newProp = b.f.NewGetAccessorDeclaration( nil, - b.reuseName(e.Name), + b.reuseName(e.Name, false /*isMethod*/), nil, nil, b.pseudoTypeToNode(d.Type), diff --git a/pkg/fourslash/tests/pathCompletionsPartialPath_test.go b/pkg/fourslash/tests/pathCompletionsPartialPath_test.go new file mode 100644 index 000000000..269daf5cf --- /dev/null +++ b/pkg/fourslash/tests/pathCompletionsPartialPath_test.go @@ -0,0 +1,206 @@ +package fourslash_test + +import ( + "testing" + + "github.com/buke/typescript-go-internal/pkg/fourslash" + . "github.com/buke/typescript-go-internal/pkg/fourslash/tests/util" + "github.com/buke/typescript-go-internal/pkg/testutil" +) + +func TestPathCompletionsPartialPathRelativeImport(t *testing.T) { + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + + const content = `// @Filename: /src/main.ts +import { } from "./foo//*$*/"; +// @Filename: /src/foo/async.ts +export const asyncApi = "async"; +// @Filename: /src/foo/fs.ts +export const fsApi = "fs"; +// @Filename: /src/foo/sync.ts +export const syncApi = "sync";` + + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCompletions(t, "$", &fourslash.CompletionsExpectedList{ + IsIncomplete: false, + ItemDefaults: &fourslash.CompletionsExpectedItemDefaults{ + CommitCharacters: &[]string{}, + EditRange: Ignored, + }, + Items: &fourslash.CompletionsExpectedItems{ + Exact: []fourslash.CompletionsExpectedItem{ + "async", + "fs", + "sync", + }, + }, + }) +} + +func TestPathCompletionsPartialPathPackageNoExports(t *testing.T) { + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + + const content = `// @moduleResolution: bundler +// @Filename: /node_modules/@typescript/native-preview/package.json +{ "name": "@typescript/native-preview", "version": "0.0.0" } +// @Filename: /node_modules/@typescript/native-preview/unstable/async.ts +export const asyncApi = "async"; +// @Filename: /node_modules/@typescript/native-preview/unstable/fs.ts +export const fsApi = "fs"; +// @Filename: /node_modules/@typescript/native-preview/unstable/sync.ts +export const syncApi = "sync"; +// @Filename: /package.json +{ "dependencies": { "@typescript/native-preview": "0.0.0" } } +// @Filename: /src/main.ts +import { } from "@typescript/native-preview/unstable//*$*/";` + + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCompletions(t, "$", &fourslash.CompletionsExpectedList{ + IsIncomplete: false, + ItemDefaults: &fourslash.CompletionsExpectedItemDefaults{ + CommitCharacters: &[]string{}, + EditRange: Ignored, + }, + Items: &fourslash.CompletionsExpectedItems{ + Exact: []fourslash.CompletionsExpectedItem{ + "async", + "fs", + "sync", + }, + }, + }) +} + +func TestPathCompletionsPartialPathPackageExports(t *testing.T) { + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + + const content = `// @moduleResolution: bundler +// @Filename: /node_modules/@typescript/native-preview/package.json +{ + "name": "@typescript/native-preview", + "version": "0.0.0", + "exports": { + "./unstable/sync": "./dist/api/sync/api.js", + "./unstable/async": "./dist/api/async/api.js", + "./unstable/fs": "./dist/api/fs.js" + } +} +// @Filename: /node_modules/@typescript/native-preview/index.d.ts +export {}; +// @Filename: /node_modules/@typescript/native-preview/dist/api/async/api.js +export const asyncApi = "async"; +// @Filename: /node_modules/@typescript/native-preview/dist/api/fs.js +export const fsApi = "fs"; +// @Filename: /node_modules/@typescript/native-preview/dist/api/sync/api.js +export const syncApi = "sync"; +// @Filename: /package.json +{ "dependencies": { "@typescript/native-preview": "0.0.0" } } +// @Filename: /src/main.ts +import { } from "@typescript/native-preview/unstable//*$*/";` + + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCompletions(t, "$", &fourslash.CompletionsExpectedList{ + IsIncomplete: false, + ItemDefaults: &fourslash.CompletionsExpectedItemDefaults{ + CommitCharacters: &[]string{}, + EditRange: Ignored, + }, + Items: &fourslash.CompletionsExpectedItems{ + Exact: []fourslash.CompletionsExpectedItem{ + "async", + "fs", + "sync", + }, + }, + }) +} + +func TestPathCompletionsPartialPathPackageExportsEndingStar(t *testing.T) { + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + + const content = `// @moduleResolution: bundler +// @Filename: /node_modules/@typescript/native-preview/package.json +{ + "name": "@typescript/native-preview", + "version": "0.0.0", + "exports": { + "./unstable/*": "./dist/unstable/*.d.ts" + } +} +// @Filename: /node_modules/@typescript/native-preview/dist/unstable/async.d.ts +export declare const asyncApi: string; +// @Filename: /node_modules/@typescript/native-preview/dist/unstable/fs.d.ts +export declare const fsApi: string; +// @Filename: /node_modules/@typescript/native-preview/dist/unstable/sync.d.ts +export declare const syncApi: string; +// @Filename: /package.json +{ "dependencies": { "@typescript/native-preview": "0.0.0" } } +// @Filename: /src/main.ts +import { } from "@typescript/native-preview/unstable//*$*/";` + + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCompletions(t, "$", &fourslash.CompletionsExpectedList{ + IsIncomplete: false, + ItemDefaults: &fourslash.CompletionsExpectedItemDefaults{ + CommitCharacters: &[]string{}, + EditRange: Ignored, + }, + Items: &fourslash.CompletionsExpectedItems{ + Exact: []fourslash.CompletionsExpectedItem{ + "async", + "fs", + "sync", + }, + }, + }) +} + +func TestPathCompletionsPartialPathPackageExportsMiddleStar(t *testing.T) { + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + + const content = `// @moduleResolution: bundler +// @Filename: /node_modules/@typescript/native-preview/package.json +{ + "name": "@typescript/native-preview", + "version": "0.0.0", + "exports": { + "./unstable/_*/api": "./dist/api/*.d.ts" + } +} +// @Filename: /node_modules/@typescript/native-preview/dist/api/async.d.ts +export declare const asyncApi: string; +// @Filename: /node_modules/@typescript/native-preview/dist/api/fs.d.ts +export declare const fsApi: string; +// @Filename: /node_modules/@typescript/native-preview/dist/api/sync.d.ts +export declare const syncApi: string; +// @Filename: /package.json +{ "dependencies": { "@typescript/native-preview": "0.0.0" } } +// @Filename: /src/main.ts +import { } from "@typescript/native-preview/unstable//*$*/";` + + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCompletions(t, "$", &fourslash.CompletionsExpectedList{ + IsIncomplete: false, + ItemDefaults: &fourslash.CompletionsExpectedItemDefaults{ + CommitCharacters: &[]string{}, + EditRange: Ignored, + }, + Items: &fourslash.CompletionsExpectedItems{ + Exact: []fourslash.CompletionsExpectedItem{ + "_async/api", + "_fs/api", + "_sync/api", + }, + }, + }) +} diff --git a/pkg/fourslash/tests/quickinfoVerbosityIncreaseDecrease_test.go b/pkg/fourslash/tests/quickinfoVerbosityIncreaseDecrease_test.go new file mode 100644 index 000000000..0a3c65070 --- /dev/null +++ b/pkg/fourslash/tests/quickinfoVerbosityIncreaseDecrease_test.go @@ -0,0 +1,64 @@ +package fourslash_test + +import ( + "testing" + + "github.com/buke/typescript-go-internal/pkg/fourslash" + "github.com/buke/typescript-go-internal/pkg/testutil" +) + +func TestQuickinfoVerbosityIncreaseDecrease(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `export const JOB_STATES = ["created", "active", "completed", "failed", "retry", "cancelled", "archive"] as const +export type JobState = (typeof JOB_STATES)[number] +type Color = "default" | "primary" | "secondary" | "success" | "warning" | "danger" +const JobsStateToColor/*a*/: Record< + JobState, + { + color: Color + label: string + labelPlural: string + } +> = { + created: { + color: "success", + label: "Направљен", + labelPlural: "Направљени", + }, + active: { + color: "success", + label: "Активан", + labelPlural: "Активни", + }, + completed: { + color: "success", + label: "Успешан", + labelPlural: "Успешни", + }, + cancelled: { + color: "default", + label: "Отаказан", + labelPlural: "Отаказни", + }, + failed: { + color: "danger", + label: "Пао", + labelPlural: "Пали", + }, + archive: { + color: "default", + label: "Архивиран", + labelPlural: "Архивирани", + }, + retry: { + color: "warning", + label: "Понавља се", + labelPlural: "Понављају се", + }, +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyBaselineHoverWithVerbosity(t, map[string][]int{"a": {0, 1, 0}}) +} diff --git a/pkg/ls/string_completions.go b/pkg/ls/string_completions.go index aa5975759..94b545035 100644 --- a/pkg/ls/string_completions.go +++ b/pkg/ls/string_completions.go @@ -1466,10 +1466,18 @@ func (l *LanguageService) getCompletionsForPathMapping( extensionOptions *extensionOptions, program *compiler.Program, ) []moduleCompletionNameAndKind { + fragmentDirectory := getFragmentDirectory(fragment) + if fragmentDirectory != "" { + fragmentDirectory = tspath.EnsureTrailingDirectorySeparator(fragmentDirectory) + } justPathMappingName := func(name string, kind moduleCompletionKind, extension string) []moduleCompletionNameAndKind { if strings.HasPrefix(name, fragment) { + name = tspath.RemoveTrailingDirectorySeparator(name) + if fragmentDirectory != "" { + name = strings.TrimPrefix(name, fragmentDirectory) + } return []moduleCompletionNameAndKind{{ - name: tspath.RemoveTrailingDirectorySeparator(name), + name: name, kind: kind, extension: extension, }} @@ -1491,10 +1499,6 @@ func (l *LanguageService) getCompletionsForPathMapping( pathPrefix := parsedPath.Text[:parsedPath.StarIndex] pathSuffix := parsedPath.Text[parsedPath.StarIndex+1:] - fragmentDirectory := getFragmentDirectory(fragment) - if fragmentDirectory != "" { - fragmentDirectory = tspath.EnsureTrailingDirectorySeparator(fragmentDirectory) - } if !strings.HasPrefix(fragment, pathPrefix) { // Fragment doesn't match the path mapping prefix at all: // we cannot extend it via this path. diff --git a/testdata/baselines/reference/compiler/declarationEmitKeywordPropertyNames.js b/testdata/baselines/reference/compiler/declarationEmitKeywordPropertyNames.js new file mode 100644 index 000000000..74c0bff19 --- /dev/null +++ b/testdata/baselines/reference/compiler/declarationEmitKeywordPropertyNames.js @@ -0,0 +1,45 @@ +//// [tests/cases/compiler/declarationEmitKeywordPropertyNames.ts] //// + +//// [declarationEmitKeywordPropertyNames.ts] +export const a = { + foo: "foo", + bar: "bar", + buzz: "buzz", + new: "new", + delete: "delete", + break: "break", + continue: "continue", +}; + +export const b = { + foo: "foo", + bar: "bar", + buzz: "buzz", + new: "new", + delete: "delete", + break: "break", + continue: "continue", +} as const; + + + + +//// [declarationEmitKeywordPropertyNames.d.ts] +export declare const a: { + foo: string; + bar: string; + buzz: string; + new: string; + delete: string; + break: string; + continue: string; +}; +export declare const b: { + readonly foo: "foo"; + readonly bar: "bar"; + readonly buzz: "buzz"; + readonly new: "new"; + readonly delete: "delete"; + readonly break: "break"; + readonly continue: "continue"; +}; diff --git a/testdata/baselines/reference/compiler/declarationEmitKeywordPropertyNames.symbols b/testdata/baselines/reference/compiler/declarationEmitKeywordPropertyNames.symbols new file mode 100644 index 000000000..65816f3a2 --- /dev/null +++ b/testdata/baselines/reference/compiler/declarationEmitKeywordPropertyNames.symbols @@ -0,0 +1,56 @@ +//// [tests/cases/compiler/declarationEmitKeywordPropertyNames.ts] //// + +=== declarationEmitKeywordPropertyNames.ts === +export const a = { +>a : Symbol(a, Decl(declarationEmitKeywordPropertyNames.ts, 0, 12)) + + foo: "foo", +>foo : Symbol(foo, Decl(declarationEmitKeywordPropertyNames.ts, 0, 18)) + + bar: "bar", +>bar : Symbol(bar, Decl(declarationEmitKeywordPropertyNames.ts, 1, 15)) + + buzz: "buzz", +>buzz : Symbol(buzz, Decl(declarationEmitKeywordPropertyNames.ts, 2, 15)) + + new: "new", +>new : Symbol(new, Decl(declarationEmitKeywordPropertyNames.ts, 3, 17)) + + delete: "delete", +>delete : Symbol(delete, Decl(declarationEmitKeywordPropertyNames.ts, 4, 15)) + + break: "break", +>break : Symbol(break, Decl(declarationEmitKeywordPropertyNames.ts, 5, 21)) + + continue: "continue", +>continue : Symbol(continue, Decl(declarationEmitKeywordPropertyNames.ts, 6, 19)) + +}; + +export const b = { +>b : Symbol(b, Decl(declarationEmitKeywordPropertyNames.ts, 10, 12)) + + foo: "foo", +>foo : Symbol(foo, Decl(declarationEmitKeywordPropertyNames.ts, 10, 18)) + + bar: "bar", +>bar : Symbol(bar, Decl(declarationEmitKeywordPropertyNames.ts, 11, 15)) + + buzz: "buzz", +>buzz : Symbol(buzz, Decl(declarationEmitKeywordPropertyNames.ts, 12, 15)) + + new: "new", +>new : Symbol(new, Decl(declarationEmitKeywordPropertyNames.ts, 13, 17)) + + delete: "delete", +>delete : Symbol(delete, Decl(declarationEmitKeywordPropertyNames.ts, 14, 15)) + + break: "break", +>break : Symbol(break, Decl(declarationEmitKeywordPropertyNames.ts, 15, 21)) + + continue: "continue", +>continue : Symbol(continue, Decl(declarationEmitKeywordPropertyNames.ts, 16, 19)) + +} as const; +>const : Symbol(const) + diff --git a/testdata/baselines/reference/compiler/declarationEmitKeywordPropertyNames.types b/testdata/baselines/reference/compiler/declarationEmitKeywordPropertyNames.types new file mode 100644 index 000000000..07f34cd9e --- /dev/null +++ b/testdata/baselines/reference/compiler/declarationEmitKeywordPropertyNames.types @@ -0,0 +1,72 @@ +//// [tests/cases/compiler/declarationEmitKeywordPropertyNames.ts] //// + +=== declarationEmitKeywordPropertyNames.ts === +export const a = { +>a : { foo: string; bar: string; buzz: string; new: string; delete: string; break: string; continue: string; } +>{ foo: "foo", bar: "bar", buzz: "buzz", new: "new", delete: "delete", break: "break", continue: "continue",} : { foo: string; bar: string; buzz: string; new: string; delete: string; break: string; continue: string; } + + foo: "foo", +>foo : string +>"foo" : "foo" + + bar: "bar", +>bar : string +>"bar" : "bar" + + buzz: "buzz", +>buzz : string +>"buzz" : "buzz" + + new: "new", +>new : string +>"new" : "new" + + delete: "delete", +>delete : string +>"delete" : "delete" + + break: "break", +>break : string +>"break" : "break" + + continue: "continue", +>continue : string +>"continue" : "continue" + +}; + +export const b = { +>b : { readonly foo: "foo"; readonly bar: "bar"; readonly buzz: "buzz"; readonly new: "new"; readonly delete: "delete"; readonly break: "break"; readonly continue: "continue"; } +>{ foo: "foo", bar: "bar", buzz: "buzz", new: "new", delete: "delete", break: "break", continue: "continue",} as const : { readonly foo: "foo"; readonly bar: "bar"; readonly buzz: "buzz"; readonly new: "new"; readonly delete: "delete"; readonly break: "break"; readonly continue: "continue"; } +>{ foo: "foo", bar: "bar", buzz: "buzz", new: "new", delete: "delete", break: "break", continue: "continue",} : { readonly foo: "foo"; readonly bar: "bar"; readonly buzz: "buzz"; readonly new: "new"; readonly delete: "delete"; readonly break: "break"; readonly continue: "continue"; } + + foo: "foo", +>foo : "foo" +>"foo" : "foo" + + bar: "bar", +>bar : "bar" +>"bar" : "bar" + + buzz: "buzz", +>buzz : "buzz" +>"buzz" : "buzz" + + new: "new", +>new : "new" +>"new" : "new" + + delete: "delete", +>delete : "delete" +>"delete" : "delete" + + break: "break", +>break : "break" +>"break" : "break" + + continue: "continue", +>continue : "continue" +>"continue" : "continue" + +} as const; + diff --git a/testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityIncreaseDecrease.baseline b/testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityIncreaseDecrease.baseline new file mode 100644 index 000000000..d68ecd767 --- /dev/null +++ b/testdata/baselines/reference/fourslash/quickInfo/quickinfoVerbosityIncreaseDecrease.baseline @@ -0,0 +1,179 @@ +// === QuickInfo === +=== /quickinfoVerbosityIncreaseDecrease.ts === +// export const JOB_STATES = ["created", "active", "completed", "failed", "retry", "cancelled", "archive"] as const +// export type JobState = (typeof JOB_STATES)[number] +// type Color = "default" | "primary" | "secondary" | "success" | "warning" | "danger" +// const JobsStateToColor: Record< +// ^^^^^^^^^^^^^^^^ +// | ---------------------------------------------------------------------- +// | ```typescript +// | const JobsStateToColor: Record<"active" | "archive" | "cancelled" | "completed" | "created" | "failed" | "retry", { +// | color: Color; +// | label: string; +// | labelPlural: string; +// | }> +// | ``` +// | +// | (verbosity level: 0) +// | ---------------------------------------------------------------------- +// ^^^^^^^^^^^^^^^^ +// | ---------------------------------------------------------------------- +// | ```typescript +// | const JobsStateToColor: Record<"active" | "archive" | "cancelled" | "completed" | "created" | "failed" | "retry", { +// | color: "danger" | "default" | "primary" | "secondary" | "success" | "warning"; +// | label: string; +// | labelPlural: string; +// | }> +// | ``` +// | +// | (verbosity level: 1) +// | ---------------------------------------------------------------------- +// ^^^^^^^^^^^^^^^^ +// | ---------------------------------------------------------------------- +// | ```typescript +// | const JobsStateToColor: Record<"active" | "archive" | "cancelled" | "completed" | "created" | "failed" | "retry", { +// | color: Color; +// | label: string; +// | labelPlural: string; +// | }> +// | ``` +// | +// | (verbosity level: 0) +// | ---------------------------------------------------------------------- +// JobState, +// { +// color: Color +// label: string +// labelPlural: string +// } +// > = { +// created: { +// color: "success", +// label: "Направљен", +// labelPlural: "Направљени", +// }, +// active: { +// color: "success", +// label: "Активан", +// labelPlural: "Активни", +// }, +// completed: { +// color: "success", +// label: "Успешан", +// labelPlural: "Успешни", +// }, +// cancelled: { +// color: "default", +// label: "Отаказан", +// labelPlural: "Отаказни", +// }, +// failed: { +// color: "danger", +// label: "Пао", +// labelPlural: "Пали", +// }, +// archive: { +// color: "default", +// label: "Архивиран", +// labelPlural: "Архивирани", +// }, +// retry: { +// color: "warning", +// label: "Понавља се", +// labelPlural: "Понављају се", +// }, +// } +[ + { + "marker": { + "Position": 270, + "LSPosition": { + "line": 3, + "character": 22 + }, + "Name": "a", + "Data": {} + }, + "item": { + "hover": { + "contents": { + "kind": "markdown", + "value": "```typescript\nconst JobsStateToColor: Record<\"active\" | \"archive\" | \"cancelled\" | \"completed\" | \"created\" | \"failed\" | \"retry\", {\n color: Color;\n label: string;\n labelPlural: string;\n}>\n```\n" + }, + "range": { + "start": { + "line": 3, + "character": 6 + }, + "end": { + "line": 3, + "character": 22 + } + }, + "canIncreaseVerbosity": true + }, + "verbosityLevel": 0 + } + }, + { + "marker": { + "Position": 270, + "LSPosition": { + "line": 3, + "character": 22 + }, + "Name": "a", + "Data": {} + }, + "item": { + "hover": { + "contents": { + "kind": "markdown", + "value": "```typescript\nconst JobsStateToColor: Record<\"active\" | \"archive\" | \"cancelled\" | \"completed\" | \"created\" | \"failed\" | \"retry\", {\n color: \"danger\" | \"default\" | \"primary\" | \"secondary\" | \"success\" | \"warning\";\n label: string;\n labelPlural: string;\n}>\n```\n" + }, + "range": { + "start": { + "line": 3, + "character": 6 + }, + "end": { + "line": 3, + "character": 22 + } + } + }, + "verbosityLevel": 1 + } + }, + { + "marker": { + "Position": 270, + "LSPosition": { + "line": 3, + "character": 22 + }, + "Name": "a", + "Data": {} + }, + "item": { + "hover": { + "contents": { + "kind": "markdown", + "value": "```typescript\nconst JobsStateToColor: Record<\"active\" | \"archive\" | \"cancelled\" | \"completed\" | \"created\" | \"failed\" | \"retry\", {\n color: Color;\n label: string;\n labelPlural: string;\n}>\n```\n" + }, + "range": { + "start": { + "line": 3, + "character": 6 + }, + "end": { + "line": 3, + "character": 22 + } + }, + "canIncreaseVerbosity": true + }, + "verbosityLevel": 0 + } + } +] \ No newline at end of file diff --git a/testdata/baselines/reference/submodule/compiler/emitMethodCalledNew.js b/testdata/baselines/reference/submodule/compiler/emitMethodCalledNew.js index efdabd60c..78289a620 100644 --- a/testdata/baselines/reference/submodule/compiler/emitMethodCalledNew.js +++ b/testdata/baselines/reference/submodule/compiler/emitMethodCalledNew.js @@ -35,5 +35,5 @@ export declare const b: { "new"(x: number): number; }; export declare const c: { - ["new"](x: number): number; + "new"(x: number): number; }; diff --git a/testdata/baselines/reference/submoduleAccepted/compiler/emitMethodCalledNew.js.diff b/testdata/baselines/reference/submoduleAccepted/compiler/emitMethodCalledNew.js.diff deleted file mode 100644 index ed1cf0b92..000000000 --- a/testdata/baselines/reference/submoduleAccepted/compiler/emitMethodCalledNew.js.diff +++ /dev/null @@ -1,9 +0,0 @@ ---- old.emitMethodCalledNew.js -+++ new.emitMethodCalledNew.js -@@= skipped -34, +34 lines =@@ - "new"(x: number): number; - }; - export declare const c: { -- "new"(x: number): number; -+ ["new"](x: number): number; - }; \ No newline at end of file diff --git a/testdata/submoduleAccepted.txt b/testdata/submoduleAccepted.txt index c31d58751..f091352ae 100644 --- a/testdata/submoduleAccepted.txt +++ b/testdata/submoduleAccepted.txt @@ -374,7 +374,6 @@ compiler/declarationEmitDefaultExportWithStaticAssignment.symbols.diff compiler/declarationEmitDefaultExportWithStaticAssignment.types.diff compiler/decoratorMetadataTypeOnlyExport.symbols.diff compiler/decoratorMetadataTypeOnlyImport.symbols.diff -compiler/emitMethodCalledNew.js.diff compiler/es6ImportWithJsDocTags.symbols.diff compiler/es2018ObjectAssign.types.diff compiler/expandoFunctionSymbolPropertyJs.js.diff diff --git a/testdata/tests/cases/compiler/declarationEmitKeywordPropertyNames.ts b/testdata/tests/cases/compiler/declarationEmitKeywordPropertyNames.ts new file mode 100644 index 000000000..5ba3823f9 --- /dev/null +++ b/testdata/tests/cases/compiler/declarationEmitKeywordPropertyNames.ts @@ -0,0 +1,22 @@ +// @declaration: true +// @emitDeclarationOnly: true + +export const a = { + foo: "foo", + bar: "bar", + buzz: "buzz", + new: "new", + delete: "delete", + break: "break", + continue: "continue", +}; + +export const b = { + foo: "foo", + bar: "bar", + buzz: "buzz", + new: "new", + delete: "delete", + break: "break", + continue: "continue", +} as const;