From a24024d639cb504e03ade6ba80cabdfb3466dd56 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Fri, 10 Apr 2026 22:16:18 -0700 Subject: [PATCH 1/3] Add ID fix --- internal/ast/utilities.go | 3 + internal/checker/exports.go | 32 + internal/checker/printer.go | 5 + .../fourslash/_scripts/convertFourslash.mts | 14 +- internal/fourslash/_scripts/failingTests.txt | 441 +----- internal/fourslash/_scripts/unparsedTests.txt | 51 - internal/fourslash/fourslash.go | 251 +++ .../fourslash/tests/basicQuickInfo_test.go | 2 +- ...ixMissingTypeAnnotationOnExports10_test.go | 37 + ...nnotationOnExports17-unique-symbol_test.go | 28 + ...ixMissingTypeAnnotationOnExports18_test.go | 34 + ...ixMissingTypeAnnotationOnExports19_test.go | 34 + ...ixMissingTypeAnnotationOnExports20_test.go | 33 + ...ationOnExports21-params-and-return_test.go | 62 + ...peAnnotationOnExports22-formatting_test.go | 35 + ...onOnExports26-fn-in-object-literal_test.go | 44 + ...onOnExports27-non-exported-bidings_test.go | 34 + ...ngTypeAnnotationOnExports29-inline_test.go | 37 + ...FixMissingTypeAnnotationOnExports2_test.go | 32 + ...nnotationOnExports30-inline-import_test.go | 40 + ...ationOnExports32-inline-short-hand_test.go | 42 + ...nnotationOnExports34-object-spread_test.go | 80 + ...tionOnExports35-variable-releative_test.go | 30 + ...AnnotationOnExports37-array-spread_test.go | 87 ++ ...onOnExports38-unique-symbol-return_test.go | 33 + ...nExports39-extract-arr-to-variable_test.go | 64 + ...FixMissingTypeAnnotationOnExports3_test.go | 37 + ...xports40-extract-other-to-variable_test.go | 53 + ...rts42-static-readonly-class-symbol_test.go | 33 + ...ionOnExports43-expando-functions-2_test.go | 37 + ...ionOnExports43-expando-functions-3_test.go | 37 + ...ionOnExports43-expando-functions-4_test.go | 38 + ...ionOnExports43-expando-functions-5_test.go | 44 + ...ationOnExports43-expando-functions_test.go | 37 + ...notationOnExports44-default-export_test.go | 30 + ...peAnnotationOnExports45-decorators_test.go | 79 + ...nExports46-decorators-experimental_test.go | 78 + ...ixMissingTypeAnnotationOnExports47_test.go | 56 + ...ixMissingTypeAnnotationOnExports48_test.go | 56 + ...AnnotationOnExports49-private-name_test.go | 59 + ...FixMissingTypeAnnotationOnExports4_test.go | 36 + ...nOnExports50-generics-with-default_test.go | 30 + ...more-complex-generics-with-default_test.go | 33 + ...orts52-generics-oversimplification_test.go | 33 + ...onOnExports53-nested-generic-types_test.go | 33 + ...tionOnExports54-generator-generics_test.go | 32 + ...tationOnExports55-generator-return_test.go | 32 + ...otationOnExports56-toplevel-import_test.go | 42 + ...erics-doesnt-drop-trailing-unknown_test.go | 34 + ...rcs-doesnt-drop-trailing-unknown-2_test.go | 32 + ...rts59-drops-unneeded-after-unknown_test.go | 33 + ...FixMissingTypeAnnotationOnExports5_test.go | 36 + ...rops-unneeded-non-trailing-unknown_test.go | 33 + ...FixMissingTypeAnnotationOnExports6_test.go | 29 + ...FixMissingTypeAnnotationOnExports7_test.go | 31 + ...FixMissingTypeAnnotationOnExports8_test.go | 30 + ...FixMissingTypeAnnotationOnExports9_test.go | 35 + ...eAnnotationOnExportsTypePredicate1_test.go | 32 + ...eFixMissingTypeAnnotationOnExports_test.go | 29 + internal/ls/autoimport/import_adder.go | 13 +- internal/ls/change/delete.go | 2 +- internal/ls/change/tracker.go | 46 +- internal/ls/change/trackerimpl.go | 62 +- internal/ls/codeactions.go | 1 + .../codeactions_fixmissingtypeannotation.go | 1355 +++++++++++++++++ internal/printer/changetrackerwriter.go | 5 +- internal/printer/printer.go | 5 +- internal/testrunner/test_case_parser.go | 18 +- .../autoImportFileExcludePatterns.baseline.md | 2 +- ...oImportSpecifierExcludeRegexes.baseline.md | 2 +- ...LensFunctionsAndConstants01.baseline.jsonc | 3 +- .../codeLensOverloads01.baseline.jsonc | 1 + ...ShowOnAllClassMethods=false.baseline.jsonc | 10 +- ...sShowOnAllClassMethods=true.baseline.jsonc | 24 +- ...cesShowOnAllFunctions=false.baseline.jsonc | 4 +- ...ncesShowOnAllFunctions=true.baseline.jsonc | 7 +- ...howOnInterfaceMethods=false.baseline.jsonc | 7 +- ...ShowOnInterfaceMethods=true.baseline.jsonc | 21 +- .../getOccurrencesDeclare3.baseline.jsonc | 20 +- .../getOccurrencesExport3.baseline.jsonc | 15 +- .../jsdocTypedefTagNavigateTo.baseline | 1 + ...initionObjectBindingPattern.baseline.jsonc | 23 +- ...ionObjectBindingPatternRest.baseline.jsonc | 1 + .../goToTypeWithTupleTypes1.baseline.jsonc | 2 + .../destructuredInterfaceJSDoc.baseline | 33 +- ...tructuredInterfaceJSDocWithRename.baseline | 17 +- .../destructuredWithOwnJSDoc.baseline | 17 +- .../hoverNilBaseSymbolIntersection.baseline | 9 +- .../signatureHelpBindingPattern.baseline | 41 +- ...onMapsRenameWithProjectReferences.baseline | 3 + ...psRenameWithProjectReferencesEdit.baseline | 3 + ...enameWithProjectReferencesEditEnd.baseline | 3 + ...indAllRefsRootOfReferencedProject.baseline | 3 + .../privatePropertyOfUndefinedThis1.baseline | 5 +- .../privatePropertyOfUndefinedThis2.baseline | 5 +- ...terStringCompletionsInNestedCall2.baseline | 5 +- .../jsdocCallbackTagRename01.baseline.jsonc | 1 + ...docCallbackTagRename01.baseline.jsonc.diff | 6 +- .../jsdocTypedefTagRename01.baseline.jsonc | 5 +- ...sdocTypedefTagRename01.baseline.jsonc.diff | 12 +- .../jsdocTypedefTagRename02.baseline.jsonc | 2 + ...sdocTypedefTagRename02.baseline.jsonc.diff | 10 +- .../jsdocTypedefTagRename03.baseline.jsonc | 2 + ...sdocTypedefTagRename03.baseline.jsonc.diff | 12 +- 104 files changed, 4035 insertions(+), 693 deletions(-) create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports10_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports17-unique-symbol_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports18_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports19_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports20_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports21-params-and-return_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports22-formatting_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports26-fn-in-object-literal_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports27-non-exported-bidings_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports29-inline_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports2_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports30-inline-import_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports32-inline-short-hand_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports34-object-spread_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports35-variable-releative_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports37-array-spread_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports38-unique-symbol-return_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports39-extract-arr-to-variable_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports3_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports40-extract-other-to-variable_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports42-static-readonly-class-symbol_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions-2_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions-3_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions-4_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions-5_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports44-default-export_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports45-decorators_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports46-decorators-experimental_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports47_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports48_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports49-private-name_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports4_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports50-generics-with-default_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports51-slightly-more-complex-generics-with-default_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports52-generics-oversimplification_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports53-nested-generic-types_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports54-generator-generics_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports55-generator-return_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports56-toplevel-import_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports57-generics-doesnt-drop-trailing-unknown_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports58-genercs-doesnt-drop-trailing-unknown-2_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports59-drops-unneeded-after-unknown_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports5_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports60-drops-unneeded-non-trailing-unknown_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports6_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports7_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports8_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports9_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExportsTypePredicate1_test.go create mode 100644 internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports_test.go create mode 100644 internal/ls/codeactions_fixmissingtypeannotation.go diff --git a/internal/ast/utilities.go b/internal/ast/utilities.go index 85d5dfab8ff..faebec87488 100644 --- a/internal/ast/utilities.go +++ b/internal/ast/utilities.go @@ -3062,6 +3062,9 @@ func IsJSDocSingleCommentNodeList(nodeList *NodeList) bool { return false } parent := nodeList.Nodes[0].Parent + if parent == nil { + return false + } return IsJSDocSingleCommentNode(parent) && nodeList == parent.CommentList() } diff --git a/internal/checker/exports.go b/internal/checker/exports.go index 1f4e49e6787..aa6f00ed212 100644 --- a/internal/checker/exports.go +++ b/internal/checker/exports.go @@ -266,3 +266,35 @@ func (c *Checker) GetIndexInfosOfType(t *Type) []*IndexInfo { func (c *Checker) IsContextSensitive(node *ast.Node) bool { return c.isContextSensitive(node) } + +func (c *Checker) FillMissingTypeArguments(typeArguments []*Type, typeParameters []*Type, minTypeArgumentCount int, isJavaScriptImplicitAny bool) []*Type { + return c.fillMissingTypeArguments(typeArguments, typeParameters, minTypeArgumentCount, isJavaScriptImplicitAny) +} + +func (c *Checker) GetMinTypeArgumentCount(typeParameters []*Type) int { + return c.getMinTypeArgumentCount(typeParameters) +} + +func (c *Checker) GetWidenedLiteralType(t *Type) *Type { + return c.getWidenedLiteralType(t) +} + +func (c *Checker) IsTypeAssignableTo(source *Type, target *Type) bool { + return c.isTypeAssignableTo(source, target) +} + +func (c *Checker) GetUnionTypeEx(types []*Type, unionReduction UnionReduction) *Type { + return c.getUnionTypeEx(types, unionReduction, nil, nil) +} + +func (c *Checker) RequiresAddingImplicitUndefined(node *ast.Node) bool { + enclosingDeclaration := ast.FindAncestor(node, ast.IsDeclaration) + if enclosingDeclaration == nil { + enclosingDeclaration = ast.GetSourceFileOfNode(node).AsNode() + } + symbol := node.Symbol() + if symbol == nil { + return false + } + return c.GetEmitResolver().RequiresAddingImplicitUndefined(node, symbol, enclosingDeclaration) +} diff --git a/internal/checker/printer.go b/internal/checker/printer.go index 1819f8b26b4..a56e244f911 100644 --- a/internal/checker/printer.go +++ b/internal/checker/printer.go @@ -381,6 +381,11 @@ func (c *Checker) TypeToTypeNode(t *Type, enclosingDeclaration *ast.Node, flags return nodeBuilder.TypeToTypeNode(t, enclosingDeclaration, flags, nodebuilder.InternalFlagsNone, nil) } +func (c *Checker) TypeToTypeNodeEx(t *Type, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, internalFlags nodebuilder.InternalFlags, idToSymbol map[*ast.IdentifierNode]*ast.Symbol) *ast.TypeNode { + nodeBuilder := c.getNodeBuilderEx(idToSymbol) + return nodeBuilder.TypeToTypeNode(t, enclosingDeclaration, flags, internalFlags, nil) +} + func (c *Checker) TypePredicateToTypePredicateNode(t *TypePredicate, enclosingDeclaration *ast.Node, flags nodebuilder.Flags, idToSymbol map[*ast.IdentifierNode]*ast.Symbol) *ast.TypePredicateNodeNode { nodeBuilder := c.getNodeBuilderEx(idToSymbol) return nodeBuilder.TypePredicateToTypePredicateNode(t, enclosingDeclaration, flags, nodebuilder.InternalFlagsNone, nil) diff --git a/internal/fourslash/_scripts/convertFourslash.mts b/internal/fourslash/_scripts/convertFourslash.mts index f5341c73b0a..d91908e8628 100755 --- a/internal/fourslash/_scripts/convertFourslash.mts +++ b/internal/fourslash/_scripts/convertFourslash.mts @@ -32,6 +32,7 @@ const IMPORT_UTIL = `. "github.com/microsoft/typescript-go/internal/fourslash/te // Tests for code fixes not in this set will be skipped during conversion. const allowedCodeFixIds = new Set([ "fixMissingImport", + "fixMissingTypeAnnotationOnExports", ]); // File name prefixes for code fix tests that are allowed even without a fixId. @@ -42,6 +43,15 @@ const allowedCodeFixDescriptionPrefixes = [ "Add import from ", "Update import from ", "Change 'import' to 'import type'", + "Add annotation of type", + "Add return type", + "Add satisfies and an inline type assertion", + "Annotate types of properties expando function", + "Extract default export to variable", + "Extract base class to variable", + "Extract binding expressions to variable", + "Extract to variable and replace with", + "Mark array literal as const", ]; function getManualTests(): Set { @@ -1857,7 +1867,7 @@ function parseUserPreferences(arg: ts.ObjectLiteralExpression): string { break; case "organizeImportsTypeOrder": if (!ts.isStringLiteralLike(prop.initializer)) { - return undefined; + throw new Error(`Expected string literal for organizeImportsTypeOrder, got ${prop.initializer.getText()}`); } switch (prop.initializer.text) { case "last": @@ -1870,7 +1880,7 @@ function parseUserPreferences(arg: ts.ObjectLiteralExpression): string { preferences.push(`OrganizeImportsTypeOrder: lsutil.OrganizeImportsTypeOrderFirst`); break; default: - return undefined; + throw new Error(`Unsupported organizeImportsTypeOrder value: ${prop.initializer.text}`); } break; case "autoImportFileExcludePatterns": diff --git a/internal/fourslash/_scripts/failingTests.txt b/internal/fourslash/_scripts/failingTests.txt index 0f5021480b3..8b137891791 100644 --- a/internal/fourslash/_scripts/failingTests.txt +++ b/internal/fourslash/_scripts/failingTests.txt @@ -1,440 +1 @@ -TestAliasMergingWithNamespace -TestAllowLateBoundSymbolsOverwriteEarlyBoundSymbols -TestAmbientShorthandGotoDefinition -TestArgumentsAreAvailableAfterEditsAtEndOfFunction -TestAugmentedTypesClass1 -TestAutoImportAllowImportingTsExtensionsPackageJsonImports1 -TestAutoImportCompletionAmbientMergedModule1 -TestAutoImportCompletionExportListAugmentation1 -TestAutoImportCompletionExportListAugmentation2 -TestAutoImportCompletionExportListAugmentation3 -TestAutoImportCompletionExportListAugmentation4 -TestAutoImportCrossProject_symlinks_stripSrc -TestAutoImportCrossProject_symlinks_toDist -TestAutoImportFileExcludePatterns3 -TestAutoImportJsDocImport1 -TestAutoImportModuleNone2 -TestAutoImportNodeModuleSymlinkRenamed -TestAutoImportNodeNextJSRequire -TestAutoImportPackageJsonImportsCaseSensitivity -TestAutoImportPackageRootPath -TestAutoImportPathsNodeModules -TestAutoImportProvider_exportMap2 -TestAutoImportProvider_exportMap9 -TestAutoImportProvider_globalTypingsCache -TestAutoImportProvider9 -TestAutoImportRelativePathToMonorepoPackage -TestAutoImportSortCaseSensitivity1 -TestAutoImportTypeImport4 -TestAutoImportTypeOnlyPreferred3 -TestAutoImportVerbatimTypeOnly1 -TestBestCommonTypeObjectLiterals -TestBestCommonTypeObjectLiterals1 -TestCalledUnionsOfDissimilarTyeshaveGoodDisplay -TestCloduleTypeOf1 -TestCodeCompletionEscaping -TestCommentsEnumsFourslash -TestCommentsExternalModulesFourslash -TestCommentsImportDeclaration -TestCommentsInheritanceFourslash -TestCommentsInterfaceFourslash -TestCommentsLinePreservation -TestCommentsOverloadsFourslash -TestCommentsUnion -TestCommentsVariables -TestCompletionAfterQuestionDot -TestCompletionAutoInsertQuestionDot -TestCompletionBeforeSemanticDiagnosticsInArrowFunction1 -TestCompletionCloneQuestionToken -TestCompletionEntryClassMembersWithInferredFunctionReturnType1 -TestCompletionEntryForArgumentConstrainedToString -TestCompletionEntryForArrayElementConstrainedToString -TestCompletionEntryForArrayElementConstrainedToString2 -TestCompletionEntryForUnionProperty -TestCompletionEntryForUnionProperty2 -TestCompletionForComputedStringProperties -TestCompletionForMetaProperty -TestCompletionForObjectProperty -TestCompletionForStringLiteral -TestCompletionForStringLiteral_quotePreference -TestCompletionForStringLiteral_quotePreference1 -TestCompletionForStringLiteral_quotePreference2 -TestCompletionForStringLiteral_quotePreference3 -TestCompletionForStringLiteral_quotePreference4 -TestCompletionForStringLiteral_quotePreference5 -TestCompletionForStringLiteral_quotePreference6 -TestCompletionForStringLiteral_quotePreference7 -TestCompletionForStringLiteral_quotePreference8 -TestCompletionForStringLiteral4 -TestCompletionImportMeta -TestCompletionImportMetaWithGlobalDeclaration -TestCompletionImportModuleSpecifierEndingUnsupportedExtension -TestCompletionInChecks1 -TestCompletionInFunctionLikeBody_includesPrimitiveTypes -TestCompletionInUncheckedJSFile -TestCompletionListBuilderLocations_VariableDeclarations -TestCompletionListForDerivedType1 -TestCompletionListInArrowFunctionInUnclosedCallSite01 -TestCompletionListInClassExpressionWithTypeParameter -TestCompletionListInNamedClassExpression -TestCompletionListInNamedClassExpressionWithShadowing -TestCompletionListInNamedFunctionExpression -TestCompletionListInNamedFunctionExpression1 -TestCompletionListInNamedFunctionExpressionWithShadowing -TestCompletionListInScope -TestCompletionListInScope_doesNotIncludeAugmentations -TestCompletionListInTemplateLiteralParts1 -TestCompletionListInUnclosedCommaExpression01 -TestCompletionListInUnclosedCommaExpression02 -TestCompletionListInUnclosedFunction08 -TestCompletionListInUnclosedFunction09 -TestCompletionListInUnclosedTaggedTemplate01 -TestCompletionListInUnclosedTaggedTemplate02 -TestCompletionListInUnclosedTemplate01 -TestCompletionListInUnclosedTemplate02 -TestCompletionListInvalidMemberNames -TestCompletionListInvalidMemberNames_escapeQuote -TestCompletionListInvalidMemberNames_startWithSpace -TestCompletionListInvalidMemberNames_withExistingIdentifier -TestCompletionListInvalidMemberNames2 -TestCompletionListOfGenericSymbol -TestCompletionListOnAliases -TestCompletionListsStringLiteralTypeAsIndexedAccessTypeObject -TestCompletionListStringParenthesizedExpression -TestCompletionListStringParenthesizedType -TestCompletionListWithoutVariableinitializer -TestCompletionNoAutoInsertQuestionDotForThis -TestCompletionNoAutoInsertQuestionDotForTypeParameter -TestCompletionNoAutoInsertQuestionDotWithUserPreferencesOff -TestCompletionOfAwaitPromise1 -TestCompletionOfAwaitPromise2 -TestCompletionOfAwaitPromise3 -TestCompletionOfAwaitPromise5 -TestCompletionOfAwaitPromise6 -TestCompletionOfAwaitPromise7 -TestCompletionOfInterfaceAndVar -TestCompletionPreferredSuggestions1 -TestCompletionsBeforeRestArg1 -TestCompletionsClassMemberImportTypeNodeParameter1 -TestCompletionsClassMemberImportTypeNodeParameter2 -TestCompletionsClassMemberImportTypeNodeParameter3 -TestCompletionsClassMemberImportTypeNodeParameter4 -TestCompletionsElementAccessNumeric -TestCompletionsExportImport -TestCompletionsGenericTypeWithMultipleBases1 -TestCompletionsImport_default_anonymous -TestCompletionsImport_details_withMisspelledName -TestCompletionsImport_exportEquals_global -TestCompletionsImport_filteredByInvalidPackageJson_direct -TestCompletionsImport_filteredByPackageJson_direct -TestCompletionsImport_filteredByPackageJson_nested -TestCompletionsImport_filteredByPackageJson_peerDependencies -TestCompletionsImport_filteredByPackageJson_typesImplicit -TestCompletionsImport_filteredByPackageJson_typesOnly -TestCompletionsImport_named_didNotExistBefore -TestCompletionsImport_noSemicolons -TestCompletionsImport_quoteStyle -TestCompletionsImport_umdDefaultNoCrash1 -TestCompletionsImport_uriStyleNodeCoreModules2 -TestCompletionsImport_uriStyleNodeCoreModules3 -TestCompletionsImport_windowsPathsProjectRelative -TestCompletionsImportOrExportSpecifier -TestCompletionsInExport -TestCompletionsInExport_moduleBlock -TestCompletionsJSDocNoCrash1 -TestCompletionsJsdocTypeTagCast -TestCompletionsJsxAttributeInitializer2 -TestCompletionsLiteralFromInferenceWithinInferredType3 -TestCompletionsLiterals -TestCompletionsMergedDeclarations1 -TestCompletionsNewTarget -TestCompletionsOptionalMethod -TestCompletionsOverridingMethod1 -TestCompletionsOverridingMethod10 -TestCompletionsOverridingMethod11 -TestCompletionsOverridingMethod14 -TestCompletionsOverridingMethod17 -TestCompletionsOverridingMethod2 -TestCompletionsOverridingMethod3 -TestCompletionsOverridingMethod4 -TestCompletionsOverridingMethod9 -TestCompletionsOverridingMethodCrash1 -TestCompletionsOverridingProperties1 -TestCompletionsRecommended_namespace -TestCompletionsRecommended_union -TestCompletionsRedeclareModuleAsGlobal -TestCompletionsStringsWithTriggerCharacter -TestCompletionsSymbolMembers -TestCompletionsTriggerCharacter -TestCompletionsTuple -TestCompletionsUniqueSymbol_import -TestCompletionsUniqueSymbol1 -TestCompletionsWithDeprecatedTag10 -TestConstEnumQuickInfoAndCompletionList -TestConstQuickInfoAndCompletionList -TestContextuallyTypedFunctionExpressionGeneric1 -TestContextualTypingOfGenericCallSignatures2 -TestCrossFileQuickInfoExportedTypeDoesNotUseImportType -TestDoubleUnderscoreCompletions -TestEditJsdocType -TestErrorsAfterResolvingVariableDeclOfMergedVariableAndClassDecl -TestExportDefaultClass -TestExportDefaultFunction -TestExportEqualTypes -TestFindAllRefs_importType_js1 -TestFindAllRefs_importType_js2 -TestFindAllRefs_importType_js3 -TestFormatDocumentPreserveTrailingWhitespace -TestFormatDotAfterNumber -TestFormatMultipleFunctionArguments -TestFormatNoSpaceAfterTemplateHeadAndMiddle -TestFormatSelectionPreserveTrailingWhitespace -TestFormatSpaceAfterTemplateHeadAndMiddle -TestFormatSpaceBetweenFunctionAndArrayIndex -TestFormattingObjectLiteralOpenCurlyNewline -TestFormattingObjectLiteralOpenCurlyNewlineAssignment -TestFormattingObjectLiteralOpenCurlyNewlineTyping -TestFormattingObjectLiteralOpenCurlySingleLine -TestFormattingOnInvalidCodes -TestFormattingOnObjectLiteral -TestFormatTsxClosingAfterJsxText -TestFormatV8Directive -TestFunduleWithRecursiveReference -TestGenericCombinators3 -TestGenericCombinatorWithConstraints1 -TestGenericFunctionWithGenericParams1 -TestGenericInterfacePropertyInference1 -TestGenericInterfacePropertyInference2 -TestGenericInterfacesWithConstraints1 -TestGenericsFormattingMultiline -TestGenericTypeWithMultipleBases1MultiFile -TestGetJavaScriptCompletions10 -TestGetJavaScriptCompletions12 -TestGetJavaScriptCompletions13 -TestGetJavaScriptCompletions15 -TestGetJavaScriptCompletions20 -TestGetJavaScriptCompletions8 -TestGetJavaScriptCompletions9 -TestGetJavaScriptGlobalCompletions1 -TestGetJavaScriptQuickInfo1 -TestGetJavaScriptQuickInfo2 -TestGetJavaScriptQuickInfo3 -TestGetJavaScriptQuickInfo4 -TestGetJavaScriptQuickInfo5 -TestGetJavaScriptQuickInfo6 -TestGetJavaScriptQuickInfo7 -TestGetJavaScriptQuickInfo8 -TestGetJavaScriptSyntacticDiagnostics24 -TestGetJSXOutliningSpans -TestHoverOverComment -TestImportCompletionsPackageJsonImportsPatternRootWildcard -TestImportFixesGlobalTypingsCache -TestImportMetaCompletionDetails -TestImportNameCodeFix_externalNonRelative1 -TestImportNameCodeFix_noDestructureNonObjectLiteral -TestImportNameCodeFix_order2 -TestImportNameCodeFix_preferBaseUrl -TestImportNameCodeFix_reExportDefault -TestImportNameCodeFix_require -TestImportNameCodeFix_require_addToExisting -TestImportNameCodeFix_require_importVsRequire_addToExistingWins -TestImportNameCodeFix_symlink_own_package -TestImportNameCodeFix_symlink_own_package_2 -TestImportNameCodeFix_uriStyleNodeCoreModules2 -TestImportNameCodeFix_uriStyleNodeCoreModules3 -TestImportNameCodeFixDefaultExport4 -TestImportNameCodeFixNewImportBaseUrl0 -TestImportNameCodeFixNewImportBaseUrl1 -TestImportNameCodeFixNewImportBaseUrl2 -TestImportNameCodeFixNewImportFile2 -TestImportNameCodeFixNewImportTypeRoots1 -TestImportStatementCompletions_esModuleInterop2 -TestImportStatementCompletions_noSnippet -TestImportStatementCompletions_pnpm1 -TestImportStatementCompletions_quotes -TestImportStatementCompletions_semicolons -TestImportSuggestionsCache_invalidPackageJson -TestImportTypeCompletions1 -TestImportTypeCompletions3 -TestImportTypeCompletions4 -TestImportTypeCompletions6 -TestImportTypeCompletions7 -TestImportTypeCompletions8 -TestImportTypeCompletions9 -TestIndexerReturnTypes1 -TestIndirectClassInstantiation -TestInstanceTypesForGenericType1 -TestJavascriptModules20 -TestJavascriptModules24 -TestJsDocAugments -TestJsDocAugmentsAndExtends -TestJsdocCallbackTag -TestJsDocExtends -TestJsDocFunctionSignatures10 -TestJsDocFunctionSignatures11 -TestJsDocFunctionSignatures13 -TestJsDocFunctionSignatures7 -TestJsDocFunctionSignatures8 -TestJsDocGenerics2 -TestJsDocInheritDoc -TestJsDocPropertyDescription1 -TestJsDocPropertyDescription11 -TestJsDocPropertyDescription4 -TestJsDocPropertyDescription6 -TestJsDocPropertyDescription7 -TestJsDocPropertyDescription9 -TestJsDocServices -TestJsDocTagsWithHyphen -TestJsdocTemplatePrototypeCompletions -TestJsdocTypedefTag -TestJsdocTypedefTag2 -TestJsdocTypedefTagNamespace -TestJsdocTypedefTagServices -TestJsFileImportNoTypes2 -TestJsQuickInfoGenerallyAcceptableSize -TestJsRequireQuickInfo -TestJsxAttributeCompletionStyleAuto -TestJsxAttributeCompletionStyleBraces -TestJsxAttributeCompletionStyleDefault -TestJsxAttributeCompletionStyleNone -TestJsxAttributeCompletionStyleNoSnippet -TestJsxAttributeSnippetCompletionAfterTypeArgs -TestJsxAttributeSnippetCompletionClosed -TestJsxAttributeSnippetCompletionUnclosed -TestJsxGenericQuickInfo -TestJsxWithTypeParametershasInstantiatedSignatureHelp -TestLetQuickInfoAndCompletionList -TestLocalFunction -TestMemberListInReopenedEnum -TestMemberListInWithBlock -TestMemberListOfExportedClass -TestMultiModuleFundule -TestNgProxy1 -TestNgProxy4 -TestNoQuickInfoForLabel -TestNoQuickInfoInWhitespace -TestNumericPropertyNames -TestOverloadQuickInfo -TestProtoVarVisibleWithOuterScopeUnderscoreProto -TestQualifyModuleTypeNames -TestQuickInfo_notInsideComment -TestQuickinfo01 -TestQuickInfoAssertionNodeNotReusedWhenTypeNotEquivalent1 -TestQuickInfoBindingPatternInJsdocNoCrash1 -TestQuickInfoCanBeTruncated -TestQuickInfoClassKeyword -TestQuickInfoCloduleWithRecursiveReference -TestQuickInfoContextuallyTypedSignatureOptionalParameterFromIntersection1 -TestQuickInfoContextualTyping -TestQuickInfoDisplayPartsIife -TestQuickInfoElementAccessDeclaration -TestQuickInfoForConstTypeReference -TestQuickInfoForContextuallyTypedArrowFunctionInSuperCall -TestQuickInfoForContextuallyTypedParameters -TestQuickInfoForGenericConstraints1 -TestQuickInfoForGenericPrototypeMember -TestQuickInfoForGenericTaggedTemplateExpression -TestQuickInfoForGetterAndSetter -TestQuickInfoForIndexerResultWithConstraint -TestQuickinfoForNamespaceMergeWithClassConstrainedToSelf -TestQuickInfoForObjectBindingElementPropertyName04 -TestQuickInfoForShorthandProperty -TestQuickInfoForTypeofParameter -TestQuickInfoForTypeParameterInTypeAlias1 -TestQuickInfoForTypeParameterInTypeAlias2 -TestQuickInfoForUMDModuleAlias -TestQuickinfoForUnionProperty -TestQuickInfoFromContextualUnionType2 -TestQuickInfoFromContextualUnionType3 -TestQuickInfoFunctionKeyword -TestQuickInfoGenerics -TestQuickInfoGetterSetter -TestQuickInfoInInvalidIndexSignature -TestQuickInfoInJsdocInTsFile1 -TestQuickInfoInOptionalChain -TestQuickInfoJSDocBackticks -TestQuickInfoJsdocEnum -TestQuickInfoJSDocFunctionNew -TestQuickInfoJSDocFunctionThis -TestQuickInfoJsDocGetterSetterNoCrash1 -TestQuickInfoJsDocNonDiscriminatedUnionSharedProp -TestQuickInfoJsdocTypedefMissingType -TestQuickInfoJSExport -TestQuickInfoMappedSpreadTypes -TestQuickInfoMappedType -TestQuickInfoMappedTypeRecursiveInference -TestQuickInfoMeaning -TestQuickInfoModuleVariables -TestQuickInfoNarrowedTypeOfAliasSymbol -TestQuickInfoNestedGenericCalls -TestQuickInfoOnArgumentsInsideFunction -TestQuickInfoOnCatchVariable -TestQuickInfoOnClosingJsx -TestQuickInfoOnElementAccessInWriteLocation1 -TestQuickInfoOnElementAccessInWriteLocation2 -TestQuickInfoOnElementAccessInWriteLocation3 -TestQuickInfoOnElementAccessInWriteLocation4 -TestQuickInfoOnElementAccessInWriteLocation5 -TestQuickInfoOnErrorTypes1 -TestQuickInfoOnExpandoLikePropertyWithSetterDeclarationJs1 -TestQuickInfoOnExpandoLikePropertyWithSetterDeclarationJs2 -TestQuickInfoOnFunctionPropertyReturnedFromGenericFunction1 -TestQuickInfoOnFunctionPropertyReturnedFromGenericFunction2 -TestQuickInfoOnFunctionPropertyReturnedFromGenericFunction3 -TestQuickInfoOnGenericWithConstraints1 -TestQuickInfoOnInternalAliases -TestQuickInfoOnJsxNamespacedNameWithDoc1 -TestQuickInfoOnMergedInterfacesWithIncrementalEdits -TestQuickInfoOnMergedModule -TestQuickInfoOnMethodOfImportEquals -TestQuickInfoOnNarrowedTypeInModule -TestQuickInfoOnNewKeyword01 -TestQuickInfoOnObjectLiteralWithAccessors -TestQuickInfoOnObjectLiteralWithOnlyGetter -TestQuickInfoOnObjectLiteralWithOnlySetter -TestQuickInfoOnPropDeclaredUsingIndexSignatureOnInterfaceWithBase -TestQuickInfoOnPropertyAccessInWriteLocation1 -TestQuickInfoOnPropertyAccessInWriteLocation2 -TestQuickInfoOnPropertyAccessInWriteLocation3 -TestQuickInfoOnPropertyAccessInWriteLocation4 -TestQuickInfoOnPropertyAccessInWriteLocation5 -TestQuickInfoOnThis3 -TestQuickInfoOnUndefined -TestQuickInfoOnVarInArrowExpression -TestQuickInfoPrivateIdentifierInTypeReferenceNoCrash1 -TestQuickInfoPropertyTag -TestQuickInforForSucessiveInferencesIsNotAny -TestQuickInfoSignatureOptionalParameterFromUnion1 -TestQuickInfoSignatureRestParameterFromUnion1 -TestQuickInfoSignatureRestParameterFromUnion2 -TestQuickInfoSignatureRestParameterFromUnion3 -TestQuickInfoSignatureRestParameterFromUnion4 -TestQuickInfoSpecialPropertyAssignment -TestQuickInfoStaticPrototypePropertyOnClass -TestQuickInfoTemplateTag -TestQuickInfoTypeAliasDefinedInDifferentFile -TestQuickInfoTypeError -TestQuickInfoTypeOfThisInStatics -TestQuickInfoTypeOnlyNamespaceAndClass -TestQuickInfoUnionOfNamespaces -TestQuickInfoUntypedModuleImport -TestQuickInfoWidenedTypes -TestQuickinfoWrongComment -TestRecursiveInternalModuleImport -TestRegexDetection -TestReverseMappedTypeQuickInfo -TestSelfReferencedExternalModule -TestSignatureHelpCallExpressionJs -TestStringCompletionsImportOrExportSpecifier -TestStringCompletionsVsEscaping -TestSuggestionOfUnusedVariableWithExternalModule -TestSymbolCompletionLowerPriority -TestSyntheticImportFromBabelGeneratedFile1 -TestSyntheticImportFromBabelGeneratedFile2 -TestThisPredicateFunctionQuickInfo01 -TestThisPredicateFunctionQuickInfo02 -TestTsxQuickInfo4 -TestTsxQuickInfo5 -TestTsxQuickInfo6 -TestTsxQuickInfo7 -TestTypeOperatorNodeBuilding + diff --git a/internal/fourslash/_scripts/unparsedTests.txt b/internal/fourslash/_scripts/unparsedTests.txt index 61ba15ce2f7..9011126eb3d 100644 --- a/internal/fourslash/_scripts/unparsedTests.txt +++ b/internal/fourslash/_scripts/unparsedTests.txt @@ -900,71 +900,20 @@ codeFixMissingCallParentheses8.ts parse error: "Code fix test has no allowed fix codeFixMissingCallParentheses9.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" codeFixMissingPrivateIdentifierMethodDeclaration.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" codeFixMissingResolutionModeImportAttribute.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports10.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" codeFixMissingTypeAnnotationOnExports11.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" codeFixMissingTypeAnnotationOnExports12.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" codeFixMissingTypeAnnotationOnExports13.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" codeFixMissingTypeAnnotationOnExports14.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" codeFixMissingTypeAnnotationOnExports15.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" codeFixMissingTypeAnnotationOnExports16.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports17-unique-symbol.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports18.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports19.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports2.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports20.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports21-params-and-return.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports22-formatting.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" codeFixMissingTypeAnnotationOnExports23-heritage-formatting.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" codeFixMissingTypeAnnotationOnExports24-heritage-formatting-2.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" codeFixMissingTypeAnnotationOnExports25-heritage-formatting-3.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports26-fn-in-object-literal.ts parse error: "Unsupported code fix ID: fixMissingTypeAnnotationOnExports" -codeFixMissingTypeAnnotationOnExports27-non-exported-bidings.ts parse error: "Unsupported code fix ID: fixMissingTypeAnnotationOnExports" codeFixMissingTypeAnnotationOnExports28-long-types.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports29-inline.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports3.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports30-inline-import.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" codeFixMissingTypeAnnotationOnExports31-inline-import-default.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports32-inline-short-hand.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" codeFixMissingTypeAnnotationOnExports33-methods.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports34-object-spread.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports35-variable-releative.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" codeFixMissingTypeAnnotationOnExports36-conditional-releative.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports37-array-spread.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports38-unique-symbol-return.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports39-extract-arr-to-variable.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports4.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports40-extract-other-to-variable.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" codeFixMissingTypeAnnotationOnExports41-no-computed-enum-members.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports42-static-readonly-class-symbol.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports43-expando-functions-2.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports43-expando-functions-3.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports43-expando-functions-4.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports43-expando-functions-5.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports43-expando-functions.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports44-default-export.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports45-decorators.ts parse error: "Unsupported code fix ID: fixMissingTypeAnnotationOnExports" -codeFixMissingTypeAnnotationOnExports46-decorators-experimental.ts parse error: "Unsupported code fix ID: fixMissingTypeAnnotationOnExports" -codeFixMissingTypeAnnotationOnExports47.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports48.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports49-private-name.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports5.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports50-generics-with-default.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports51-slightly-more-complex-generics-with-default.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports52-generics-oversimplification.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports53-nested-generic-types.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports54-generator-generics.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports55-generator-return.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports56-toplevel-import.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports57-generics-doesnt-drop-trailing-unknown.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports58-genercs-doesnt-drop-trailing-unknown-2.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports59-drops-unneeded-after-unknown.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports6.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports60-drops-unneeded-non-trailing-unknown.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports7.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports8.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExports9.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" -codeFixMissingTypeAnnotationOnExportsTypePredicate1.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" codeFixNegativeReplaceQualifiedNameWithIndexedAccessType01.ts parse error: "Unrecognized fourslash statement: verify.not.codeFixAvailable(...)" codeFixNoPropertyAccessFromIndexSignature_fixAll.ts parse error: "Unsupported code fix ID: fixNoPropertyAccessFromIndexSignature" codeFixNoPropertyAccessFromIndexSignature1.ts parse error: "Code fix test has no allowed fixId and descriptions do not match any allowed prefix" diff --git a/internal/fourslash/fourslash.go b/internal/fourslash/fourslash.go index c7a6fb0033d..bbf0ffa45d8 100644 --- a/internal/fourslash/fourslash.go +++ b/internal/fourslash/fourslash.go @@ -1813,6 +1813,238 @@ func (f *FourslashTest) VerifyApplyCodeActionFromCompletion(t *testing.T, marker } } +// VerifyCodeFixOptions are the options for VerifyCodeFix. +type VerifyCodeFixOptions struct { + Description string + NewFileContent string + Index int + ApplyChanges bool +} + +// VerifyCodeFixAllOptions are the options for VerifyCodeFixAll. +type VerifyCodeFixAllOptions struct { + FixID string + NewFileContent string +} + +// VerifyCodeFix verifies that applying a code fix produces the expected file content. +func (f *FourslashTest) VerifyCodeFix(t *testing.T, options VerifyCodeFixOptions) { + t.Helper() + + actions := f.getCodeFixActions(t) + + if len(actions) == 0 { + t.Fatalf("No code fixes returned.") + } + if options.Index >= len(actions) { + t.Fatalf("Code fix index %d out of range (got %d fixes)", options.Index, len(actions)) + } + + // In TS, index refers to the Nth fix overall (not per description). + // Description is verified to match the fix at that index. + if options.Index >= len(actions) { + t.Fatalf("Code fix index %d out of range (got %d fixes)", options.Index, len(actions)) + } + matchingAction := actions[options.Index] + if matchingAction.Title != options.Description { + // Try finding by description match as fallback (for tests where diagnostic ordering differs) + found := false + for _, action := range actions { + if action.Title == options.Description { + matchingAction = action + found = true + break + } + } + if !found { + var titles []string + for _, a := range actions { + titles = append(titles, a.Title) + } + t.Fatalf("No code fix with description %q at index %d found. Available fixes: %v", options.Description, options.Index, titles) + } + } + + if options.ApplyChanges { + // Apply changes to the actual file (like TS's applyChanges: true) + if matchingAction.Edit != nil && matchingAction.Edit.Changes != nil { + for _, edits := range *matchingAction.Edit.Changes { + f.applyTextEdits(t, edits) + } + } + actual := f.getScriptInfo(f.activeFilename).content + assert.Equal(t, options.NewFileContent, actual, "File content after applying code fix did not match expected content.") + } else { + // Compute the new content without mutating the file (matching TS behavior where + // verify.codeFix without applyChanges does not modify the file). + actual := f.getScriptInfo(f.activeFilename).content + if matchingAction.Edit != nil && matchingAction.Edit.Changes != nil { + for _, edits := range *matchingAction.Edit.Changes { + actual = f.applyEditsToContent(actual, edits) + } + } + assert.Equal(t, options.NewFileContent, actual, "File content after applying code fix did not match expected content.") + } +} + +// VerifyCodeFixAvailable verifies that code fixes with the given descriptions are available. +func (f *FourslashTest) VerifyCodeFixAvailable(t *testing.T, expectedDescriptions []string) { + t.Helper() + + actions := f.getCodeFixActions(t) + + if expectedDescriptions == nil { + // Just checking that some fixes are available + if len(actions) == 0 { + t.Fatalf("Expected code fixes to be available, but got none.") + } + return + } + + if len(expectedDescriptions) == 0 { + if len(actions) != 0 { + var titles []string + for _, a := range actions { + titles = append(titles, a.Title) + } + t.Fatalf("Expected no code fixes, but got: %v", titles) + } + return + } + + for _, expected := range expectedDescriptions { + found := false + for _, action := range actions { + if action.Title == expected { + found = true + break + } + } + if !found { + var titles []string + for _, a := range actions { + titles = append(titles, a.Title) + } + t.Fatalf("Expected code fix with description %q not found. Available fixes: %v", expected, titles) + } + } +} + +// VerifyCodeFixAll verifies that applying all code fixes with the given fixId produces the expected file content. +// For each diagnostic, it requests code actions and applies only the first one (the annotation fix). +func (f *FourslashTest) VerifyCodeFixAll(t *testing.T, options VerifyCodeFixAllOptions) { + t.Helper() + + applied := false + // Re-fetch diagnostics after each fix application to handle position shifts + for { + diagParams := &lsproto.DocumentDiagnosticParams{ + TextDocument: lsproto.TextDocumentIdentifier{ + Uri: lsconv.FileNameToDocumentURI(f.activeFilename), + }, + } + diagResult := sendRequest(t, f, lsproto.TextDocumentDiagnosticInfo, diagParams) + + var diagnostics []*lsproto.Diagnostic + if diagResult.FullDocumentDiagnosticReport != nil && diagResult.FullDocumentDiagnosticReport.Items != nil { + diagnostics = diagResult.FullDocumentDiagnosticReport.Items + } + + appliedThisRound := false + for _, diag := range diagnostics { + params := &lsproto.CodeActionParams{ + TextDocument: lsproto.TextDocumentIdentifier{ + Uri: lsconv.FileNameToDocumentURI(f.activeFilename), + }, + Range: lsproto.Range{ + Start: diag.Range.Start, + End: diag.Range.End, + }, + Context: &lsproto.CodeActionContext{ + Diagnostics: []*lsproto.Diagnostic{diag}, + }, + } + result := sendRequest(t, f, lsproto.TextDocumentCodeActionInfo, params) + + if result.CommandOrCodeActionArray == nil { + continue + } + // Apply only the first quick fix for each diagnostic + for _, item := range *result.CommandOrCodeActionArray { + if item.CodeAction != nil && item.CodeAction.Kind != nil && *item.CodeAction.Kind == lsproto.CodeActionKindQuickFix { + if item.CodeAction.Edit != nil && item.CodeAction.Edit.Changes != nil { + for _, edits := range *item.CodeAction.Edit.Changes { + f.applyTextEdits(t, edits) + } + applied = true + appliedThisRound = true + } + break // Only apply the first fix per diagnostic + } + } + if appliedThisRound { + break // Re-fetch diagnostics after applying a fix + } + } + if !appliedThisRound { + break // No more fixes to apply + } + } + + if !applied { + t.Fatalf("No code fixes applied for fixId %q", options.FixID) + } + + actual := f.getScriptInfo(f.activeFilename).content + assert.Equal(t, options.NewFileContent, actual, "File content after applying all code fixes did not match expected content.") +} + +// getCodeFixActions gets all quick fix code actions for the current file by gathering diagnostics. +func (f *FourslashTest) getCodeFixActions(t *testing.T) []*lsproto.CodeAction { + t.Helper() + + diagParams := &lsproto.DocumentDiagnosticParams{ + TextDocument: lsproto.TextDocumentIdentifier{ + Uri: lsconv.FileNameToDocumentURI(f.activeFilename), + }, + } + diagResult := sendRequest(t, f, lsproto.TextDocumentDiagnosticInfo, diagParams) + + var diagnostics []*lsproto.Diagnostic + if diagResult.FullDocumentDiagnosticReport != nil && diagResult.FullDocumentDiagnosticReport.Items != nil { + diagnostics = diagResult.FullDocumentDiagnosticReport.Items + } + + if len(diagnostics) == 0 { + return nil + } + + params := &lsproto.CodeActionParams{ + TextDocument: lsproto.TextDocumentIdentifier{ + Uri: lsconv.FileNameToDocumentURI(f.activeFilename), + }, + Range: lsproto.Range{ + Start: diagnostics[0].Range.Start, + End: diagnostics[0].Range.End, + }, + Context: &lsproto.CodeActionContext{ + Diagnostics: diagnostics, + }, + } + result := sendRequest(t, f, lsproto.TextDocumentCodeActionInfo, params) + + var actions []*lsproto.CodeAction + if result.CommandOrCodeActionArray != nil { + for _, item := range *result.CommandOrCodeActionArray { + if item.CodeAction != nil && item.CodeAction.Kind != nil && *item.CodeAction.Kind == lsproto.CodeActionKindQuickFix { + actions = append(actions, item.CodeAction) + } + } + } + + return actions +} + func (f *FourslashTest) VerifyImportFixAtPosition(t *testing.T, expectedTexts []string, preferences *lsutil.UserPreferences) { t.Helper() fileName := f.activeFilename @@ -3207,6 +3439,25 @@ func (f *FourslashTest) getSelection() core.TextRange { ) } +// applyEditsToContent applies text edits to a content string without mutating the file. +// Returns the new content. +func (f *FourslashTest) applyEditsToContent(content string, edits []*lsproto.TextEdit) string { + script := f.getScriptInfo(f.activeFilename) + slices.SortFunc(edits, func(a, b *lsproto.TextEdit) int { + aStart := f.converters.LineAndCharacterToPosition(script, a.Range.Start) + bStart := f.converters.LineAndCharacterToPosition(script, b.Range.Start) + return int(aStart) - int(bStart) + }) + // Apply edits in reverse order to avoid affecting positions + for i := len(edits) - 1; i >= 0; i-- { + edit := edits[i] + start := int(f.converters.LineAndCharacterToPosition(script, edit.Range.Start)) + end := int(f.converters.LineAndCharacterToPosition(script, edit.Range.End)) + content = content[:start] + edit.NewText + content[end:] + } + return content +} + // Updates f.currentCaretPosition func (f *FourslashTest) applyTextEdits(t *testing.T, edits []*lsproto.TextEdit) int { script := f.getScriptInfo(f.activeFilename) diff --git a/internal/fourslash/tests/basicQuickInfo_test.go b/internal/fourslash/tests/basicQuickInfo_test.go index 487ce3fe8f5..32346d6567c 100644 --- a/internal/fourslash/tests/basicQuickInfo_test.go +++ b/internal/fourslash/tests/basicQuickInfo_test.go @@ -29,5 +29,5 @@ class Foo/*3*/ { f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) defer done() f.VerifyQuickInfoAt(t, "1", "var someVar: number", "Some var") - f.VerifyQuickInfoAt(t, "2", "var otherVar: number", "Other var\nSee [someVar](file:///basicQuickInfo.ts#4,5-4,12)") + f.VerifyQuickInfoAt(t, "2", "var otherVar: number", "Other var\nSee [someVar](file:///basicQuickInfo.ts#5,5-5,12)") } diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports10_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports10_test.go new file mode 100644 index 00000000000..dfaf9898db6 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports10_test.go @@ -0,0 +1,37 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports10" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports10(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +function foo() { + return { x: 1, y: 1 }; +} +export default foo();` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Extract default export to variable", + NewFileContent: `function foo() { + return { x: 1, y: 1 }; +} +const _default_1: { + x: number; + y: number; +} = foo(); +export default _default_1;`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports17-unique-symbol_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports17-unique-symbol_test.go new file mode 100644 index 00000000000..4ebc434e01b --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports17-unique-symbol_test.go @@ -0,0 +1,28 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports17-unique-symbol" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports17_unique_symbol(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2019 +export const a = Symbol();` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type 'unique symbol'", + NewFileContent: `export const a: unique symbol = Symbol();`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports18_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports18_test.go new file mode 100644 index 00000000000..7c213b53954 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports18_test.go @@ -0,0 +1,34 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports18" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports18(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +function foo() { return 42; } +export class A { + readonly a = () => foo(); +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFixAvailable(t, []string{"Add return type 'number'"}) + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type 'number'", + NewFileContent: `function foo() { return 42; } +export class A { + readonly a = (): number => foo(); +}`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports19_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports19_test.go new file mode 100644 index 00000000000..0e5bce4985b --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports19_test.go @@ -0,0 +1,34 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports19" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports19(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2019 +export const a = { + z: Symbol() +} as const;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type '{ readonly z: symbol; }'", + NewFileContent: `export const a: { + readonly z: symbol; +} = { + z: Symbol() +} as const;`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports20_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports20_test.go new file mode 100644 index 00000000000..f7d5f9432ea --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports20_test.go @@ -0,0 +1,33 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports20" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports20(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2019 +export function foo () { + return Symbol(); +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFixAvailable(t, []string{"Add return type 'symbol'"}) + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type 'symbol'", + NewFileContent: `export function foo (): symbol { + return Symbol(); +}`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports21-params-and-return_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports21-params-and-return_test.go new file mode 100644 index 00000000000..c6b4b713e00 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports21-params-and-return_test.go @@ -0,0 +1,62 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports21-params-and-return" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports21_params_and_return(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2019 +/** + * Test + */ +export function foo(): number { return 0; } +/** +* Docs +*/ +export const bar = (a = foo()) => + a; +// Trivia` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type 'number'", + NewFileContent: `/** + * Test + */ +export function foo(): number { return 0; } +/** +* Docs +*/ +export const bar = (a = foo()): number => + a; +// Trivia`, + Index: 0, + ApplyChanges: true, + }) + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type 'number'", + NewFileContent: `/** + * Test + */ +export function foo(): number { return 0; } +/** +* Docs +*/ +export const bar = (a: number = foo()): number => + a; +// Trivia`, + Index: 0, + ApplyChanges: true, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports22-formatting_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports22-formatting_test.go new file mode 100644 index 00000000000..1bd36f95f29 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports22-formatting_test.go @@ -0,0 +1,35 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports22-formatting" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports22_formatting(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2019 +/** + * Test + */ +export function foo(){}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFixAvailable(t, []string{"Add return type 'void'"}) + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type 'void'", + NewFileContent: `/** + * Test + */ +export function foo(): void{}`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports26-fn-in-object-literal_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports26-fn-in-object-literal_test.go new file mode 100644 index 00000000000..542121194c3 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports26-fn-in-object-literal_test.go @@ -0,0 +1,44 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports26-fn-in-object-literal" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports26_fn_in_object_literal(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +export const extensions = { + /** + */ + fn: (actualValue: T, expectedValue: T) => { + return actualValue === expectedValue + }, + fn2: function(actualValue: T, expectedValue: T) { + return actualValue === expectedValue + } +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFixAll(t, fourslash.VerifyCodeFixAllOptions{ + FixID: "fixMissingTypeAnnotationOnExports", + NewFileContent: `export const extensions = { + /** + */ + fn: (actualValue: T, expectedValue: T): boolean => { + return actualValue === expectedValue + }, + fn2: function(actualValue: T, expectedValue: T): boolean { + return actualValue === expectedValue + } +}`, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports27-non-exported-bidings_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports27-non-exported-bidings_test.go new file mode 100644 index 00000000000..ab72f933fc6 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports27-non-exported-bidings_test.go @@ -0,0 +1,34 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports27-non-exported-bidings" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports27_non_exported_bidings(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +let p = { x: 1, y: 2} +const a = 1, b = 10, { x, y } = p, c = 1; +export { x, y } +export const d = a + b + c;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFixAll(t, fourslash.VerifyCodeFixAllOptions{ + FixID: "fixMissingTypeAnnotationOnExports", + NewFileContent: `let p = { x: 1, y: 2} +const x: number = p.x; +const y: number = p.y; +const a = 1, b = 10, c = 1; +export { x, y } +export const d: number = a + b + c;`, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports29-inline_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports29-inline_test.go new file mode 100644 index 00000000000..6e6f04ee7bd --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports29-inline_test.go @@ -0,0 +1,37 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports29-inline" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports29_inline(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +function getString() { + return "" +} +export const exp = { + prop: getString() +};` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add satisfies and an inline type assertion with 'string'", + NewFileContent: `function getString() { + return "" +} +export const exp = { + prop: getString() satisfies string as string +};`, + Index: 1, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports2_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports2_test.go new file mode 100644 index 00000000000..eb3794b99c1 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports2_test.go @@ -0,0 +1,32 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports2" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports2(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +const a = 42; +const b = 43; +export function foo() { return a + b; }` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFixAvailable(t, []string{"Add return type 'number'"}) + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type 'number'", + NewFileContent: `const a = 42; +const b = 43; +export function foo(): number { return a + b; }`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports30-inline-import_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports30-inline-import_test.go new file mode 100644 index 00000000000..c3cb88695fc --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports30-inline-import_test.go @@ -0,0 +1,40 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports30-inline-import" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports30_inline_import(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @Filename: /person-code.ts +export type Person = { x: string; } +export function getPerson() : Person { + return null! +} +// @Filename: /code.ts +import { getPerson } from "./person-code"; +export const exp = { + person: getPerson() +};` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.GoToFile(t, "/code.ts") + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add satisfies and an inline type assertion with 'Person'", + NewFileContent: `import { getPerson, Person } from "./person-code"; +export const exp = { + person: getPerson() satisfies Person as Person +};`, + Index: 1, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports32-inline-short-hand_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports32-inline-short-hand_test.go new file mode 100644 index 00000000000..b74e2637625 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports32-inline-short-hand_test.go @@ -0,0 +1,42 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports32-inline-short-hand" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports32_inline_short_hand(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @Filename: /code.ts +const x = 1; +export default { + x +};` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add satisfies and an inline type assertion with 'number'", + NewFileContent: `const x = 1; +export default { + x: x as number +};`, + Index: 1, + }) + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add satisfies and an inline type assertion with 'typeof x'", + NewFileContent: `const x = 1; +export default { + x: x as typeof x +};`, + Index: 2, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports34-object-spread_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports34-object-spread_test.go new file mode 100644 index 00000000000..fe13e1f66be --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports34-object-spread_test.go @@ -0,0 +1,80 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports34-object-spread" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports34_object_spread(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @Filename: /code.ts +const Start = { + A: 'A', + B: 'B', +} as const; + +const End = { + Y: "Y", + Z: "Z" +} as const; +export const All_Part1 = {}; +function getPart() { + return { M: "Z"} +} + +export const All = { + x: 1, + ...Start, + y: 1, + ...getPart(), + ...End, + z: 1, +};` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type 'typeof All_Part1_1 & typeof Start & typeof All_Part3 & typeof All_Part4 & typeof End & typeof All_Part6'", + NewFileContent: `const Start = { + A: 'A', + B: 'B', +} as const; + +const End = { + Y: "Y", + Z: "Z" +} as const; +export const All_Part1 = {}; +function getPart() { + return { M: "Z"} +} + +const All_Part1_1 = { + x: 1 +}; +const All_Part3 = { + y: 1 +}; +const All_Part4 = getPart(); +const All_Part6 = { + z: 1 +}; +export const All: typeof All_Part1_1 & typeof Start & typeof All_Part3 & typeof All_Part4 & typeof End & typeof All_Part6 = { + ...All_Part1_1, + ...Start, + ...All_Part3, + ...All_Part4, + ...End, + ...All_Part6 +};`, + Index: 1, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports35-variable-releative_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports35-variable-releative_test.go new file mode 100644 index 00000000000..197ae51fa7a --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports35-variable-releative_test.go @@ -0,0 +1,30 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports35-variable-releative" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports35_variable_releative(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @Filename: /code.ts +const foo = { a: 1 } +export const exported = foo;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type 'typeof foo'", + NewFileContent: `const foo = { a: 1 } +export const exported: typeof foo = foo;`, + Index: 1, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports37-array-spread_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports37-array-spread_test.go new file mode 100644 index 00000000000..6cf7c21cf7e --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports37-array-spread_test.go @@ -0,0 +1,87 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports37-array-spread" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports37_array_spread(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @Filename: /code.ts +const Start = [ + 'A', + 'B', +] as const; + +const End = [ + "Y", + "Z" +] as const; +export const All_Part1 = {}; +function getPart() { + return ["Z"] +} + +export const All = [ + 1, + ...Start, + 1, + ...getPart(), + ...End, + 1, +] as const;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type '[...typeof All_Part1_1, ...typeof Start, ...typeof All_Part3, ...typeof All_Part4, ...typeof End, ...typeof All_Part6]'", + NewFileContent: `const Start = [ + 'A', + 'B', +] as const; + +const End = [ + "Y", + "Z" +] as const; +export const All_Part1 = {}; +function getPart() { + return ["Z"] +} + +const All_Part1_1 = [ + 1 +] as const; +const All_Part3 = [ + 1 +] as const; +const All_Part4 = getPart() as const; +const All_Part6 = [ + 1 +] as const; +export const All: [ + ...typeof All_Part1_1, + ...typeof Start, + ...typeof All_Part3, + ...typeof All_Part4, + ...typeof End, + ...typeof All_Part6 +] = [ + ...All_Part1_1, + ...Start, + ...All_Part3, + ...All_Part4, + ...End, + ...All_Part6 +] as const;`, + Index: 1, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports38-unique-symbol-return_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports38-unique-symbol-return_test.go new file mode 100644 index 00000000000..a1ab6c98d97 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports38-unique-symbol-return_test.go @@ -0,0 +1,33 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports38-unique-symbol-return" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports38_unique_symbol_return(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2019 +// @Filename: /code.ts +const u: unique symbol = Symbol(); +export const fn = () => ({ u } as const);` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type '{ readonly u: typeof u; }'", + NewFileContent: `const u: unique symbol = Symbol(); +export const fn = (): { + readonly u: typeof u; +} => ({ u } as const);`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports39-extract-arr-to-variable_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports39-extract-arr-to-variable_test.go new file mode 100644 index 00000000000..5c4ae60dca9 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports39-extract-arr-to-variable_test.go @@ -0,0 +1,64 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports39-extract-arr-to-variable" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports39_extract_arr_to_variable(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2019 +// @Filename: /code.ts +let c: string[] = []; +export let o = { + p: [ + ...c + ] +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Mark array literal as const", + NewFileContent: `let c: string[] = []; +export let o = { + p: [ + ...c + ] as const +}`, + Index: 2, + ApplyChanges: true, + }) + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Extract to variable and replace with 'newLocal as typeof newLocal'", + NewFileContent: `let c: string[] = []; +const newLocal = [ + ...c +] as const; +export let o = { + p: newLocal as typeof newLocal +}`, + Index: 1, + ApplyChanges: true, + }) + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type 'readonly string[]'", + NewFileContent: `let c: string[] = []; +const newLocal: readonly string[] = [ + ...c +] as const; +export let o = { + p: newLocal as typeof newLocal +}`, + Index: 0, + ApplyChanges: true, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports3_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports3_test.go new file mode 100644 index 00000000000..d6271a0d885 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports3_test.go @@ -0,0 +1,37 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports3" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports3(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +const a = 42; +const b = 42; +export class C { + //making sure comments are not changed + property =a+b; // comment should stay here +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type 'number'", + NewFileContent: `const a = 42; +const b = 42; +export class C { + //making sure comments are not changed + property: number =a+b; // comment should stay here +}`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports40-extract-other-to-variable_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports40-extract-other-to-variable_test.go new file mode 100644 index 00000000000..eabae6a2dc1 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports40-extract-other-to-variable_test.go @@ -0,0 +1,53 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports40-extract-other-to-variable" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports40_extract_other_to_variable(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2019 +// @Filename: /code.ts +let c: string[] = []; +export let o = { + p: Math.random() ? []: [ + ...c + ] +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Extract to variable and replace with 'newLocal as typeof newLocal'", + NewFileContent: `let c: string[] = []; +const newLocal = Math.random() ? [] : [ + ...c +]; +export let o = { + p: newLocal as typeof newLocal +}`, + Index: 2, + ApplyChanges: true, + }) + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type 'string[]'", + NewFileContent: `let c: string[] = []; +const newLocal: string[] = Math.random() ? [] : [ + ...c +]; +export let o = { + p: newLocal as typeof newLocal +}`, + Index: 0, + ApplyChanges: true, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports42-static-readonly-class-symbol_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports42-static-readonly-class-symbol_test.go new file mode 100644 index 00000000000..d11110596b2 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports42-static-readonly-class-symbol_test.go @@ -0,0 +1,33 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports42-static-readonly-class-symbol" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports42_static_readonly_class_symbol(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2019 +// @Filename: /code.ts +class A { + static readonly p1 = Symbol(); +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type 'unique symbol'", + NewFileContent: `class A { + static readonly p1: unique symbol = Symbol(); +}`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions-2_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions-2_test.go new file mode 100644 index 00000000000..b74c80bcadc --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions-2_test.go @@ -0,0 +1,37 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports43-expando-functions-2" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports43_expando_functions_2(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2019 +// @Filename: /code.ts +const foo = () => {} +foo/*a*/["a"] = "A"; +foo["b"] = "C"` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type '{ (): void; a: string; b: string; }'", + NewFileContent: `const foo: { + (): void; + a: string; + b: string; +} = () => {} +foo["a"] = "A"; +foo["b"] = "C"`, + Index: 1, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions-3_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions-3_test.go new file mode 100644 index 00000000000..a70e487dd36 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions-3_test.go @@ -0,0 +1,37 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports43-expando-functions-3" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports43_expando_functions_3(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2019 +// @Filename: /code.ts +function foo(): void {} +foo.x = 1; +foo.y = 1;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Annotate types of properties expando function in a namespace", + NewFileContent: `function foo(): void {} +declare namespace foo { + export var x: number; + export var y: number; +} +foo.x = 1; +foo.y = 1;`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions-4_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions-4_test.go new file mode 100644 index 00000000000..b697e921535 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions-4_test.go @@ -0,0 +1,38 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports43-expando-functions-4" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports43_expando_functions_4(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2019 +// @Filename: /code.ts +function foo(): void {} +// cannot name this property because it's an invalid variable name. +foo["@bar"] = 42; +foo.x = 1;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Annotate types of properties expando function in a namespace", + NewFileContent: `function foo(): void {} +declare namespace foo { + export var x: number; +} +// cannot name this property because it's an invalid variable name. +foo["@bar"] = 42; +foo.x = 1;`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions-5_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions-5_test.go new file mode 100644 index 00000000000..25472908b83 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions-5_test.go @@ -0,0 +1,44 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports43-expando-functions-5" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports43_expando_functions_5(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2019 +// @Filename: /code.ts +function foo(): void {} +// x already exists, so do not generate code for 'x' +foo.x = 1; +foo.y = 1; +namespace foo { + export let x = 42; +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Annotate types of properties expando function in a namespace", + NewFileContent: `function foo(): void {} +declare namespace foo { + export var y: number; +} +// x already exists, so do not generate code for 'x' +foo.x = 1; +foo.y = 1; +namespace foo { + export let x = 42; +}`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions_test.go new file mode 100644 index 00000000000..85ecae1d79a --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports43-expando-functions_test.go @@ -0,0 +1,37 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports43-expando-functions" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports43_expando_functions(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2019 +// @Filename: /code.ts +const foo = (): void => {} +foo.a = "A"; +foo.b = "C"` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type '{ (): void; a: string; b: string; }'", + NewFileContent: `const foo: { + (): void; + a: string; + b: string; +} = (): void => {} +foo.a = "A"; +foo.b = "C"`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports44-default-export_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports44-default-export_test.go new file mode 100644 index 00000000000..bc205df74cb --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports44-default-export_test.go @@ -0,0 +1,30 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports44-default-export" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports44_default_export(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2019 +// @Filename: /code.ts +export default 1 + 1;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Extract default export to variable", + NewFileContent: `const _default_1: number = 1 + 1; +export default _default_1;`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports45-decorators_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports45-decorators_test.go new file mode 100644 index 00000000000..eb7f94acff3 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports45-decorators_test.go @@ -0,0 +1,79 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports45-decorators" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports45_decorators(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @Filename: /code.ts +function classDecorator (value: T, context: ClassDecoratorContext) {} +function methodDecorator ( + target: (...args: number[])=> number, + context: ClassMethodDecoratorContext number>) {} +function getterDecorator(value: Function, context: ClassGetterDecoratorContext) {} +function setterDecorator(value: Function, context: ClassSetterDecoratorContext) {} +function fieldDecorator(value: undefined, context: ClassFieldDecoratorContext) {} +function foo() { return 42;} + +@classDecorator +export class A { + @methodDecorator + sum(...args: number[]) { + return args.reduce((a, b) => a + b, 0); + } + getSelf() { + return this; + } + @getterDecorator + get a() { + return foo(); + } + @setterDecorator + set a(value) {} + + @fieldDecorator classProp = foo(); +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFixAll(t, fourslash.VerifyCodeFixAllOptions{ + FixID: "fixMissingTypeAnnotationOnExports", + NewFileContent: `function classDecorator (value: T, context: ClassDecoratorContext) {} +function methodDecorator ( + target: (...args: number[])=> number, + context: ClassMethodDecoratorContext number>) {} +function getterDecorator(value: Function, context: ClassGetterDecoratorContext) {} +function setterDecorator(value: Function, context: ClassSetterDecoratorContext) {} +function fieldDecorator(value: undefined, context: ClassFieldDecoratorContext) {} +function foo() { return 42;} + +@classDecorator +export class A { + @methodDecorator + sum(...args: number[]): number { + return args.reduce((a, b) => a + b, 0); + } + getSelf(): this { + return this; + } + @getterDecorator + get a(): number { + return foo(); + } + @setterDecorator + set a(value) {} + + @fieldDecorator classProp: number = foo(); +}`, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports46-decorators-experimental_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports46-decorators-experimental_test.go new file mode 100644 index 00000000000..4a054c85c0f --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports46-decorators-experimental_test.go @@ -0,0 +1,78 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports46-decorators-experimental" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports46_decorators_experimental(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @experimentalDecorators: true +// @Filename: /code.ts +function classDecorator() { return (target: T) => target; } +function methodDecorator() { return (target: any, key: string, descriptor: PropertyDescriptor) => descriptor;} +function parameterDecorator() { return (target: any, key: string, idx: number) => {};} +function getterDecorator() { return (target: any, key: string) => {}; } +function setterDecorator() { return (target: any, key: string) => {}; } +function fieldDecorator() { return (target: any, key: string) => {}; } +function foo() { return 42; } + +@classDecorator() +export class A { + @methodDecorator() + sum(...args: number[]) { + return args.reduce((a, b) => a + b, 0); + } + getSelf() { + return this; + } + passParameter(@parameterDecorator() param = foo()) {} + @getterDecorator() + get a() { + return foo(); + } + @setterDecorator() + set a(value) {} + @fieldDecorator() classProp = foo(); +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFixAll(t, fourslash.VerifyCodeFixAllOptions{ + FixID: "fixMissingTypeAnnotationOnExports", + NewFileContent: `function classDecorator() { return (target: T) => target; } +function methodDecorator() { return (target: any, key: string, descriptor: PropertyDescriptor) => descriptor;} +function parameterDecorator() { return (target: any, key: string, idx: number) => {};} +function getterDecorator() { return (target: any, key: string) => {}; } +function setterDecorator() { return (target: any, key: string) => {}; } +function fieldDecorator() { return (target: any, key: string) => {}; } +function foo() { return 42; } + +@classDecorator() +export class A { + @methodDecorator() + sum(...args: number[]): number { + return args.reduce((a, b) => a + b, 0); + } + getSelf(): this { + return this; + } + passParameter(@parameterDecorator() param: number = foo()): void {} + @getterDecorator() + get a(): number { + return foo(); + } + @setterDecorator() + set a(value) {} + @fieldDecorator() classProp: number = foo(); +}`, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports47_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports47_test.go new file mode 100644 index 00000000000..5a5e65e0bc5 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports47_test.go @@ -0,0 +1,56 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports47" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports47(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @moduleResolution: bundler +// @target: es2018 +// @jsx: react-jsx +// @filename: node_modules/react/package.json +{ + "name": "react", + "types": "index.d.ts" +} +// @filename: node_modules/react/index.d.ts +export = React; +declare namespace JSX { + interface Element extends GlobalJSXElement { } + interface IntrinsicElements extends GlobalJSXIntrinsicElements { } +} +declare namespace React { } +declare global { + namespace JSX { + interface Element { } + interface IntrinsicElements { [x: string]: any; } + } +} +interface GlobalJSXElement extends JSX.Element {} +interface GlobalJSXIntrinsicElements extends JSX.IntrinsicElements {} +// @filename: node_modules/react/jsx-runtime.d.ts +import './'; +// @filename: node_modules/react/jsx-dev-runtime.d.ts +import './'; +// @filename: /a.tsx +export const x =
;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.GoToFile(t, "/a.tsx") + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type 'JSX.Element'", + NewFileContent: `export const x: JSX.Element =
;`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports48_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports48_test.go new file mode 100644 index 00000000000..072eb787f6d --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports48_test.go @@ -0,0 +1,56 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports48" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports48(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @moduleResolution: bundler +// @target: es2018 +// @jsx: react-jsx +// @filename: node_modules/react/package.json +{ + "name": "react", + "types": "index.d.ts" +} +// @filename: node_modules/react/index.d.ts +export = React; +declare namespace JSX { + interface Element extends GlobalJSXElement { } + interface IntrinsicElements extends GlobalJSXIntrinsicElements { } +} +declare namespace React { } +declare global { + namespace JSX { + interface Element { } + interface IntrinsicElements { [x: string]: any; } + } +} +interface GlobalJSXElement extends JSX.Element {} +interface GlobalJSXIntrinsicElements extends JSX.IntrinsicElements {} +// @filename: node_modules/react/jsx-runtime.d.ts +import './'; +// @filename: node_modules/react/jsx-dev-runtime.d.ts +import './'; +// @filename: /a.tsx +export const x =
;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.GoToFile(t, "/a.tsx") + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add satisfies and an inline type assertion with 'JSX.Element'", + NewFileContent: `export const x = (
) satisfies JSX.Element as JSX.Element;`, + Index: 1, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports49-private-name_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports49-private-name_test.go new file mode 100644 index 00000000000..2df9d60ed76 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports49-private-name_test.go @@ -0,0 +1,59 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports49-private-name" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports49_private_name(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @moduleResolution: bundler +// @target: es2018 +// @jsx: react-jsx +export function two() { + const y = ""; + return {} as typeof y; +} + +export function three() { + type Z = string; + return {} as Z; +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type '\"\"'", + NewFileContent: `export function two(): "" { + const y = ""; + return {} as typeof y; +} + +export function three() { + type Z = string; + return {} as Z; +}`, + Index: 0, + }) + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type 'string'", + NewFileContent: `export function two() { + const y = ""; + return {} as typeof y; +} + +export function three(): string { + type Z = string; + return {} as Z; +}`, + Index: 1, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports4_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports4_test.go new file mode 100644 index 00000000000..630a8ba0f99 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports4_test.go @@ -0,0 +1,36 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports4" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports4(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +const a = 42; +const b = 42; +export class C { + method() { return a + b }; +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFixAvailable(t, []string{"Add return type 'number'"}) + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type 'number'", + NewFileContent: `const a = 42; +const b = 42; +export class C { + method(): number { return a + b }; +}`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports50-generics-with-default_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports50-generics-with-default_test.go new file mode 100644 index 00000000000..799dcc46416 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports50-generics-with-default_test.go @@ -0,0 +1,30 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports50-generics-with-default" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports50_generics_with_default(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2015 +let x: Iterator; +export const y = x;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type 'Iterator'", + NewFileContent: `let x: Iterator; +export const y: Iterator = x;`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports51-slightly-more-complex-generics-with-default_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports51-slightly-more-complex-generics-with-default_test.go new file mode 100644 index 00000000000..39abc73b71a --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports51-slightly-more-complex-generics-with-default_test.go @@ -0,0 +1,33 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports51-slightly-more-complex-generics-with-default" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports51_slightly_more_complex_generics_with_default(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +export interface Foo {} +export function foo(x: Foo) { + return x; +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type 'Foo'", + NewFileContent: `export interface Foo {} +export function foo(x: Foo): Foo { + return x; +}`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports52-generics-oversimplification_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports52-generics-oversimplification_test.go new file mode 100644 index 00000000000..7b7b4d4f3a7 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports52-generics-oversimplification_test.go @@ -0,0 +1,33 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports52-generics-oversimplification" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports52_generics_oversimplification(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +export interface Foo {} +export function foo(x: Foo) { + return x; +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type 'Foo'", + NewFileContent: `export interface Foo {} +export function foo(x: Foo): Foo { + return x; +}`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports53-nested-generic-types_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports53-nested-generic-types_test.go new file mode 100644 index 00000000000..428aa188bd3 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports53-nested-generic-types_test.go @@ -0,0 +1,33 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports53-nested-generic-types" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports53_nested_generic_types(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +export interface Foo {} +export function foo(x: Map>) { + return x; +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type 'Map>'", + NewFileContent: `export interface Foo {} +export function foo(x: Map>): Map> { + return x; +}`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports54-generator-generics_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports54-generator-generics_test.go new file mode 100644 index 00000000000..788fd6cbf75 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports54-generator-generics_test.go @@ -0,0 +1,32 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports54-generator-generics" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports54_generator_generics(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2015 +export function foo(x: Generator) { + return x; +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type 'Generator'", + NewFileContent: `export function foo(x: Generator): Generator { + return x; +}`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports55-generator-return_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports55-generator-return_test.go new file mode 100644 index 00000000000..5462cbabee3 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports55-generator-return_test.go @@ -0,0 +1,32 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports55-generator-return" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports55_generator_return(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2015 +export function *foo() { + yield 5; +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type 'Generator'", + NewFileContent: `export function *foo(): Generator { + yield 5; +}`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports56-toplevel-import_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports56-toplevel-import_test.go new file mode 100644 index 00000000000..ec25e49164c --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports56-toplevel-import_test.go @@ -0,0 +1,42 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports56-toplevel-import" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports56_toplevel_import(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @Filename: /person-code.ts +export interface Person { x: string; } +export function getPerson() : Person { + return null! +} +// @Filename: /code.ts +import { getPerson } from "./person-code"; +export function wrapPerson() { + return { person: getPerson() } +};` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.GoToFile(t, "/code.ts") + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type '{ person: Person; }'", + NewFileContent: `import { getPerson, Person } from "./person-code"; +export function wrapPerson(): { + person: Person; +} { + return { person: getPerson() } +};`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports57-generics-doesnt-drop-trailing-unknown_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports57-generics-doesnt-drop-trailing-unknown_test.go new file mode 100644 index 00000000000..865dcd94e5b --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports57-generics-doesnt-drop-trailing-unknown_test.go @@ -0,0 +1,34 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports57-generics-doesnt-drop-trailing-unknown" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports57_generics_doesnt_drop_trailing_unknown(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2015 + +let x: unknown; +export const s = new Set([x]); +` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type 'Set'", + NewFileContent: ` +let x: unknown; +export const s: Set = new Set([x]); +`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports58-genercs-doesnt-drop-trailing-unknown-2_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports58-genercs-doesnt-drop-trailing-unknown-2_test.go new file mode 100644 index 00000000000..745207a4b6f --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports58-genercs-doesnt-drop-trailing-unknown-2_test.go @@ -0,0 +1,32 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports58-genercs-doesnt-drop-trailing-unknown-2" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports58_genercs_doesnt_drop_trailing_unknown_2(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @lib: es2015 + +export const s = new Set(); +` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type 'Set'", + NewFileContent: ` +export const s: Set = new Set(); +`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports59-drops-unneeded-after-unknown_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports59-drops-unneeded-after-unknown_test.go new file mode 100644 index 00000000000..12f2ac6f429 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports59-drops-unneeded-after-unknown_test.go @@ -0,0 +1,33 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports59-drops-unneeded-after-unknown" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports59_drops_unneeded_after_unknown(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true + +export interface Foo {} +export function g(x: Foo) { return x; } +` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type 'Foo'", + NewFileContent: ` +export interface Foo {} +export function g(x: Foo): Foo { return x; } +`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports5_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports5_test.go new file mode 100644 index 00000000000..2ec1194fa37 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports5_test.go @@ -0,0 +1,36 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports5" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports5(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +const a = 42; +const b = 42; +export class C { + get property() { return a + b; } +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFixAvailable(t, []string{"Add return type 'number'"}) + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type 'number'", + NewFileContent: `const a = 42; +const b = 42; +export class C { + get property(): number { return a + b; } +}`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports60-drops-unneeded-non-trailing-unknown_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports60-drops-unneeded-non-trailing-unknown_test.go new file mode 100644 index 00000000000..7f3b210cd62 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports60-drops-unneeded-non-trailing-unknown_test.go @@ -0,0 +1,33 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports60-drops-unneeded-non-trailing-unknown" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports60_drops_unneeded_non_trailing_unknown(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true + +export interface Foo {} +export function f(x: Foo) { return x; } +` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type 'Foo'", + NewFileContent: ` +export interface Foo {} +export function f(x: Foo): Foo { return x; } +`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports6_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports6_test.go new file mode 100644 index 00000000000..42614839d5b --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports6_test.go @@ -0,0 +1,29 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports6" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports6(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +function foo(): number[] { return [42]; } +export const c = [...foo()];` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type 'number[]'", + NewFileContent: `function foo(): number[] { return [42]; } +export const c: number[] = [...foo()];`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports7_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports7_test.go new file mode 100644 index 00000000000..560448a24a0 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports7_test.go @@ -0,0 +1,31 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports7" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports7(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +function foo(): number[] { return [42]; } +export const c = { foo: foo() };` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type '{ foo: number[]; }'", + NewFileContent: `function foo(): number[] { return [42]; } +export const c: { + foo: number[]; +} = { foo: foo() };`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports8_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports8_test.go new file mode 100644 index 00000000000..fc4e3f99a05 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports8_test.go @@ -0,0 +1,30 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports8" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports8(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +function foo() {return 42;} +export const g = function () { return foo(); };` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFixAvailable(t, []string{"Add return type 'number'"}) + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type 'number'", + NewFileContent: `function foo() {return 42;} +export const g = function (): number { return foo(); };`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports9_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports9_test.go new file mode 100644 index 00000000000..4d8b336319f --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports9_test.go @@ -0,0 +1,35 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports9" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports9(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +function foo( ){ + return 42; +} +const a = foo(); +export = a;` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type 'number'", + NewFileContent: `function foo( ){ + return 42; +} +const a: number = foo(); +export = a;`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExportsTypePredicate1_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExportsTypePredicate1_test.go new file mode 100644 index 00000000000..2bafa03e436 --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExportsTypePredicate1_test.go @@ -0,0 +1,32 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExportsTypePredicate1" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExportsTypePredicate1(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +// @filename: index.ts +export function isString(value: unknown) { + return typeof value === "string"; +}` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add return type 'value is string'", + NewFileContent: `export function isString(value: unknown): value is string { + return typeof value === "string"; +}`, + Index: 0, + }) +} diff --git a/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports_test.go b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports_test.go new file mode 100644 index 00000000000..39a75048fea --- /dev/null +++ b/internal/fourslash/tests/gen/codeFixMissingTypeAnnotationOnExports_test.go @@ -0,0 +1,29 @@ +// Code generated by convertFourslash; DO NOT EDIT. +// To modify this test, run "npm run makemanual codeFixMissingTypeAnnotationOnExports" + +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestCodeFixMissingTypeAnnotationOnExports(t *testing.T) { + fourslash.SkipIfFailing(t) + t.Parallel() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @isolatedDeclarations: true +// @declaration: true +function foo() { return 42; } +export const g = foo();` + f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content) + defer done() + f.VerifyCodeFix(t, fourslash.VerifyCodeFixOptions{ + Description: "Add annotation of type 'number'", + NewFileContent: `function foo() { return 42; } +export const g: number = foo();`, + Index: 0, + }) +} diff --git a/internal/ls/autoimport/import_adder.go b/internal/ls/autoimport/import_adder.go index c90364c200b..ab0603d65be 100644 --- a/internal/ls/autoimport/import_adder.go +++ b/internal/ls/autoimport/import_adder.go @@ -389,15 +389,17 @@ func TypeToAutoImportableTypeNode( if typeNode == nil { return nil } - return typeNodeToAutoImportableTypeNode(typeNode, importAdder, idToSymbol) + return TypeNodeToAutoImportableTypeNode(typeNode, importAdder, idToSymbol) } -func typeNodeToAutoImportableTypeNode( +// TypeNodeToAutoImportableTypeNode converts import type references in a type node to +// simple type references and registers needed imports with the import adder. +func TypeNodeToAutoImportableTypeNode( typeNode *ast.TypeNode, importAdder ImportAdder, idToSymbol map[*ast.IdentifierNode]*ast.Symbol, ) *ast.TypeNode { - referenceTypeNode, importableSymbols := tryGetAutoImportableReferenceFromTypeNode(typeNode, idToSymbol) + referenceTypeNode, importableSymbols := TryGetAutoImportableReferenceFromTypeNode(typeNode, idToSymbol) if referenceTypeNode != nil { if importAdder != nil { importSymbols(importAdder, importableSymbols) @@ -418,7 +420,10 @@ func importSymbols(importAdder ImportAdder, symbols []*ast.Symbol) { // Given a type node containing 'import("./a").SomeType>', // returns an equivalent type reference node with any nested ImportTypeNodes also replaced // with type references, and a list of symbols that must be imported to use the type reference. -func tryGetAutoImportableReferenceFromTypeNode(importTypeNode *ast.TypeNode, idToSymbol map[*ast.IdentifierNode]*ast.Symbol) (*ast.TypeNode, []*ast.Symbol) { +// TryGetAutoImportableReferenceFromTypeNode converts import type references in a type node +// to simple type references and returns the transformed type node and the symbols that need +// to be imported. +func TryGetAutoImportableReferenceFromTypeNode(importTypeNode *ast.TypeNode, idToSymbol map[*ast.IdentifierNode]*ast.Symbol) (*ast.TypeNode, []*ast.Symbol) { var symbols []*ast.Symbol var visitor *ast.NodeVisitor factory := ast.NewNodeFactory(ast.NodeFactoryHooks{}) diff --git a/internal/ls/change/delete.go b/internal/ls/change/delete.go index b5a3dd4a05d..e4af6b4ebb6 100644 --- a/internal/ls/change/delete.go +++ b/internal/ls/change/delete.go @@ -25,7 +25,7 @@ func deleteDeclaration(t *Tracker, deletedNodesInLists map[*ast.Node]bool, sourc // Lambdas with exactly one parameter are special because, after removal, there // must be an empty parameter list (i.e. `()`) and this won't necessarily be the // case if the parameter is simply removed (e.g. in `x => 1`). - t.ReplaceRangeWithText(sourceFile, t.getAdjustedRange(sourceFile, node, node, LeadingTriviaOptionIncludeAll, TrailingTriviaOptionInclude), "()") + t.ReplaceRangeWithText(sourceFile, t.GetAdjustedRange(sourceFile, node, node, LeadingTriviaOptionIncludeAll, TrailingTriviaOptionInclude), "()") } else { deleteNodeInList(t, deletedNodesInLists, sourceFile, node) } diff --git a/internal/ls/change/tracker.go b/internal/ls/change/tracker.go index 8ed4111564a..bb8161f510f 100644 --- a/internal/ls/change/tracker.go +++ b/internal/ls/change/tracker.go @@ -129,7 +129,7 @@ func (t *Tracker) ReplaceNode(sourceFile *ast.SourceFile, oldNode *ast.Node, new TrailingTriviaOption: TrailingTriviaOptionExclude, } } - t.ReplaceRange(sourceFile, t.getAdjustedRange(sourceFile, oldNode, oldNode, options.LeadingTriviaOption, options.TrailingTriviaOption), newNode, *options) + t.ReplaceRange(sourceFile, t.GetAdjustedRange(sourceFile, oldNode, oldNode, options.LeadingTriviaOption, options.TrailingTriviaOption), newNode, *options) } func (t *Tracker) ReplaceNodeWithNodes(sourceFile *ast.SourceFile, oldNode *ast.Node, newNodes []*ast.Node, options *NodeOptions) { @@ -139,7 +139,7 @@ func (t *Tracker) ReplaceNodeWithNodes(sourceFile *ast.SourceFile, oldNode *ast. TrailingTriviaOption: TrailingTriviaOptionExclude, } } - t.ReplaceRangeWithNodes(sourceFile, t.getAdjustedRange(sourceFile, oldNode, oldNode, options.LeadingTriviaOption, options.TrailingTriviaOption), newNodes, *options) + t.ReplaceRangeWithNodes(sourceFile, t.GetAdjustedRange(sourceFile, oldNode, oldNode, options.LeadingTriviaOption, options.TrailingTriviaOption), newNodes, *options) } func (t *Tracker) ReplaceRange(sourceFile *ast.SourceFile, lsprotoRange lsproto.Range, newNode *ast.Node, options NodeOptions) { @@ -186,6 +186,46 @@ func (t *Tracker) InsertNodeBefore(sourceFile *ast.SourceFile, before *ast.Node, t.InsertNodeAt(sourceFile, core.TextPos(t.getAdjustedStartPosition(sourceFile, before, leadingTriviaOption, false)), newNode, t.getOptionsForInsertNodeBefore(before, newNode, blankLineBetween)) } +// TryInsertTypeAnnotation inserts a type annotation after the appropriate position on a node +// (after the close paren for function-like, after the name/exclamation/question for variable-like). +// Returns true if successful. +func (t *Tracker) TryInsertTypeAnnotation(sourceFile *ast.SourceFile, node *ast.Node, typeNode *ast.Node) bool { + var endNode *ast.Node + if ast.IsFunctionLike(node) { + endNode = astnav.FindChildOfKind(node, ast.KindCloseParenToken, sourceFile) + if endNode == nil { + if !ast.IsArrowFunction(node) { + return false + } + // If no `)`, is an arrow function `x => x`, so use the end of the first parameter + params := node.Parameters() + if len(params) == 0 { + return false + } + endNode = params[0] + } + } else { + switch node.Kind { + case ast.KindVariableDeclaration: + endNode = node.AsVariableDeclaration().ExclamationToken + case ast.KindPropertySignature: + endNode = node.AsPropertySignatureDeclaration().PostfixToken + case ast.KindPropertyDeclaration: + endNode = node.AsPropertyDeclaration().PostfixToken + case ast.KindParameter: + endNode = node.AsParameterDeclaration().QuestionToken + } + if endNode == nil { + endNode = node.Name() + } + } + if endNode == nil { + return false + } + t.InsertNodeAt(sourceFile, core.TextPos(endNode.End()), typeNode, NodeOptions{Prefix: ": "}) + return true +} + // InsertModifierBefore inserts a modifier token (like 'type') before a node with a trailing space. func (t *Tracker) InsertModifierBefore(sourceFile *ast.SourceFile, modifier ast.Kind, before *ast.Node) { pos := astnav.GetStartOfNode(before, sourceFile, false) @@ -210,7 +250,7 @@ func (t *Tracker) DeleteRange(sourceFile *ast.SourceFile, textRange core.TextRan // DeleteNode deletes a node immediately with specified trivia options. // Stop! Consider using Delete instead, which has logic for deleting nodes from delimited lists. func (t *Tracker) DeleteNode(sourceFile *ast.SourceFile, node *ast.Node, leadingTrivia LeadingTriviaOption, trailingTrivia TrailingTriviaOption) { - rng := t.getAdjustedRange(sourceFile, node, node, leadingTrivia, trailingTrivia) + rng := t.GetAdjustedRange(sourceFile, node, node, leadingTrivia, trailingTrivia) t.ReplaceRangeWithText(sourceFile, rng, "") } diff --git a/internal/ls/change/trackerimpl.go b/internal/ls/change/trackerimpl.go index 1d748c3986d..e9e0ae717e2 100644 --- a/internal/ls/change/trackerimpl.go +++ b/internal/ls/change/trackerimpl.go @@ -122,23 +122,6 @@ func getFormatCodeSettingsForWriting(options lsutil.FormatCodeSettings, sourceFi } func (t *Tracker) getNonformattedText(node *ast.Node, sourceFile *ast.SourceFile) (string, *ast.Node) { - nodeIn := node - eofToken := t.Factory.NewToken(ast.KindEndOfFile) - if ast.IsStatement(node) { - text := "" - // OrganizeImports uses nodes from the old tree for preserving comments when emitting, - // which causes text to be indexed with the positions of the old nodes. - // For more details, check PR #2331 - if !ast.NodeIsSynthesized(node) { - text = sourceFile.Text() - } - nodeIn = t.Factory.NewSourceFile( - ast.SourceFileParseOptions{FileName: sourceFile.FileName(), Path: sourceFile.Path()}, - text, - t.Factory.NewNodeList([]*ast.Node{node}), - t.Factory.NewToken(ast.KindEndOfFile), - ) - } writer := printer.NewChangeTrackerWriter(t.newLine, t.formatSettings.IndentSize) printer.NewPrinter( printer.PrinterOptions{ @@ -149,36 +132,33 @@ func (t *Tracker) getNonformattedText(node *ast.Node, sourceFile *ast.SourceFile }, writer.GetPrintHandlers(), t.EmitContext, - ).Write(nodeIn, sourceFile, writer, nil) + ).Write(node, sourceFile, writer, nil) text := writer.String() - text = strings.TrimSuffix(text, t.newLine) // Newline artifact from printing a SourceFile instead of a node - - nodeOut := writer.AssignPositionsToNode(nodeIn, t.NodeFactory) - var sourceFileLike *ast.Node - if !ast.IsStatement(node) { - nodeList := t.Factory.NewNodeList([]*ast.Node{nodeOut}) - nodeList.Loc = nodeOut.Loc - eofToken.Loc = core.NewTextRange(nodeOut.End(), nodeOut.End()) - sourceFileLike = t.Factory.NewSourceFile( - ast.SourceFileParseOptions{FileName: sourceFile.FileName(), Path: sourceFile.Path()}, - text, - nodeList, - eofToken, - ) - sourceFileLike.ForEachChild(func(child *ast.Node) bool { - child.Parent = sourceFileLike - return true - }) - sourceFileLike.Loc = nodeOut.Loc - } else { - sourceFileLike = nodeOut - } + text = strings.TrimSuffix(text, t.newLine) + + nodeOut := writer.AssignPositionsToNode(node, t.NodeFactory) + eofToken := t.Factory.NewToken(ast.KindEndOfFile) + nodeList := t.Factory.NewNodeList([]*ast.Node{nodeOut}) + nodeList.Loc = nodeOut.Loc + eofToken.Loc = core.NewTextRange(nodeOut.End(), nodeOut.End()) + sourceFileLike := t.Factory.NewSourceFile( + ast.SourceFileParseOptions{FileName: sourceFile.FileName(), Path: sourceFile.Path()}, + text, + nodeList, + eofToken, + ) + sourceFileLike.ForEachChild(func(child *ast.Node) bool { + child.Parent = sourceFileLike + return true + }) + sourceFileLike.Loc = nodeOut.Loc return text, sourceFileLike } // method on the changeTracker because use of converters -func (t *Tracker) getAdjustedRange(sourceFile *ast.SourceFile, startNode *ast.Node, endNode *ast.Node, leadingOption LeadingTriviaOption, trailingOption TrailingTriviaOption) lsproto.Range { +// GetAdjustedRange computes the adjusted range for a node in a source file, accounting for trivia. +func (t *Tracker) GetAdjustedRange(sourceFile *ast.SourceFile, startNode *ast.Node, endNode *ast.Node, leadingOption LeadingTriviaOption, trailingOption TrailingTriviaOption) lsproto.Range { return t.converters.ToLSPRange( sourceFile, core.NewTextRange( diff --git a/internal/ls/codeactions.go b/internal/ls/codeactions.go index 964af56d0a0..c77e86b2f34 100644 --- a/internal/ls/codeactions.go +++ b/internal/ls/codeactions.go @@ -51,6 +51,7 @@ type CombinedCodeActions struct { // codeFixProviders is the list of all registered code fix providers var codeFixProviders = []*CodeFixProvider{ ImportFixProvider, + IsolatedDeclarationsFixProvider, // Add more code fix providers here as they are implemented } diff --git a/internal/ls/codeactions_fixmissingtypeannotation.go b/internal/ls/codeactions_fixmissingtypeannotation.go new file mode 100644 index 00000000000..5e4b4d3e8e2 --- /dev/null +++ b/internal/ls/codeactions_fixmissingtypeannotation.go @@ -0,0 +1,1355 @@ +package ls + +import ( + "context" + "fmt" + "strconv" + + "github.com/microsoft/typescript-go/internal/ast" + "github.com/microsoft/typescript-go/internal/astnav" + "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/diagnostics" + "github.com/microsoft/typescript-go/internal/ls/autoimport" + "github.com/microsoft/typescript-go/internal/ls/change" + "github.com/microsoft/typescript-go/internal/nodebuilder" + "github.com/microsoft/typescript-go/internal/printer" + "github.com/microsoft/typescript-go/internal/scanner" +) + +var isolatedDeclarationsFixErrorCodes = []int32{ + diagnostics.Function_must_have_an_explicit_return_type_annotation_with_isolatedDeclarations.Code(), + diagnostics.Method_must_have_an_explicit_return_type_annotation_with_isolatedDeclarations.Code(), + diagnostics.At_least_one_accessor_must_have_an_explicit_type_annotation_with_isolatedDeclarations.Code(), + diagnostics.Variable_must_have_an_explicit_type_annotation_with_isolatedDeclarations.Code(), + diagnostics.Parameter_must_have_an_explicit_type_annotation_with_isolatedDeclarations.Code(), + diagnostics.Property_must_have_an_explicit_type_annotation_with_isolatedDeclarations.Code(), + diagnostics.Expression_type_can_t_be_inferred_with_isolatedDeclarations.Code(), + diagnostics.Binding_elements_can_t_be_exported_directly_with_isolatedDeclarations.Code(), + diagnostics.Computed_property_names_on_class_or_object_literals_cannot_be_inferred_with_isolatedDeclarations.Code(), + diagnostics.Computed_properties_must_be_number_or_string_literals_variables_or_dotted_expressions_with_isolatedDeclarations.Code(), + diagnostics.Enum_member_initializers_must_be_computable_without_references_to_external_symbols_with_isolatedDeclarations.Code(), + diagnostics.Extends_clause_can_t_contain_an_expression_with_isolatedDeclarations.Code(), + diagnostics.Objects_that_contain_shorthand_properties_can_t_be_inferred_with_isolatedDeclarations.Code(), + diagnostics.Objects_that_contain_spread_assignments_can_t_be_inferred_with_isolatedDeclarations.Code(), + diagnostics.Arrays_with_spread_elements_can_t_inferred_with_isolatedDeclarations.Code(), + diagnostics.Default_exports_can_t_be_inferred_with_isolatedDeclarations.Code(), + diagnostics.Only_const_arrays_can_be_inferred_with_isolatedDeclarations.Code(), + diagnostics.Assigning_properties_to_functions_without_declaring_them_is_not_supported_with_isolatedDeclarations_Add_an_explicit_declaration_for_the_properties_assigned_to_this_function.Code(), + diagnostics.Declaration_emit_for_this_parameter_requires_implicitly_adding_undefined_to_its_type_This_is_not_supported_with_isolatedDeclarations.Code(), + diagnostics.Type_containing_private_name_0_can_t_be_used_with_isolatedDeclarations.Code(), + diagnostics.Add_satisfies_and_a_type_assertion_to_this_expression_satisfies_T_as_T_to_make_the_type_explicit.Code(), +} + +const fixMissingTypeAnnotationOnExportsFixID = "fixMissingTypeAnnotationOnExports" + +// IsolatedDeclarationsFixProvider is the CodeFixProvider for isolatedDeclarations-related type annotation fixes. +var IsolatedDeclarationsFixProvider = &CodeFixProvider{ + ErrorCodes: isolatedDeclarationsFixErrorCodes, + GetCodeActions: getIsolatedDeclarationsCodeActions, + FixIds: []string{fixMissingTypeAnnotationOnExportsFixID}, +} + +// canHaveTypeAnnotationKinds are the node kinds that can have type annotations added. +var canHaveTypeAnnotationKinds = map[ast.Kind]bool{ + ast.KindGetAccessor: true, + ast.KindMethodDeclaration: true, + ast.KindPropertyDeclaration: true, + ast.KindFunctionDeclaration: true, + ast.KindFunctionExpression: true, + ast.KindArrowFunction: true, + ast.KindVariableDeclaration: true, + ast.KindParameter: true, + ast.KindExportAssignment: true, + ast.KindClassDeclaration: true, + ast.KindObjectBindingPattern: true, + ast.KindArrayBindingPattern: true, +} + +// declarationEmitNodeBuilderFlags are the node builder flags used for declaration emit. +var declarationEmitNodeBuilderFlags = nodebuilder.FlagsMultilineObjectLiterals | + nodebuilder.FlagsWriteClassExpressionAsTypeLiteral | + nodebuilder.FlagsUseTypeOfFunction | + nodebuilder.FlagsUseStructuralFallback | + nodebuilder.FlagsAllowEmptyTuple | + nodebuilder.FlagsGenerateNamesForShadowedTypeParams | + nodebuilder.FlagsNoTruncation + +type typePrintMode int + +const ( + typePrintModeFull typePrintMode = iota + typePrintModeRelative // typeof X + typePrintModeWidened // widened literal type +) + +func getIsolatedDeclarationsCodeActions(ctx context.Context, fixContext *CodeFixContext) ([]CodeAction, error) { + ch, done := fixContext.Program.GetTypeCheckerForFile(ctx, fixContext.SourceFile) + defer done() + + var fixes []CodeAction + + // Match TS ordering: Full annotation, Relative annotation, Widened annotation, + // Full inline, Relative inline, Widened inline, Full extract + modes := []typePrintMode{typePrintModeFull, typePrintModeRelative, typePrintModeWidened} + + for _, mode := range modes { + if action := tryCodeAction(ctx, fixContext, ch, func(f *isolatedDeclarationsFixer) string { + f.typePrintMode = mode + return f.addTypeAnnotation(fixContext.Span) + }); action != nil { + fixes = append(fixes, *action) + } + } + + for _, mode := range modes { + if action := tryCodeAction(ctx, fixContext, ch, func(f *isolatedDeclarationsFixer) string { + f.typePrintMode = mode + return f.addInlineAssertion(fixContext.Span) + }); action != nil { + fixes = append(fixes, *action) + } + } + + // extractAsVariable only in Full mode + if action := tryCodeAction(ctx, fixContext, ch, func(f *isolatedDeclarationsFixer) string { + f.typePrintMode = typePrintModeFull + return f.extractAsVariable(fixContext.Span) + }); action != nil { + fixes = append(fixes, *action) + } + + return fixes, nil +} + +func tryCodeAction(ctx context.Context, fixContext *CodeFixContext, ch *checker.Checker, fn func(*isolatedDeclarationsFixer) string) *CodeAction { + changeTracker := change.NewTracker(ctx, fixContext.Program.Options(), fixContext.LS.FormatOptions(), fixContext.LS.converters) + + var importAdder autoimport.ImportAdder + // importAdder may be nil if the auto-import registry is not available; + // type node transformation still works without it, just without adding imports. + + fixer := &isolatedDeclarationsFixer{ + sourceFile: fixContext.SourceFile, + program: fixContext.Program, + checker: ch, + changeTracker: changeTracker, + importAdder: importAdder, + fixedNodes: make(map[*ast.Node]bool), + } + + description := fn(fixer) + if description == "" { + return nil + } + + // Add any symbols that need to be imported to existing import declarations + for _, sym := range fixer.symbolsToImport { + fixer.addSymbolToExistingImport(sym) + } + + changes := changeTracker.GetChanges() + fileChanges := changes[fixContext.SourceFile.FileName()] + + // Add import edits if import adder has fixes + if importAdder != nil && importAdder.HasFixes() { + fileChanges = append(fileChanges, importAdder.Edits()...) + } + + if len(fileChanges) == 0 { + return nil + } + + return &CodeAction{Description: description, Changes: fileChanges} +} + +// isolatedDeclarationsFixer encapsulates the state for fixing isolated declarations errors. +type isolatedDeclarationsFixer struct { + sourceFile *ast.SourceFile + program *compiler.Program + checker *checker.Checker + changeTracker *change.Tracker + importAdder autoimport.ImportAdder + fixedNodes map[*ast.Node]bool + typePrintMode typePrintMode + symbolsToImport []*ast.Symbol + mutatedTarget bool // set by inferType/relativeType when the target was mutated (e.g., spread decomposition) +} + +func (f *isolatedDeclarationsFixer) addTypeAnnotation(span core.TextRange) string { + nodeWithDiag := astnav.GetTokenAtPosition(f.sourceFile, span.Pos()) + + expandoFunction := findExpandoFunction(f.checker, nodeWithDiag) + if expandoFunction != nil { + if ast.IsFunctionDeclaration(expandoFunction) { + return f.createNamespaceForExpandoProperties(expandoFunction) + } + return f.fixIsolatedDeclarationError(expandoFunction) + } + + nodeMissingType := findAncestorWithMissingType(nodeWithDiag) + if nodeMissingType != nil { + return f.fixIsolatedDeclarationError(nodeMissingType) + } + return "" +} + +func (f *isolatedDeclarationsFixer) createNamespaceForExpandoProperties(expandoFunc *ast.Node) string { + funcDecl := expandoFunc.AsFunctionDeclaration() + if funcDecl.Name() == nil { + return "" + } + + t := f.checker.GetTypeAtLocation(expandoFunc) + elements := f.checker.GetPropertiesOfType(t) + if len(elements) == 0 { + return "" + } + + factory := f.changeTracker.NodeFactory + + var newProperties []*ast.Node + for _, symbol := range elements { + if !scanner.IsIdentifierText(symbol.Name, core.LanguageVariantStandard) { + continue + } + // skip symbols that already have a variable declaration + if symbol.ValueDeclaration != nil && ast.IsVariableDeclaration(symbol.ValueDeclaration) { + continue + } + + symType := f.checker.GetTypeOfSymbol(symbol) + typeNode := f.typeToMinimizedReferenceType(symType, expandoFunc, declarationEmitNodeBuilderFlags) + if typeNode == nil { + continue + } + + varDecl := factory.NewVariableDeclaration(factory.NewIdentifier(symbol.Name), nil, typeNode, nil) + exportToken := factory.NewToken(ast.KindExportKeyword) + varDeclList := factory.NewVariableDeclarationList(ast.NodeFlagsNone, factory.NewNodeList([]*ast.Node{varDecl})) + varStmt := factory.NewVariableStatement(factory.NewModifierList([]*ast.Node{exportToken}), varDeclList) + newProperties = append(newProperties, varStmt) + } + + if len(newProperties) == 0 { + return "" + } + + var modifiers []*ast.Node + if ast.HasSyntacticModifier(expandoFunc, ast.ModifierFlagsExport) { + modifiers = append(modifiers, factory.NewToken(ast.KindExportKeyword)) + } + modifiers = append(modifiers, factory.NewToken(ast.KindDeclareKeyword)) + + namespace := factory.NewModuleDeclaration( + factory.NewModifierList(modifiers), + ast.KindNamespaceKeyword, + factory.NewIdentifier(funcDecl.Name().Text()), + factory.NewModuleBlock(factory.NewNodeList(newProperties)), + ) + // Set the flags for namespace + namespace.Flags = ast.NodeFlagsAmbient | ast.NodeFlagsExportContext | ast.NodeFlagsContextFlags + + f.changeTracker.InsertNodeAfter(f.sourceFile, expandoFunc, namespace) + return "Annotate types of properties expando function in a namespace" +} + +// needsParenthesizedExpressionForAssertion checks if an expression needs parentheses for an assertion. +func needsParenthesizedExpressionForAssertion(node *ast.Node) bool { + return !ast.IsEntityNameExpression(node) && !ast.IsCallExpression(node) && !ast.IsObjectLiteralExpression(node) && !ast.IsArrayLiteralExpression(node) +} + +// createAsExpression creates an `expr as Type` expression, parenthesizing if needed. +func createAsExpression(factory *ast.NodeFactory, node *ast.Node, typeNode *ast.Node) *ast.Node { + if needsParenthesizedExpressionForAssertion(node) { + node = factory.NewParenthesizedExpression(node) + } + return factory.NewAsExpression(node, typeNode) +} + +func (f *isolatedDeclarationsFixer) addInlineAssertion(span core.TextRange) string { + nodeWithDiag := astnav.GetTokenAtPosition(f.sourceFile, span.Pos()) + + // No inline assertions for expando members + expandoFunction := findExpandoFunction(f.checker, nodeWithDiag) + if expandoFunction != nil { + return "" + } + + targetNode := findBestFittingNode(nodeWithDiag, span) + if targetNode == nil || isValueSignatureDeclaration(targetNode) || isValueSignatureDeclaration(targetNode.Parent) { + return "" + } + + isExpressionTarget := ast.IsExpression(targetNode) + isShorthandPropertyAssignmentTarget := ast.IsShorthandPropertyAssignment(targetNode) + + // Go's IsDeclaration is broader than TS's isDeclaration (e.g. CallExpression has DeclarationData + // in Go but is not a declaration kind in TS). Use isNamedDeclarationKind to match TS behavior. + if !isShorthandPropertyAssignmentTarget && isNamedDeclarationKind(targetNode) { + return "" + } + // No inline assertions on binding patterns + if ast.FindAncestor(targetNode, ast.IsBindingPattern) != nil { + return "" + } + // No inline assertions on enum members + if ast.FindAncestor(targetNode, ast.IsEnumMember) != nil { + return "" + } + // No support for typeof in extends clauses + if isExpressionTarget && (ast.FindAncestorKind(targetNode, ast.KindHeritageClause) != nil || ast.FindAncestor(targetNode, ast.IsTypeNode) != nil) { + return "" + } + // Can't inline type spread elements + if ast.IsSpreadElement(targetNode) { + return "" + } + + variableDeclaration := ast.FindAncestorKind(targetNode, ast.KindVariableDeclaration) + var variableType *checker.Type + if variableDeclaration != nil { + variableType = f.checker.GetTypeAtLocation(variableDeclaration) + } + // Can't use typeof on unique symbols + if variableType != nil && variableType.Flags()&checker.TypeFlagsUniqueESSymbol != 0 { + return "" + } + + if !isExpressionTarget && !isShorthandPropertyAssignmentTarget { + return "" + } + + typeNode := f.inferType(targetNode, variableType) + if typeNode == nil || f.mutatedTarget { + return "" + } + + factory := f.changeTracker.NodeFactory + + if isShorthandPropertyAssignmentTarget { + // Insert `: expr as Type` after the shorthand property name + clonedName := factory.DeepCloneNode(targetNode.AsShorthandPropertyAssignment().Name()) + asExpr := createAsExpression(factory, clonedName, typeNode) + f.changeTracker.InsertNodeAt(f.sourceFile, core.TextPos(targetNode.End()), asExpr, change.NodeOptions{Prefix: ": "}) + } else if isExpressionTarget { + // Replace expression with `(expression) satisfies Type as Type` or `expression satisfies Type as Type` + clonedTarget := factory.DeepCloneNode(targetNode) + if needsParenthesizedExpressionForAssertion(targetNode) { + clonedTarget = factory.NewParenthesizedExpression(clonedTarget) + } + clonedType := factory.DeepCloneNode(typeNode) + satisfiesAsExpr := factory.NewAsExpression( + factory.NewSatisfiesExpression(clonedTarget, clonedType), + typeNode, + ) + f.changeTracker.ReplaceNode(f.sourceFile, targetNode, satisfiesAsExpr, nil) + } else { + return "" + } + + return fmt.Sprintf("Add satisfies and an inline type assertion with '%s'", typeToStringForDiag(typeNode, f.sourceFile, f.changeTracker)) +} + +func (f *isolatedDeclarationsFixer) extractAsVariable(span core.TextRange) string { + nodeWithDiag := astnav.GetTokenAtPosition(f.sourceFile, span.Pos()) + targetNode := findBestFittingNode(nodeWithDiag, span) + if targetNode == nil || isValueSignatureDeclaration(targetNode) || isValueSignatureDeclaration(targetNode.Parent) { + return "" + } + + if !ast.IsExpression(targetNode) { + return "" + } + + factory := f.changeTracker.NodeFactory + + // Array literals should be marked as const + if ast.IsArrayLiteralExpression(targetNode) { + constRef := factory.NewTypeReferenceNode(factory.NewIdentifier("const"), nil) + cloned := factory.DeepCloneNode(targetNode) + f.changeTracker.ReplaceNode(f.sourceFile, targetNode, createAsExpression(factory, cloned, constRef), nil) + return "Mark array literal as const" + } + + parentPropertyAssignment := ast.FindAncestorKind(targetNode, ast.KindPropertyAssignment) + if parentPropertyAssignment != nil { + // Identifiers or entity names can already be typeof-ed + if parentPropertyAssignment == targetNode.Parent && ast.IsEntityNameExpression(targetNode) { + return "" + } + + tempName := f.changeTracker.EmitContext.Factory.NewUniqueNameEx(getIdentifierNameForNode(targetNode), printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsOptimistic}) + + replacementTarget := targetNode + initializationNode := targetNode + + // Handle spread elements: walk up to the spread's parent and handle const assertions + if ast.IsSpreadElement(replacementTarget) { + replacementTarget = ast.WalkUpParenthesizedExpressions(replacementTarget.Parent) + if isConstAssertion(replacementTarget.Parent) { + replacementTarget = replacementTarget.Parent + initializationNode = replacementTarget + } else { + constRef := factory.NewTypeReferenceNode(factory.NewIdentifier("const"), nil) + initializationNode = createAsExpression(factory, factory.DeepCloneNode(replacementTarget), constRef) + } + } + + if ast.IsEntityNameExpression(replacementTarget) { + return "" + } + + clonedInit := factory.DeepCloneNode(initializationNode) + varDecl := factory.NewVariableDeclaration(tempName.AsNode(), nil, nil, clonedInit) + varDeclList := factory.NewVariableDeclarationList(ast.NodeFlagsConst, factory.NewNodeList([]*ast.Node{varDecl})) + varStmt := factory.NewVariableStatement(nil, varDeclList) + + statement := ast.FindAncestor(targetNode, ast.IsStatement) + if statement == nil { + return "" + } + f.changeTracker.InsertNodeBefore(f.sourceFile, statement, varStmt, false, change.LeadingTriviaOptionNone) + + typeQuery := factory.NewTypeQueryNode(tempName.AsNode(), nil) + asExpr := factory.NewAsExpression(tempName.AsNode(), typeQuery) + f.changeTracker.ReplaceNode(f.sourceFile, replacementTarget, asExpr, nil) + + idText := typeToStringForDiag(tempName.AsNode(), f.sourceFile, f.changeTracker) + return fmt.Sprintf("Extract to variable and replace with '%s as typeof %s'", idText, idText) + } + + return "" +} + +// findExpandoFunction finds the function declaration that has expando properties assigned to it. +func findExpandoFunction(ch *checker.Checker, node *ast.Node) *ast.Node { + expandoDeclaration := ast.FindAncestorOrQuit(node, func(n *ast.Node) ast.FindAncestorResult { + if ast.IsStatement(n) { + return ast.FindAncestorQuit + } + if ast.IsExpandoPropertyDeclaration(n) { + return ast.FindAncestorTrue + } + return ast.FindAncestorFalse + }) + + if expandoDeclaration == nil || !ast.IsExpandoPropertyDeclaration(expandoDeclaration) { + return nil + } + + assignmentTarget := expandoDeclaration + // Some late bound expando members use the whole expression as the declaration. + if ast.IsBinaryExpression(assignmentTarget) { + assignmentTarget = assignmentTarget.AsBinaryExpression().Left + if !ast.IsExpandoPropertyDeclaration(assignmentTarget) { + return nil + } + } + + var expression *ast.Node + if ast.IsPropertyAccessExpression(assignmentTarget) { + expression = assignmentTarget.AsPropertyAccessExpression().Expression + } else if ast.IsElementAccessExpression(assignmentTarget) { + expression = assignmentTarget.AsElementAccessExpression().Expression + } else { + return nil + } + + targetType := ch.GetTypeAtLocation(expression) + if targetType == nil { + return nil + } + + properties := ch.GetPropertiesOfType(targetType) + found := false + for _, p := range properties { + if p.ValueDeclaration == expandoDeclaration || p.ValueDeclaration == expandoDeclaration.Parent { + found = true + break + } + } + if !found { + return nil + } + + symbol := targetType.Symbol() + if symbol == nil || symbol.ValueDeclaration == nil { + return nil + } + + fn := symbol.ValueDeclaration + if (ast.IsFunctionExpression(fn) || ast.IsArrowFunction(fn)) && ast.IsVariableDeclaration(fn.Parent) { + return fn.Parent + } + if ast.IsFunctionDeclaration(fn) { + return fn + } + + return nil +} + +func (f *isolatedDeclarationsFixer) fixIsolatedDeclarationError(node *ast.Node) string { + // Avoid creating duplicate fixes for the same node + if f.fixedNodes[node] { + return "" + } + f.fixedNodes[node] = true + + switch node.Kind { + case ast.KindParameter, ast.KindPropertyDeclaration, ast.KindVariableDeclaration: + return f.addTypeToVariableLike(node) + case ast.KindArrowFunction, ast.KindFunctionExpression, ast.KindFunctionDeclaration, + ast.KindMethodDeclaration, ast.KindGetAccessor: + return f.addTypeToSignatureDeclaration(node) + case ast.KindExportAssignment: + return f.transformExportAssignment(node) + case ast.KindClassDeclaration: + return f.transformExtendsClauseWithExpression(node) + case ast.KindObjectBindingPattern, ast.KindArrayBindingPattern: + return f.transformDestructuringPatterns(node) + default: + return "" + } +} + +func (f *isolatedDeclarationsFixer) addTypeToSignatureDeclaration(funcNode *ast.Node) string { + if funcNode.Type() != nil { + return "" + } + typeNode := f.inferType(funcNode, nil) + if typeNode == nil { + return "" + } + f.changeTracker.TryInsertTypeAnnotation(f.sourceFile, funcNode, typeNode) + return fmt.Sprintf("Add return type '%s'", typeToStringForDiag(typeNode, f.sourceFile, f.changeTracker)) +} + +func (f *isolatedDeclarationsFixer) transformExportAssignment(defaultExport *ast.Node) string { + exportAssignment := defaultExport.AsExportAssignment() + if exportAssignment.IsExportEquals { + return "" + } + + expression := exportAssignment.Expression + typeNode := f.inferType(expression, nil) + if typeNode == nil { + return "" + } + + factory := f.changeTracker.NodeFactory + + defaultIdentifier := f.changeTracker.EmitContext.Factory.NewUniqueName("_default") + + // Deep clone the expression so synthesized nodes don't reference original source positions + clonedExpression := factory.DeepCloneNode(expression) + + varDecl := factory.NewVariableDeclaration(defaultIdentifier.AsNode(), nil, typeNode, clonedExpression) + varDeclList := factory.NewVariableDeclarationList(ast.NodeFlagsConst, factory.NewNodeList([]*ast.Node{varDecl})) + varStmt := factory.NewVariableStatement(nil, varDeclList) + + newExport := factory.UpdateExportAssignment(defaultExport.AsExportAssignment(), defaultExport.Modifiers(), nil, defaultIdentifier.AsNode()) + + f.changeTracker.ReplaceNodeWithNodes(f.sourceFile, defaultExport, []*ast.Node{varStmt, newExport}, nil) + return "Extract default export to variable" +} + +func (f *isolatedDeclarationsFixer) transformExtendsClauseWithExpression(classDecl *ast.Node) string { + cd := classDecl.AsClassDeclaration() + var extendsClause *ast.Node + if cd.HeritageClauses != nil { + for _, clause := range cd.HeritageClauses.Nodes { + if clause.AsHeritageClause().Token == ast.KindExtendsKeyword { + extendsClause = clause + break + } + } + } + if extendsClause == nil { + return "" + } + + heritageTypes := extendsClause.AsHeritageClause().Types + if heritageTypes == nil || len(heritageTypes.Nodes) == 0 { + return "" + } + heritageExpression := heritageTypes.Nodes[0] + expression := heritageExpression.AsExpressionWithTypeArguments().Expression + + heritageTypeNode := f.inferType(expression, nil) + if heritageTypeNode == nil { + return "" + } + + factory := f.changeTracker.NodeFactory + + baseName := "Anonymous" + if cd.Name() != nil { + baseName = cd.Name().Text() + "Base" + } + baseClassName := f.changeTracker.EmitContext.Factory.NewUniqueNameEx(baseName, printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsOptimistic}) + + // Create: const : = ; + clonedExpression := factory.DeepCloneNode(expression) + varDecl := factory.NewVariableDeclaration(baseClassName.AsNode(), nil, heritageTypeNode, clonedExpression) + varDeclList := factory.NewVariableDeclarationList(ast.NodeFlagsConst, factory.NewNodeList([]*ast.Node{varDecl})) + varStmt := factory.NewVariableStatement(nil, varDeclList) + + f.changeTracker.InsertNodeBefore(f.sourceFile, classDecl, varStmt, false, change.LeadingTriviaOptionNone) + + // Replace the heritage expression with the base class name + f.changeTracker.ReplaceNode(f.sourceFile, heritageExpression, factory.NewExpressionWithTypeArguments(baseClassName.AsNode(), nil), nil) + + return "Extract base class to variable" +} + +func (f *isolatedDeclarationsFixer) transformDestructuringPatterns(bindingPattern *ast.Node) string { + enclosingVariableDeclaration := bindingPattern.Parent + if !ast.IsVariableDeclaration(enclosingVariableDeclaration) { + return "" + } + enclosingVarStmt := enclosingVariableDeclaration.Parent.Parent + if !ast.IsVariableStatement(enclosingVarStmt) { + return "" + } + + initializer := enclosingVariableDeclaration.Initializer() + if initializer == nil { + return "" + } + + factory := f.changeTracker.NodeFactory + var newNodes []*ast.Node + + var baseExprNode *ast.Node + if !ast.IsIdentifier(initializer) { + // Create a temporary variable for complex expressions + tempName := f.changeTracker.EmitContext.Factory.NewUniqueNameEx("dest", printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsOptimistic}) + clonedInitializer := factory.DeepCloneNode(initializer) + varDecl := factory.NewVariableDeclaration(tempName.AsNode(), nil, nil, clonedInitializer) + varDeclList := factory.NewVariableDeclarationList(ast.NodeFlagsConst, factory.NewNodeList([]*ast.Node{varDecl})) + varStmt := factory.NewVariableStatement(nil, varDeclList) + newNodes = append(newNodes, varStmt) + baseExprNode = tempName.AsNode() + } else { + // Use a new identifier to avoid referencing original source positions + baseExprNode = factory.NewIdentifier(initializer.Text()) + } + + // Extract each binding element as a separate variable with type annotation + f.extractBindingElements(bindingPattern, baseExprNode, &newNodes, enclosingVarStmt) + + if len(newNodes) == 0 { + return "" + } + + // If the enclosing variable statement has multiple declarations, preserve the non-destructuring ones + declList := enclosingVarStmt.AsVariableStatement().DeclarationList.AsVariableDeclarationList() + if len(declList.Declarations.Nodes) > 1 { + var remainingDecls []*ast.Node + for _, d := range declList.Declarations.Nodes { + if d != enclosingVariableDeclaration { + remainingDecls = append(remainingDecls, d) + } + } + if len(remainingDecls) > 0 { + newNodes = append(newNodes, factory.UpdateVariableStatement( + enclosingVarStmt.AsVariableStatement(), + enclosingVarStmt.AsVariableStatement().Modifiers(), + factory.UpdateVariableDeclarationList( + declList, + factory.NewNodeList(remainingDecls), + ), + )) + } + } + + f.changeTracker.ReplaceNodeWithNodes(f.sourceFile, enclosingVarStmt, newNodes, nil) + return "Extract binding expressions to variable" +} + +func (f *isolatedDeclarationsFixer) extractBindingElements( + bindingPattern *ast.Node, + baseExpr *ast.Node, + newNodes *[]*ast.Node, + enclosingVarStmt *ast.Node, +) { + factory := f.changeTracker.NodeFactory + + if ast.IsObjectBindingPattern(bindingPattern) { + for _, element := range bindingPattern.AsBindingPattern().Elements.Nodes { + if ast.IsOmittedExpression(element) { + continue + } + be := element.AsBindingElement() + name := be.Name() + if name == nil { + continue + } + + // Build property access expression + var accessExpr *ast.Node + if be.PropertyName != nil && ast.IsComputedPropertyName(be.PropertyName) { + // Handle computed property names: create a temp variable for the computed expression + computedExpression := be.PropertyName.AsComputedPropertyName().Expression + identifierForComputedProperty := f.changeTracker.EmitContext.Factory.NewGeneratedNameForNode(computedExpression) + compVarDecl := factory.NewVariableDeclaration(identifierForComputedProperty.AsNode(), nil, nil, computedExpression) + compVarDeclList := factory.NewVariableDeclarationList(ast.NodeFlagsConst, factory.NewNodeList([]*ast.Node{compVarDecl})) + compVarStmt := factory.NewVariableStatement(nil, compVarDeclList) + *newNodes = append(*newNodes, compVarStmt) + accessExpr = factory.NewElementAccessExpression(baseExpr, nil, identifierForComputedProperty.AsNode(), ast.NodeFlagsNone) + } else if be.PropertyName != nil { + // Use property name text (handles identifiers, string literals, numeric literals) + propText := be.PropertyName.Text() + accessExpr = factory.NewPropertyAccessExpression(baseExpr, nil, factory.NewIdentifier(propText), ast.NodeFlagsNone) + } else if ast.IsIdentifier(name) { + accessExpr = factory.NewPropertyAccessExpression(baseExpr, nil, factory.NewIdentifier(name.Text()), ast.NodeFlagsNone) + } else { + continue + } + + if ast.IsBindingPattern(name) { + f.extractBindingElements(name, accessExpr, newNodes, enclosingVarStmt) + } else { + f.emitBindingElementVariable(factory, name, be, accessExpr, newNodes, enclosingVarStmt) + } + } + } else if ast.IsArrayBindingPattern(bindingPattern) { + for i, element := range bindingPattern.AsBindingPattern().Elements.Nodes { + if ast.IsOmittedExpression(element) { + continue + } + be := element.AsBindingElement() + name := be.Name() + if name == nil { + continue + } + + accessExpr := factory.NewElementAccessExpression(baseExpr, nil, factory.NewNumericLiteral(strconv.Itoa(i), ast.TokenFlagsNone), ast.NodeFlagsNone) + + if ast.IsBindingPattern(name) { + f.extractBindingElements(name, accessExpr, newNodes, enclosingVarStmt) + } else { + f.emitBindingElementVariable(factory, name, be, accessExpr, newNodes, enclosingVarStmt) + } + } + } +} + +// emitBindingElementVariable creates a variable declaration for a single binding element, +// handling default initializers by creating a ternary `temp === undefined ? default : temp`. +func (f *isolatedDeclarationsFixer) emitBindingElementVariable( + factory *ast.NodeFactory, + name *ast.Node, + be *ast.BindingElement, + accessExpr *ast.Node, + newNodes *[]*ast.Node, + enclosingVarStmt *ast.Node, +) { + typeNode := f.inferType(name, nil) + variableInitializer := accessExpr + + if be.Initializer != nil { + // Create a temp variable to hold the accessed value, then use a conditional expression + // to apply the default: temp === undefined ? defaultValue : temp + propName := be.PropertyName + tempBaseName := "temp" + if propName != nil && ast.IsIdentifier(propName) { + tempBaseName = propName.Text() + } + tempName := f.changeTracker.EmitContext.Factory.NewUniqueNameEx(tempBaseName, printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsOptimistic}) + tempVarDecl := factory.NewVariableDeclaration(tempName.AsNode(), nil, nil, variableInitializer) + tempVarDeclList := factory.NewVariableDeclarationList(ast.NodeFlagsConst, factory.NewNodeList([]*ast.Node{tempVarDecl})) + tempVarStmt := factory.NewVariableStatement(nil, tempVarDeclList) + *newNodes = append(*newNodes, tempVarStmt) + + variableInitializer = factory.NewConditionalExpression( + factory.NewBinaryExpression( + nil, + tempName.AsNode(), + nil, + factory.NewToken(ast.KindEqualsEqualsEqualsToken), + factory.NewIdentifier("undefined"), + ), + factory.NewToken(ast.KindQuestionToken), + be.Initializer, + factory.NewToken(ast.KindColonToken), + variableInitializer, + ) + } + + exportModifier := f.getExportModifier(enclosingVarStmt) + varDecl := factory.NewVariableDeclaration(factory.NewIdentifier(name.Text()), nil, typeNode, variableInitializer) + varDeclList := factory.NewVariableDeclarationList(ast.NodeFlagsConst, factory.NewNodeList([]*ast.Node{varDecl})) + varStmt := factory.NewVariableStatement(exportModifier, varDeclList) + *newNodes = append(*newNodes, varStmt) +} + +func (f *isolatedDeclarationsFixer) getExportModifier(enclosingVarStmt *ast.Node) *ast.ModifierList { + if ast.HasSyntacticModifier(enclosingVarStmt, ast.ModifierFlagsExport) { + exportToken := f.changeTracker.NodeFactory.NewToken(ast.KindExportKeyword) + return f.changeTracker.NodeFactory.NewModifierList([]*ast.Node{exportToken}) + } + return nil +} + +func (f *isolatedDeclarationsFixer) inferType(node *ast.Node, variableType *checker.Type) *ast.TypeNode { + f.mutatedTarget = false + + // Handle Relative mode first: return typeof X for identifiers + if f.typePrintMode == typePrintModeRelative { + return f.relativeType(node) + } + + var t *checker.Type + + if isValueSignatureDeclaration(node) { + signature := f.checker.GetSignatureFromDeclaration(node) + if signature != nil { + typePredicate := f.checker.GetTypePredicateOfSignature(signature) + if typePredicate != nil { + if typePredicate.Type() == nil { + return nil + } + enclosingDecl := ast.FindAncestor(node, ast.IsDeclaration) + if enclosingDecl == nil { + enclosingDecl = f.sourceFile.AsNode() + } + flags := declarationEmitNodeBuilderFlags + if typePredicate.Type().Flags()&checker.TypeFlagsUniqueESSymbol != 0 { + flags |= nodebuilder.FlagsAllowUniqueESSymbolType + } + result := f.checker.TypePredicateToTypePredicateNode(typePredicate, enclosingDecl, flags, nil) + if result != nil { + return result.AsNode() + } + return nil + } + t = f.checker.GetReturnTypeOfSignature(signature) + } + } else { + t = f.checker.GetTypeAtLocation(node) + } + + if t == nil { + return nil + } + + // Handle Widened mode: return widened literal type if different + if f.typePrintMode == typePrintModeWidened { + if variableType != nil { + t = variableType + } + widenedType := f.checker.GetWidenedLiteralType(t) + if f.checker.IsTypeAssignableTo(widenedType, t) { + return nil // widened type is same, no fix needed + } + t = widenedType + } + + enclosingDecl := ast.FindAncestor(node, ast.IsDeclaration) + if enclosingDecl == nil { + enclosingDecl = f.sourceFile.AsNode() + } + + flags := declarationEmitNodeBuilderFlags | f.getExtraFlags(node, t) + + // For parameters that require adding implicit undefined, add it to the type + if ast.IsParameter(node) && f.checker.RequiresAddingImplicitUndefined(node) { + t = f.checker.GetUnionTypeEx([]*checker.Type{f.checker.GetUndefinedType(), t}, checker.UnionReductionNone) + } + + typeNode := f.typeToMinimizedReferenceType(t, enclosingDecl, flags) + return typeNode +} + +func (f *isolatedDeclarationsFixer) getExtraFlags(node *ast.Node, t *checker.Type) nodebuilder.Flags { + if (ast.IsVariableDeclaration(node) || + (ast.IsPropertyDeclaration(node) && ast.HasSyntacticModifier(node, ast.ModifierFlagsStatic|ast.ModifierFlagsReadonly))) && + t.Flags()&checker.TypeFlagsUniqueESSymbol != 0 { + return nodebuilder.FlagsAllowUniqueESSymbolType + } + return nodebuilder.FlagsNone +} + +// createTypeOfFromEntityNameExpression creates a `typeof X` type query node. +func (f *isolatedDeclarationsFixer) createTypeOfFromEntityNameExpression(node *ast.Node) *ast.TypeNode { + return f.changeTracker.NodeFactory.NewTypeQueryNode( + f.changeTracker.NodeFactory.DeepCloneNode(node), nil) +} + +// typeFromArraySpreadElements decomposes an array literal with spread elements into +// separate variables, returning a tuple type of typeof references. +func (f *isolatedDeclarationsFixer) typeFromArraySpreadElements(node *ast.ArrayLiteralExpression, name string) *ast.TypeNode { + isInConstContext := ast.FindAncestor(node.AsNode(), isConstAssertion) != nil + if !isInConstContext { + return nil + } + if name == "" { + name = "temp" + } + factory := f.changeTracker.NodeFactory + return f.typeFromSpreads( + node.AsNode(), + name, + isInConstContext, + func(n *ast.Node) []*ast.Node { + return n.AsArrayLiteralExpression().Elements.Nodes + }, + ast.IsSpreadElement, + func(expr *ast.Node) *ast.Node { + return factory.NewSpreadElement(expr) + }, + func(elements []*ast.Node) *ast.Node { + return factory.NewArrayLiteralExpression(factory.NewNodeList(elements), true) + }, + func(types []*ast.TypeNode) *ast.TypeNode { + restTypes := make([]*ast.TypeNode, len(types)) + for i, t := range types { + restTypes[i] = factory.NewRestTypeNode(t) + } + return factory.NewTupleTypeNode(factory.NewNodeList(restTypes)) + }, + ) +} + +// typeFromObjectSpreadAssignment decomposes an object literal with spread assignments into +// separate variables, returning an intersection type of typeof references. +func (f *isolatedDeclarationsFixer) typeFromObjectSpreadAssignment(node *ast.ObjectLiteralExpression, name string) *ast.TypeNode { + isInConstContext := ast.FindAncestor(node.AsNode(), isConstAssertion) != nil + if name == "" { + name = "temp" + } + factory := f.changeTracker.NodeFactory + return f.typeFromSpreads( + node.AsNode(), + name, + isInConstContext, + func(n *ast.Node) []*ast.Node { + if n.AsObjectLiteralExpression().Properties != nil { + return n.AsObjectLiteralExpression().Properties.Nodes + } + return nil + }, + ast.IsSpreadAssignment, + func(expr *ast.Node) *ast.Node { + return factory.NewSpreadAssignment(expr) + }, + func(elements []*ast.Node) *ast.Node { + return factory.NewObjectLiteralExpression(factory.NewNodeList(elements), true) + }, + func(types []*ast.TypeNode) *ast.TypeNode { + return factory.NewIntersectionTypeNode(factory.NewNodeList(types)) + }, + ) +} + +// typeFromSpreads is the generic spread decomposition function, ported from TS's typeFromSpreads. +// It splits a literal with spread elements into separate const variables and returns a composed type. +func (f *isolatedDeclarationsFixer) typeFromSpreads( + node *ast.Node, + name string, + isInConstContext bool, + getChildren func(*ast.Node) []*ast.Node, + isSpread func(*ast.Node) bool, + createSpread func(*ast.Node) *ast.Node, + makeNodeOfKind func([]*ast.Node) *ast.Node, + finalType func([]*ast.TypeNode) *ast.TypeNode, +) *ast.TypeNode { + factory := f.changeTracker.NodeFactory + var intersectionTypes []*ast.TypeNode + var newSpreads []*ast.Node + var currentVariableProperties []*ast.Node + + statement := ast.FindAncestor(node, ast.IsStatement) + + children := getChildren(node) + for _, prop := range children { + if isSpread(prop) { + f.finalizesVariablePart(factory, name, isInConstContext, statement, makeNodeOfKind, createSpread, ¤tVariableProperties, &intersectionTypes, &newSpreads) + if ast.IsEntityNameExpression(prop.Expression()) { + intersectionTypes = append(intersectionTypes, f.createTypeOfFromEntityNameExpression(prop.Expression())) + newSpreads = append(newSpreads, prop) + } else { + f.makeSpreadVariable(factory, name, isInConstContext, statement, createSpread, prop.Expression(), &intersectionTypes, &newSpreads) + } + } else { + currentVariableProperties = append(currentVariableProperties, prop) + } + } + + if len(newSpreads) == 0 { + return nil + } + + f.finalizesVariablePart(factory, name, isInConstContext, statement, makeNodeOfKind, createSpread, ¤tVariableProperties, &intersectionTypes, &newSpreads) + + f.changeTracker.ReplaceNode(f.sourceFile, node, makeNodeOfKind(newSpreads), nil) + f.mutatedTarget = true + + return finalType(intersectionTypes) +} + +// makeSpreadVariable creates a const variable for a spread expression and adds it to the decomposition. +func (f *isolatedDeclarationsFixer) makeSpreadVariable( + factory *ast.NodeFactory, + name string, + isInConstContext bool, + statement *ast.Node, + createSpread func(*ast.Node) *ast.Node, + expression *ast.Node, + intersectionTypes *[]*ast.TypeNode, + newSpreads *[]*ast.Node, +) { + tempName := f.changeTracker.EmitContext.Factory.NewUniqueNameEx( + name+"_Part"+strconv.Itoa(len(*newSpreads)+1), + printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsOptimistic}, + ).AsNode() + + var initializer *ast.Node + if !isInConstContext { + initializer = factory.DeepCloneNode(expression) + } else { + constRef := factory.NewTypeReferenceNode(factory.NewIdentifier("const"), nil) + initializer = factory.NewAsExpression(factory.DeepCloneNode(expression), constRef) + } + + varDecl := factory.NewVariableDeclaration(tempName, nil, nil, initializer) + varDeclList := factory.NewVariableDeclarationList(ast.NodeFlagsConst, factory.NewNodeList([]*ast.Node{varDecl})) + varStmt := factory.NewVariableStatement(nil, varDeclList) + + if statement != nil { + f.changeTracker.InsertNodeBefore(f.sourceFile, statement, varStmt, false, change.LeadingTriviaOptionNone) + } + + *intersectionTypes = append(*intersectionTypes, f.createTypeOfFromEntityNameExpression(tempName)) + *newSpreads = append(*newSpreads, createSpread(tempName)) +} + +// finalizesVariablePart finalizes accumulated non-spread properties into a variable. +func (f *isolatedDeclarationsFixer) finalizesVariablePart( + factory *ast.NodeFactory, + name string, + isInConstContext bool, + statement *ast.Node, + makeNodeOfKind func([]*ast.Node) *ast.Node, + createSpread func(*ast.Node) *ast.Node, + currentVariableProperties *[]*ast.Node, + intersectionTypes *[]*ast.TypeNode, + newSpreads *[]*ast.Node, +) { + if len(*currentVariableProperties) > 0 { + f.makeSpreadVariable(factory, name, isInConstContext, statement, createSpread, makeNodeOfKind(*currentVariableProperties), intersectionTypes, newSpreads) + *currentVariableProperties = nil + } +} + +// isConstAssertion checks if a node is an `as const` or `` assertion. +func isConstAssertion(node *ast.Node) bool { + if ast.IsAssertionExpression(node) { + typeNode := node.Type() + return ast.IsConstTypeReference(typeNode) + } + return false +} + +// relativeType creates a typeof expression for a node, used in TypePrintMode.Relative. +// Instead of spelling out the full type, returns `typeof X` for identifiers. +// For object/array literals with spreads, decomposes into separate variables. +func (f *isolatedDeclarationsFixer) relativeType(node *ast.Node) *ast.TypeNode { + if ast.IsParameter(node) { + return nil + } + if ast.IsShorthandPropertyAssignment(node) { + return f.createTypeOfFromEntityNameExpression(node.AsShorthandPropertyAssignment().Name()) + } + if ast.IsEntityNameExpression(node) { + return f.createTypeOfFromEntityNameExpression(node) + } + if isConstAssertion(node) { + return f.relativeType(node.Expression()) + } + if ast.IsArrayLiteralExpression(node) { + varDecl := ast.FindAncestorKind(node, ast.KindVariableDeclaration) + partName := "" + if varDecl != nil && ast.IsIdentifier(varDecl.Name()) { + partName = varDecl.Name().AsIdentifier().Text + } + return f.typeFromArraySpreadElements(node.AsArrayLiteralExpression(), partName) + } + if ast.IsObjectLiteralExpression(node) { + varDecl := ast.FindAncestorKind(node, ast.KindVariableDeclaration) + partName := "" + if varDecl != nil && ast.IsIdentifier(varDecl.Name()) { + partName = varDecl.Name().AsIdentifier().Text + } + return f.typeFromObjectSpreadAssignment(node.AsObjectLiteralExpression(), partName) + } + if ast.IsVariableDeclaration(node) && node.Initializer() != nil { + return f.relativeType(node.Initializer()) + } + if ast.IsConditionalExpression(node) { + cond := node.AsConditionalExpression() + trueType := f.relativeType(cond.WhenTrue) + if trueType == nil { + return nil + } + trueMutated := f.mutatedTarget + falseType := f.relativeType(cond.WhenFalse) + if falseType == nil { + return nil + } + f.mutatedTarget = trueMutated || f.mutatedTarget + factory := f.changeTracker.NodeFactory + return factory.NewUnionTypeNode(factory.NewNodeList([]*ast.Node{trueType, falseType})) + } + return nil +} + +// typeToMinimizedReferenceType converts a type to a type node, then trims trailing +// type arguments that match their defaults. Ported from TS's +// services/codefixes/helpers.ts typeToMinimizedReferenceType. +func (f *isolatedDeclarationsFixer) typeToMinimizedReferenceType(t *checker.Type, enclosingDecl *ast.Node, flags nodebuilder.Flags) *ast.TypeNode { + idToSymbol := make(map[*ast.IdentifierNode]*ast.Symbol) + // !!! When truncation tracking is supported, check if the type was truncated + // and return factory.NewKeywordTypeNode(ast.KindAnyKeyword) instead of the truncated node. + typeNode := f.checker.TypeToTypeNodeEx(t, enclosingDecl, flags, nodebuilder.InternalFlagsWriteComputedProps, idToSymbol) + if typeNode == nil { + return nil + } + if ast.IsTypeReferenceNode(typeNode) && t.ObjectFlags()&checker.ObjectFlagsReference != 0 { + typeArgs := f.checker.GetTypeArguments(t) + nodeTypeArgs := typeNode.TypeArguments() + if len(typeArgs) > 0 && len(nodeTypeArgs) > 0 { + cutoff := endOfRequiredTypeParameters(f.checker, t) + if cutoff < len(nodeTypeArgs) { + // Trim trailing default type arguments + trimmedArgs := f.changeTracker.NodeFactory.NewNodeList(nodeTypeArgs[:cutoff]) + typeNode = f.changeTracker.NodeFactory.UpdateTypeReferenceNode( + typeNode.AsTypeReferenceNode(), + typeNode.AsTypeReferenceNode().TypeName, + trimmedArgs, + ) + } + } + } + // Convert import type references (e.g. import("./path").Name) to simple type references + // and collect symbols that need to be imported + referenceTypeNode, importableSymbols := autoimport.TryGetAutoImportableReferenceFromTypeNode(typeNode, idToSymbol) + if referenceTypeNode != nil { + typeNode = referenceTypeNode + f.symbolsToImport = append(f.symbolsToImport, importableSymbols...) + } + return typeNode +} + +// endOfRequiredTypeParameters finds the number of type arguments that are +// actually required (i.e., differ from their defaults). Ported from TS's +// services/codefixes/helpers.ts endOfRequiredTypeParameters. +func endOfRequiredTypeParameters(ch *checker.Checker, t *checker.Type) int { + typeArgs := ch.GetTypeArguments(t) + if len(typeArgs) == 0 { + return 0 + } + target := t.Target() + if target == nil || target.AsInterfaceType() == nil { + return len(typeArgs) + } + typeParams := target.AsInterfaceType().TypeParameters() + localTypeParams := target.AsInterfaceType().LocalTypeParameters() + outerCount := len(typeParams) - len(localTypeParams) + for cutoff := range typeArgs { + // Skip cutoff positions where the local type parameter has no default. + // This matches TS's check for constraint === undefined on localTypeParameters, + // which in practice skips type parameters without defaults (e.g. Set + // where T has no default should not have elided). + localIdx := cutoff - outerCount + if localIdx < 0 || localIdx >= len(localTypeParams) || !typeParamHasDefault(localTypeParams[localIdx]) { + continue + } + filledIn := ch.FillMissingTypeArguments(typeArgs[:cutoff], typeParams, cutoff, false) + allMatch := true + for i, fill := range filledIn { + if fill != typeArgs[i] { + allMatch = false + break + } + } + if allMatch { + return cutoff + } + } + return len(typeArgs) +} + +// typeParamHasDefault checks if a type parameter has a default type declaration. +func typeParamHasDefault(tp *checker.Type) bool { + sym := tp.Symbol() + if sym == nil { + return false + } + for _, decl := range sym.Declarations { + if ast.IsTypeParameterDeclaration(decl) && decl.AsTypeParameter().DefaultType != nil { + return true + } + } + return false +} + +func (f *isolatedDeclarationsFixer) addTypeToVariableLike(decl *ast.Node) string { + typeNode := f.inferType(decl, nil) + if typeNode == nil { + return "" + } + if decl.Type() != nil { + f.changeTracker.ReplaceNode(f.sourceFile, decl.Type(), typeNode, nil) + } else { + f.changeTracker.TryInsertTypeAnnotation(f.sourceFile, decl, typeNode) + } + return fmt.Sprintf("Add annotation of type '%s'", typeToStringForDiag(typeNode, f.sourceFile, f.changeTracker)) +} + +// typeToStringForDiag converts a type node to a string for use in diagnostic descriptions. +// It reuses the change tracker's EmitContext so that generated identifier names are resolved +// consistently with the actual code edits, and passes the source file so that the printer's +// name generator can check for conflicts with existing file-level identifiers. +func typeToStringForDiag(typeNode *ast.Node, sourceFile *ast.SourceFile, ct *change.Tracker) string { + savedFlags := ct.EmitContext.EmitFlags(typeNode) + ct.EmitContext.SetEmitFlags(typeNode, savedFlags|printer.EFSingleLine) + p := printer.NewPrinter( + printer.PrinterOptions{ + NewLine: core.NewLineKindLF, + }, + printer.PrintHandlers{}, + ct.EmitContext, + ) + writer, release := printer.GetSingleLineStringWriter() + defer release() + p.Write(typeNode, sourceFile, writer, nil) + ct.EmitContext.SetEmitFlags(typeNode, savedFlags) + result := writer.String() + if len(result) > 160 { + return result[:157] + "..." + } + return result +} + +// findAncestorWithMissingType walks up the ancestor chain to find a node that +// can have a type annotation and is missing one. +func findAncestorWithMissingType(node *ast.Node) *ast.Node { + return ast.FindAncestor(node, func(n *ast.Node) bool { + if !canHaveTypeAnnotationKinds[n.Kind] { + return false + } + if ast.IsObjectBindingPattern(n) || ast.IsArrayBindingPattern(n) { + return ast.IsVariableDeclaration(n.Parent) + } + return true + }) +} + +// findBestFittingNode walks up from the token to find the node that best fits the diagnostic span. +func findBestFittingNode(node *ast.Node, span core.TextRange) *ast.Node { + if node == nil { + return nil + } + for node != nil && node.End() < span.Pos()+span.Len() { + node = node.Parent + } + for node.Parent != nil && node.Parent.Pos() == node.Pos() && node.Parent.End() == node.End() { + node = node.Parent + } + if ast.IsIdentifier(node) && ast.HasInitializer(node.Parent) && node.Parent.Initializer() != nil { + return node.Parent.Initializer() + } + if ast.IsIdentifier(node) && ast.IsShorthandPropertyAssignment(node.Parent) { + return node.Parent + } + return node +} + +// isNamedDeclarationKind matches TS's isDeclarationKind, which is narrower than Go's IsDeclaration. +// Go's IsDeclaration returns true for any node with DeclarationData (including CallExpression), +// while TS's isDeclaration only returns true for specific named declaration kinds. +func isNamedDeclarationKind(node *ast.Node) bool { + switch node.Kind { + case ast.KindArrowFunction, ast.KindBindingElement, ast.KindClassDeclaration, ast.KindClassExpression, + ast.KindClassStaticBlockDeclaration, ast.KindConstructor, ast.KindEnumDeclaration, ast.KindEnumMember, + ast.KindExportSpecifier, ast.KindFunctionDeclaration, ast.KindFunctionExpression, + ast.KindGetAccessor, ast.KindImportClause, ast.KindImportEqualsDeclaration, + ast.KindImportSpecifier, ast.KindInterfaceDeclaration, ast.KindJsxAttribute, + ast.KindMethodDeclaration, ast.KindMethodSignature, ast.KindModuleDeclaration, + ast.KindNamespaceExportDeclaration, ast.KindNamespaceImport, ast.KindNamespaceExport, + ast.KindParameter, ast.KindPropertyAssignment, ast.KindPropertyDeclaration, + ast.KindPropertySignature, ast.KindSetAccessor, ast.KindShorthandPropertyAssignment, + ast.KindTypeAliasDeclaration, ast.KindTypeParameter, ast.KindVariableDeclaration, + ast.KindJSDocTypedefTag, ast.KindJSDocCallbackTag, ast.KindJSDocPropertyTag, + ast.KindNamedTupleMember: + return true + } + return false +} + +// isValueSignatureDeclaration checks if a node is a function-like declaration that produces a value. +func isValueSignatureDeclaration(node *ast.Node) bool { + return ast.IsFunctionExpression(node) || ast.IsArrowFunction(node) || ast.IsMethodDeclaration(node) || + ast.IsAccessor(node) || ast.IsFunctionDeclaration(node) || ast.IsConstructorDeclaration(node) +} + +// getIdentifierNameForNode derives a meaningful variable name from a node expression. +// For property access expressions like `obj.foo`, returns "foo". Otherwise returns "newLocal". +// Ported from TS's getIdentifierForNode in services/refactors/helpers.ts. +func getIdentifierNameForNode(node *ast.Node) string { + if ast.IsPropertyAccessExpression(node) { + name := node.AsPropertyAccessExpression().Name() + if ast.IsIdentifier(name) && !ast.IsPrivateIdentifier(name) && scanner.IdentifierToKeywordKind(name.AsIdentifier()) == ast.KindUnknown { + return name.Text() + } + } + return "newLocal" +} + +// addSymbolToExistingImport finds the existing import declaration for the symbol's module +// and adds the symbol name to the named imports. +func (f *isolatedDeclarationsFixer) addSymbolToExistingImport(sym *ast.Symbol) { + if sym == nil || sym.Parent == nil { + return + } + + // Find the module specifier for this symbol + moduleSymbol := sym.Parent + symbolName := sym.Name + + // Walk the source file's import declarations to find the one importing from the same module + for _, stmt := range f.sourceFile.Statements.Nodes { + if !ast.IsImportDeclaration(stmt) { + continue + } + importDecl := stmt.AsImportDeclaration() + if importDecl.ImportClause == nil { + continue + } + + // Check if this import is from the same module + importModuleSymbol := f.checker.GetSymbolAtLocation(importDecl.ModuleSpecifier) + if importModuleSymbol == nil || f.checker.GetMergedSymbol(importModuleSymbol) != f.checker.GetMergedSymbol(moduleSymbol) { + continue + } + + // Found the matching import - add the symbol to named imports + importClause := importDecl.ImportClause.AsImportClause() + if importClause.NamedBindings != nil && ast.IsNamedImports(importClause.NamedBindings) { + // Add to existing named imports + existingElements := importClause.NamedBindings.AsNamedImports().Elements.Nodes + factory := f.changeTracker.NodeFactory + newSpecifier := factory.NewImportSpecifier(false, nil, factory.NewIdentifier(symbolName)) + newElements := append(existingElements, newSpecifier.AsNode()) + newNamedImports := factory.NewNamedImports(factory.NewNodeList(newElements)) + newImportClause := factory.UpdateImportClause(importClause, importClause.PhaseModifier, importClause.Name(), newNamedImports) + newImportDecl := factory.UpdateImportDeclaration(importDecl, importDecl.Modifiers(), newImportClause, importDecl.ModuleSpecifier, importDecl.Attributes) + f.changeTracker.ReplaceNode(f.sourceFile, stmt, newImportDecl.AsNode(), nil) + } + return + } +} diff --git a/internal/printer/changetrackerwriter.go b/internal/printer/changetrackerwriter.go index 9e365030e22..89fc4c165ea 100644 --- a/internal/printer/changetrackerwriter.go +++ b/internal/printer/changetrackerwriter.go @@ -108,7 +108,10 @@ func (ct *ChangeTrackerWriter) AssignPositionsToNode(node *ast.Node, factory *as VisitToken: ct.assignPositionsToNodeWorker, VisitModifiers: func(modifiers *ast.ModifierList, v *ast.NodeVisitor) *ast.ModifierList { if modifiers != nil { - ct.assignPositionsToNodeArray(&modifiers.NodeList, v) + newNodeList := ct.assignPositionsToNodeArray(&modifiers.NodeList, v) + // Return a new ModifierList so that VisitEachChild/Update detects the + // change and creates a new node with reassigned child positions. + return factory.NewModifierList(newNodeList.Nodes) } return modifiers }, diff --git a/internal/printer/printer.go b/internal/printer/printer.go index 8e436b023b2..5878360f9d4 100644 --- a/internal/printer/printer.go +++ b/internal/printer/printer.go @@ -233,12 +233,13 @@ func (p *Printer) getTextOfNode(node *ast.Node, includeTrivia bool) string { } } + canUseSourceFile := p.currentSourceFile != nil && node.Parent != nil && !ast.NodeIsSynthesized(node) + switch node.Kind { case ast.KindIdentifier, ast.KindPrivateIdentifier, ast.KindJsxNamespacedName: - // !!! If `node` is not a parse tree node, verify its original node comes from the same source file - if p.currentSourceFile == nil || node.Parent == nil || ast.NodeIsSynthesized(node) { + if !canUseSourceFile || ast.GetSourceFileOfNode(node) != p.emitContext.MostOriginal(p.currentSourceFile.AsNode()).AsSourceFile() { return node.Text() } case ast.KindStringLiteral, diff --git a/internal/testrunner/test_case_parser.go b/internal/testrunner/test_case_parser.go index af8fd77d0d9..98a16e97356 100644 --- a/internal/testrunner/test_case_parser.go +++ b/internal/testrunner/test_case_parser.go @@ -141,6 +141,7 @@ func ParseTestFilesAndSymlinksWithOptions[T any]( // Stuff related to the subfile we're parsing var currentFileContent strings.Builder var currentFileName string + seenContentLine := false hasSeenFile := false if options.AllowImplicitFirstFile { // For fourslash tests, initialize currentFileName to the fileName parameter @@ -203,6 +204,7 @@ func ParseTestFilesAndSymlinksWithOptions[T any]( // Reset local data currentFileContent.Reset() + seenContentLine = false currentFileName = metaDataValue currentFileOptions = make(map[string]string) } else { @@ -227,15 +229,25 @@ func ParseTestFilesAndSymlinksWithOptions[T any]( // Reset for the new file currentFileContent.Reset() + seenContentLine = false currentFileName = strings.TrimSpace(testMetaData[2]) currentFileOptions = make(map[string]string) } } else { // Subfile content line // Append to the current subfile content, inserting a newline if needed - if currentFileContent.Len() != 0 { - // End-of-line - currentFileContent.WriteRune('\n') + // For fourslash tests, use seenContentLine to preserve leading blank lines + // (matching TS fourslash's //// content markers). For compiler tests, use + // Len() != 0 which drops leading blanks (matching TS's harness behavior). + if options.AllowImplicitFirstFile { + if seenContentLine { + currentFileContent.WriteRune('\n') + } + seenContentLine = true + } else { + if currentFileContent.Len() != 0 { + currentFileContent.WriteRune('\n') + } } currentFileContent.WriteString(line) } diff --git a/testdata/baselines/reference/fourslash/autoImports/autoImportFileExcludePatterns.baseline.md b/testdata/baselines/reference/fourslash/autoImports/autoImportFileExcludePatterns.baseline.md index b977e80852b..bb1951581b2 100644 --- a/testdata/baselines/reference/fourslash/autoImports/autoImportFileExcludePatterns.baseline.md +++ b/testdata/baselines/reference/fourslash/autoImports/autoImportFileExcludePatterns.baseline.md @@ -4,7 +4,7 @@ mySym/*1*/ ignoredSym ``````ts -import { mySymbol } from "./foo"; +import { mySymbol } from "./foo" mySym ignoredSym diff --git a/testdata/baselines/reference/fourslash/autoImports/autoImportSpecifierExcludeRegexes.baseline.md b/testdata/baselines/reference/fourslash/autoImports/autoImportSpecifierExcludeRegexes.baseline.md index b977e80852b..bb1951581b2 100644 --- a/testdata/baselines/reference/fourslash/autoImports/autoImportSpecifierExcludeRegexes.baseline.md +++ b/testdata/baselines/reference/fourslash/autoImports/autoImportSpecifierExcludeRegexes.baseline.md @@ -4,7 +4,7 @@ mySym/*1*/ ignoredSym ``````ts -import { mySymbol } from "./foo"; +import { mySymbol } from "./foo" mySym ignoredSym diff --git a/testdata/baselines/reference/fourslash/codeLenses/codeLensFunctionsAndConstants01.baseline.jsonc b/testdata/baselines/reference/fourslash/codeLenses/codeLensFunctionsAndConstants01.baseline.jsonc index 5c306865e3a..064c8307259 100644 --- a/testdata/baselines/reference/fourslash/codeLenses/codeLensFunctionsAndConstants01.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/codeLenses/codeLensFunctionsAndConstants01.baseline.jsonc @@ -1,5 +1,6 @@ // === Code Lenses === // === /exports.ts === +// // let callCount = 0; // export function /*CODELENS: 3 references*/foo(n: number): void { // callCount++; @@ -34,7 +35,7 @@ // // === /exports.ts === -// --- (line: 10) skipped --- +// --- (line: 11) skipped --- // // foo(5); // diff --git a/testdata/baselines/reference/fourslash/codeLenses/codeLensOverloads01.baseline.jsonc b/testdata/baselines/reference/fourslash/codeLenses/codeLensOverloads01.baseline.jsonc index f8163d73a46..1ccb0d61ac5 100644 --- a/testdata/baselines/reference/fourslash/codeLenses/codeLensOverloads01.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/codeLenses/codeLensOverloads01.baseline.jsonc @@ -1,5 +1,6 @@ // === Code Lenses === // === /codeLensOverloads01.ts === +// // export function /*CODELENS: 3 references*/foo(x: number): number; // export function foo(x: string): string; // export function foo(x: string | number): string | number { diff --git a/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnAllClassMethods=false.baseline.jsonc b/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnAllClassMethods=false.baseline.jsonc index 09d45e997ce..165db624f2f 100644 --- a/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnAllClassMethods=false.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnAllClassMethods=false.baseline.jsonc @@ -1,27 +1,29 @@ // === Code Lenses === // === /codeLensReferencesShowOnAllClassMethods=false.ts === +// // export abstract class /*CODELENS: 0 implementations*/ABC { // abstract methodA(): void; // methodB(): void {} // #methodC(): void {} -// --- (line: 5) skipped --- +// --- (line: 6) skipped --- // === Code Lenses === // === /codeLensReferencesShowOnAllClassMethods=false.ts === +// // export abstract class ABC { // abstract /*CODELENS: 0 implementations*/methodA(): void; // methodB(): void {} // #methodC(): void {} // protected methodD(): void {} -// --- (line: 6) skipped --- +// --- (line: 7) skipped --- // === Code Lenses === // === /codeLensReferencesShowOnAllClassMethods=false.ts === -// --- (line: 3) skipped --- +// --- (line: 4) skipped --- // #methodC(): void {} // protected methodD(): void {} // private methodE(): void {} @@ -29,4 +31,4 @@ // public methodH(): void {} // // static methodStaticA(): void {} -// --- (line: 11) skipped --- \ No newline at end of file +// --- (line: 12) skipped --- \ No newline at end of file diff --git a/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnAllClassMethods=true.baseline.jsonc b/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnAllClassMethods=true.baseline.jsonc index 7da1d95f5d3..feb76cca92e 100644 --- a/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnAllClassMethods=true.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnAllClassMethods=true.baseline.jsonc @@ -1,38 +1,42 @@ // === Code Lenses === // === /codeLensReferencesShowOnAllClassMethods=true.ts === +// // export abstract class /*CODELENS: 0 implementations*/ABC { // abstract methodA(): void; // methodB(): void {} // #methodC(): void {} -// --- (line: 5) skipped --- +// --- (line: 6) skipped --- // === Code Lenses === // === /codeLensReferencesShowOnAllClassMethods=true.ts === +// // export abstract class ABC { // abstract /*CODELENS: 0 implementations*/methodA(): void; // methodB(): void {} // #methodC(): void {} // protected methodD(): void {} -// --- (line: 6) skipped --- +// --- (line: 7) skipped --- // === Code Lenses === // === /codeLensReferencesShowOnAllClassMethods=true.ts === +// // export abstract class ABC { // abstract methodA(): void; // /*CODELENS: 0 implementations*/methodB(): void {} // #methodC(): void {} // protected methodD(): void {} // private methodE(): void {} -// --- (line: 7) skipped --- +// --- (line: 8) skipped --- // === Code Lenses === // === /codeLensReferencesShowOnAllClassMethods=true.ts === +// // export abstract class ABC { // abstract methodA(): void; // methodB(): void {} @@ -41,13 +45,13 @@ // private methodE(): void {} // protected abstract methodG(): void; // public methodH(): void {} -// --- (line: 9) skipped --- +// --- (line: 10) skipped --- // === Code Lenses === // === /codeLensReferencesShowOnAllClassMethods=true.ts === -// --- (line: 3) skipped --- +// --- (line: 4) skipped --- // #methodC(): void {} // protected methodD(): void {} // private methodE(): void {} @@ -55,13 +59,13 @@ // public methodH(): void {} // // static methodStaticA(): void {} -// --- (line: 11) skipped --- +// --- (line: 12) skipped --- // === Code Lenses === // === /codeLensReferencesShowOnAllClassMethods=true.ts === -// --- (line: 4) skipped --- +// --- (line: 5) skipped --- // protected methodD(): void {} // private methodE(): void {} // protected abstract methodG(): void; @@ -69,13 +73,13 @@ // // static methodStaticA(): void {} // protected static methodStaticB(): void {} -// --- (line: 12) skipped --- +// --- (line: 13) skipped --- // === Code Lenses === // === /codeLensReferencesShowOnAllClassMethods=true.ts === -// --- (line: 6) skipped --- +// --- (line: 7) skipped --- // protected abstract methodG(): void; // public methodH(): void {} // @@ -90,7 +94,7 @@ // === Code Lenses === // === /codeLensReferencesShowOnAllClassMethods=true.ts === -// --- (line: 7) skipped --- +// --- (line: 8) skipped --- // public methodH(): void {} // // static methodStaticA(): void {} diff --git a/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnAllFunctions=false.baseline.jsonc b/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnAllFunctions=false.baseline.jsonc index 7bb4a5657d6..241fe64324e 100644 --- a/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnAllFunctions=false.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnAllFunctions=false.baseline.jsonc @@ -1,15 +1,17 @@ // === Code Lenses === // === /codeLensReferencesShowOnAllFunctions=false.ts === +// // export function /*CODELENS: 0 references*/f1(): void {} // // function f2(): void {} // -// --- (line: 5) skipped --- +// --- (line: 6) skipped --- // === Code Lenses === // === /codeLensReferencesShowOnAllFunctions=false.ts === +// // export function f1(): void {} // // function f2(): void {} diff --git a/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnAllFunctions=true.baseline.jsonc b/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnAllFunctions=true.baseline.jsonc index b890c7f5c1b..358fee380db 100644 --- a/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnAllFunctions=true.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnAllFunctions=true.baseline.jsonc @@ -1,27 +1,30 @@ // === Code Lenses === // === /codeLensReferencesShowOnAllFunctions=true.ts === +// // export function /*CODELENS: 0 references*/f1(): void {} // // function f2(): void {} // -// --- (line: 5) skipped --- +// --- (line: 6) skipped --- // === Code Lenses === // === /codeLensReferencesShowOnAllFunctions=true.ts === +// // export function f1(): void {} // // function /*CODELENS: 0 references*/f2(): void {} // // export const f3 = () => {}; // -// --- (line: 7) skipped --- +// --- (line: 8) skipped --- // === Code Lenses === // === /codeLensReferencesShowOnAllFunctions=true.ts === +// // export function f1(): void {} // // function f2(): void {} diff --git a/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnInterfaceMethods=false.baseline.jsonc b/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnInterfaceMethods=false.baseline.jsonc index 5f9918a03c1..1cea1d23303 100644 --- a/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnInterfaceMethods=false.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnInterfaceMethods=false.baseline.jsonc @@ -1,5 +1,6 @@ // === Code Lenses === // === /codeLensReferencesShowOnInterfaceMethods=false.ts === +// // export interface /*CODELENS: 3 implementations*/I { // methodA(): void; // } @@ -29,7 +30,7 @@ // === Code Lenses === // === /codeLensReferencesShowOnInterfaceMethods=false.ts === -// --- (line: 4) skipped --- +// --- (line: 5) skipped --- // methodB(): void; // } // @@ -55,7 +56,7 @@ // === Code Lenses === // === /codeLensReferencesShowOnInterfaceMethods=false.ts === -// --- (line: 16) skipped --- +// --- (line: 17) skipped --- // } // // class AbstractC implements J { @@ -69,7 +70,7 @@ // === Code Lenses === // === /codeLensReferencesShowOnInterfaceMethods=false.ts === -// --- (line: 18) skipped --- +// --- (line: 19) skipped --- // class AbstractC implements J { // abstract methodA(): void; // methodB(): void {} diff --git a/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnInterfaceMethods=true.baseline.jsonc b/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnInterfaceMethods=true.baseline.jsonc index cf498182d5a..b13f2491e4d 100644 --- a/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnInterfaceMethods=true.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/codeLenses/codeLensReferencesShowOnInterfaceMethods=true.baseline.jsonc @@ -1,5 +1,6 @@ // === Code Lenses === // === /codeLensReferencesShowOnInterfaceMethods=true.ts === +// // export interface /*CODELENS: 3 implementations*/I { // methodA(): void; // } @@ -29,14 +30,15 @@ // === Code Lenses === // === /codeLensReferencesShowOnInterfaceMethods=true.ts === +// // export interface I { // /*CODELENS: 1 implementation*/methodA(): void; // } // export interface I { // methodB(): void; -// --- (line: 6) skipped --- +// --- (line: 7) skipped --- -// --- (line: 10) skipped --- +// --- (line: 11) skipped --- // } // // class C implements J { @@ -44,12 +46,13 @@ // methodB(): void {} // methodC(): void {} // } -// --- (line: 18) skipped --- +// --- (line: 19) skipped --- // === Code Lenses === // === /codeLensReferencesShowOnInterfaceMethods=true.ts === +// // export interface I { // methodA(): void; // } @@ -79,7 +82,7 @@ // === Code Lenses === // === /codeLensReferencesShowOnInterfaceMethods=true.ts === -// --- (line: 4) skipped --- +// --- (line: 5) skipped --- // methodB(): void; // } // @@ -105,7 +108,7 @@ // === Code Lenses === // === /codeLensReferencesShowOnInterfaceMethods=true.ts === -// --- (line: 5) skipped --- +// --- (line: 6) skipped --- // } // // interface J extends I { @@ -130,7 +133,7 @@ // === Code Lenses === // === /codeLensReferencesShowOnInterfaceMethods=true.ts === -// --- (line: 6) skipped --- +// --- (line: 7) skipped --- // // interface J extends I { // methodB(): void; @@ -144,13 +147,13 @@ // } // // class AbstractC implements J { -// --- (line: 20) skipped --- +// --- (line: 21) skipped --- // === Code Lenses === // === /codeLensReferencesShowOnInterfaceMethods=true.ts === -// --- (line: 16) skipped --- +// --- (line: 17) skipped --- // } // // class AbstractC implements J { @@ -164,7 +167,7 @@ // === Code Lenses === // === /codeLensReferencesShowOnInterfaceMethods=true.ts === -// --- (line: 18) skipped --- +// --- (line: 19) skipped --- // class AbstractC implements J { // abstract methodA(): void; // methodB(): void {} diff --git a/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesDeclare3.baseline.jsonc b/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesDeclare3.baseline.jsonc index 3fca7d26ca9..2593115d539 100644 --- a/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesDeclare3.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesDeclare3.baseline.jsonc @@ -1,13 +1,14 @@ // === documentHighlights === // === /getOccurrencesDeclare3.ts === +// // /*HIGHLIGHTS*/[|declare|] var x; // export [|declare|] var y, z; // // namespace m { // export class C1 { -// --- (line: 6) skipped --- +// --- (line: 7) skipped --- -// --- (line: 53) skipped --- +// --- (line: 54) skipped --- // declare function foo(): string; // } // @@ -19,14 +20,15 @@ // === documentHighlights === // === /getOccurrencesDeclare3.ts === +// // [|declare|] var x; // export /*HIGHLIGHTS*/[|declare|] var y, z; // // namespace m { // export class C1 { -// --- (line: 6) skipped --- +// --- (line: 7) skipped --- -// --- (line: 53) skipped --- +// --- (line: 54) skipped --- // declare function foo(): string; // } // @@ -38,14 +40,15 @@ // === documentHighlights === // === /getOccurrencesDeclare3.ts === +// // [|declare|] var x; // export [|declare|] var y, z; // // namespace m { // export class C1 { -// --- (line: 6) skipped --- +// --- (line: 7) skipped --- -// --- (line: 53) skipped --- +// --- (line: 54) skipped --- // declare function foo(): string; // } // @@ -57,14 +60,15 @@ // === documentHighlights === // === /getOccurrencesDeclare3.ts === +// // [|declare|] var x; // export [|declare|] var y, z; // // namespace m { // export class C1 { -// --- (line: 6) skipped --- +// --- (line: 7) skipped --- -// --- (line: 53) skipped --- +// --- (line: 54) skipped --- // declare function foo(): string; // } // diff --git a/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesExport3.baseline.jsonc b/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesExport3.baseline.jsonc index da17f630311..5e4b2219930 100644 --- a/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesExport3.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesExport3.baseline.jsonc @@ -1,13 +1,14 @@ // === documentHighlights === // === /getOccurrencesExport3.ts === +// // declare var x; // /*HIGHLIGHTS*/[|export|] declare var y, z; // // namespace m { // export class C1 { -// --- (line: 6) skipped --- +// --- (line: 7) skipped --- -// --- (line: 53) skipped --- +// --- (line: 54) skipped --- // declare function foo(): string; // } // @@ -19,14 +20,15 @@ // === documentHighlights === // === /getOccurrencesExport3.ts === +// // declare var x; // [|export|] declare var y, z; // // namespace m { // export class C1 { -// --- (line: 6) skipped --- +// --- (line: 7) skipped --- -// --- (line: 53) skipped --- +// --- (line: 54) skipped --- // declare function foo(): string; // } // @@ -38,14 +40,15 @@ // === documentHighlights === // === /getOccurrencesExport3.ts === +// // declare var x; // [|export|] declare var y, z; // // namespace m { // export class C1 { -// --- (line: 6) skipped --- +// --- (line: 7) skipped --- -// --- (line: 53) skipped --- +// --- (line: 54) skipped --- // declare function foo(): string; // } // diff --git a/testdata/baselines/reference/fourslash/documentSymbols/jsdocTypedefTagNavigateTo.baseline b/testdata/baselines/reference/fourslash/documentSymbols/jsdocTypedefTagNavigateTo.baseline index 9d9df97ac33..38eac7922d9 100644 --- a/testdata/baselines/reference/fourslash/documentSymbols/jsdocTypedefTagNavigateTo.baseline +++ b/testdata/baselines/reference/fourslash/documentSymbols/jsdocTypedefTagNavigateTo.baseline @@ -1,5 +1,6 @@ // === Document Symbols === // === /jsDocTypedef_form2.js === +// // /** <|@typedef {(string | number)} [|{| name: NumberLike, kind: Class |}NumberLike|]|> */ // /** @typedef {(string | number | string[])} */ // var <|[|{| name: NumberLike2, kind: Variable |}NumberLike2|]|>; diff --git a/testdata/baselines/reference/fourslash/goToDefinition/goToDefinitionObjectBindingPattern.baseline.jsonc b/testdata/baselines/reference/fourslash/goToDefinition/goToDefinitionObjectBindingPattern.baseline.jsonc index 8b8d90a1cfd..cb736abfebf 100644 --- a/testdata/baselines/reference/fourslash/goToDefinition/goToDefinitionObjectBindingPattern.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/goToDefinition/goToDefinitionObjectBindingPattern.baseline.jsonc @@ -1,5 +1,6 @@ // === goToDefinition === // === /goToDefinitionObjectBindingPattern.ts === +// // interface SomeType { // <|[|targetProperty|]: number;|> // } @@ -10,13 +11,13 @@ // targetProperty // }); // -// --- (line: 11) skipped --- +// --- (line: 12) skipped --- // === goToDefinition === // === /goToDefinitionObjectBindingPattern.ts === -// --- (line: 3) skipped --- +// --- (line: 4) skipped --- // // function foo(callback: (p: SomeType) => void) {} // @@ -25,12 +26,13 @@ // }); // // let { targetProperty }: SomeType = { targetProperty: 42 }; -// --- (line: 12) skipped --- +// --- (line: 13) skipped --- // === goToDefinition === // === /goToDefinitionObjectBindingPattern.ts === +// // interface SomeType { // <|[|targetProperty|]: number;|> // } @@ -51,6 +53,7 @@ // === goToDefinition === // === /goToDefinitionObjectBindingPattern.ts === +// // interface SomeType { // <|[|targetProperty|]: number;|> // } @@ -71,14 +74,15 @@ // === goToDefinition === // === /goToDefinitionObjectBindingPattern.ts === +// // interface SomeType { // <|[|targetProperty|]: number;|> // } // // function foo(callback: (p: SomeType) => void) {} -// --- (line: 6) skipped --- +// --- (line: 7) skipped --- -// --- (line: 9) skipped --- +// --- (line: 10) skipped --- // // let { targetProperty }: SomeType = { targetProperty: 42 }; // @@ -90,7 +94,7 @@ // === goToDefinition === // === /goToDefinitionObjectBindingPattern.ts === -// --- (line: 9) skipped --- +// --- (line: 10) skipped --- // // let { targetProperty }: SomeType = { targetProperty: 42 }; // @@ -102,14 +106,15 @@ // === goToDefinition === // === /goToDefinitionObjectBindingPattern.ts === +// // interface SomeType { // <|[|targetProperty|]: number;|> // } // // function foo(callback: (p: SomeType) => void) {} -// --- (line: 6) skipped --- +// --- (line: 7) skipped --- -// --- (line: 11) skipped --- +// --- (line: 12) skipped --- // // let { targetProperty: alias_1 }: SomeType = { targetProperty: 42 }; // @@ -119,7 +124,7 @@ // === goToDefinition === // === /goToDefinitionObjectBindingPattern.ts === -// --- (line: 11) skipped --- +// --- (line: 12) skipped --- // // let { targetProperty: alias_1 }: SomeType = { targetProperty: 42 }; // diff --git a/testdata/baselines/reference/fourslash/goToDefinition/goToDefinitionObjectBindingPatternRest.baseline.jsonc b/testdata/baselines/reference/fourslash/goToDefinition/goToDefinitionObjectBindingPatternRest.baseline.jsonc index 0fcedb0482e..248f5065960 100644 --- a/testdata/baselines/reference/fourslash/goToDefinition/goToDefinitionObjectBindingPatternRest.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/goToDefinition/goToDefinitionObjectBindingPatternRest.baseline.jsonc @@ -1,5 +1,6 @@ // === goToDefinition === // === /goToDefinitionObjectBindingPatternRest.ts === +// // interface SomeType { // targetProperty: number; // } diff --git a/testdata/baselines/reference/fourslash/goToType/goToTypeWithTupleTypes1.baseline.jsonc b/testdata/baselines/reference/fourslash/goToType/goToTypeWithTupleTypes1.baseline.jsonc index 38d09de2015..baf09943a37 100644 --- a/testdata/baselines/reference/fourslash/goToType/goToTypeWithTupleTypes1.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/goToType/goToTypeWithTupleTypes1.baseline.jsonc @@ -1,5 +1,6 @@ // === goToType === // === /goToTypeWithTupleTypes1.ts === +// // export let x/*GOTO TYPE*/: [number, number] = [1, 2]; // // type DoubleTupleTrouble = [T, T]; @@ -11,6 +12,7 @@ // === goToType === // === /goToTypeWithTupleTypes1.ts === +// // export let x: [number, number] = [1, 2]; // // type DoubleTupleTrouble = [T, T]; diff --git a/testdata/baselines/reference/fourslash/quickInfo/destructuredInterfaceJSDoc.baseline b/testdata/baselines/reference/fourslash/quickInfo/destructuredInterfaceJSDoc.baseline index 35cead43d29..4839ec34bea 100644 --- a/testdata/baselines/reference/fourslash/quickInfo/destructuredInterfaceJSDoc.baseline +++ b/testdata/baselines/reference/fourslash/quickInfo/destructuredInterfaceJSDoc.baseline @@ -1,5 +1,6 @@ // === QuickInfo === === /destructuredInterfaceJSDoc.ts === +// // interface FooBar { // /** foo comment */ // foo: number; @@ -44,9 +45,9 @@ [ { "marker": { - "Position": 179, + "Position": 180, "LSPosition": { - "line": 11, + "line": 12, "character": 7 }, "Name": "1", @@ -59,11 +60,11 @@ }, "range": { "start": { - "line": 11, + "line": 12, "character": 7 }, "end": { - "line": 11, + "line": 12, "character": 10 } } @@ -71,9 +72,9 @@ }, { "marker": { - "Position": 184, + "Position": 185, "LSPosition": { - "line": 11, + "line": 12, "character": 12 }, "Name": "2", @@ -86,11 +87,11 @@ }, "range": { "start": { - "line": 11, + "line": 12, "character": 12 }, "end": { - "line": 11, + "line": 12, "character": 15 } } @@ -98,9 +99,9 @@ }, { "marker": { - "Position": 189, + "Position": 190, "LSPosition": { - "line": 11, + "line": 12, "character": 17 }, "Name": "3", @@ -113,11 +114,11 @@ }, "range": { "start": { - "line": 11, + "line": 12, "character": 17 }, "end": { - "line": 11, + "line": 12, "character": 20 } } @@ -125,9 +126,9 @@ }, { "marker": { - "Position": 194, + "Position": 195, "LSPosition": { - "line": 11, + "line": 12, "character": 22 }, "Name": "4", @@ -140,11 +141,11 @@ }, "range": { "start": { - "line": 11, + "line": 12, "character": 22 }, "end": { - "line": 11, + "line": 12, "character": 25 } } diff --git a/testdata/baselines/reference/fourslash/quickInfo/destructuredInterfaceJSDocWithRename.baseline b/testdata/baselines/reference/fourslash/quickInfo/destructuredInterfaceJSDocWithRename.baseline index 05decd03a89..2ddf9deffde 100644 --- a/testdata/baselines/reference/fourslash/quickInfo/destructuredInterfaceJSDocWithRename.baseline +++ b/testdata/baselines/reference/fourslash/quickInfo/destructuredInterfaceJSDocWithRename.baseline @@ -1,5 +1,6 @@ // === QuickInfo === === /destructuredInterfaceJSDocWithRename.ts === +// // interface FooBar { // /** foo comment */ // foo: number; @@ -28,9 +29,9 @@ [ { "marker": { - "Position": 144, + "Position": 145, "LSPosition": { - "line": 9, + "line": 10, "character": 12 }, "Name": "1", @@ -43,11 +44,11 @@ }, "range": { "start": { - "line": 9, + "line": 10, "character": 12 }, "end": { - "line": 9, + "line": 10, "character": 17 } } @@ -55,9 +56,9 @@ }, { "marker": { - "Position": 156, + "Position": 157, "LSPosition": { - "line": 9, + "line": 10, "character": 24 }, "Name": "2", @@ -70,11 +71,11 @@ }, "range": { "start": { - "line": 9, + "line": 10, "character": 24 }, "end": { - "line": 9, + "line": 10, "character": 29 } } diff --git a/testdata/baselines/reference/fourslash/quickInfo/destructuredWithOwnJSDoc.baseline b/testdata/baselines/reference/fourslash/quickInfo/destructuredWithOwnJSDoc.baseline index 5f66732246c..82dbbb65f31 100644 --- a/testdata/baselines/reference/fourslash/quickInfo/destructuredWithOwnJSDoc.baseline +++ b/testdata/baselines/reference/fourslash/quickInfo/destructuredWithOwnJSDoc.baseline @@ -1,5 +1,6 @@ // === QuickInfo === === /destructuredWithOwnJSDoc.ts === +// // interface Foo { // /** This is bar from the interface */ // bar: string; @@ -32,9 +33,9 @@ [ { "marker": { - "Position": 251, + "Position": 252, "LSPosition": { - "line": 11, + "line": 12, "character": 41 }, "Name": "1", @@ -47,11 +48,11 @@ }, "range": { "start": { - "line": 11, + "line": 12, "character": 41 }, "end": { - "line": 11, + "line": 12, "character": 44 } } @@ -59,9 +60,9 @@ }, { "marker": { - "Position": 297, + "Position": 298, "LSPosition": { - "line": 12, + "line": 13, "character": 41 }, "Name": "2", @@ -74,11 +75,11 @@ }, "range": { "start": { - "line": 12, + "line": 13, "character": 41 }, "end": { - "line": 12, + "line": 13, "character": 44 } } diff --git a/testdata/baselines/reference/fourslash/quickInfo/hoverNilBaseSymbolIntersection.baseline b/testdata/baselines/reference/fourslash/quickInfo/hoverNilBaseSymbolIntersection.baseline index 3d4098eb598..c5a492b82b6 100644 --- a/testdata/baselines/reference/fourslash/quickInfo/hoverNilBaseSymbolIntersection.baseline +++ b/testdata/baselines/reference/fourslash/quickInfo/hoverNilBaseSymbolIntersection.baseline @@ -1,5 +1,6 @@ // === QuickInfo === === /main.ts === +// // class Base {} // // declare const BaseFactory: new() => Base & { c: string }; @@ -18,9 +19,9 @@ [ { "marker": { - "Position": 119, + "Position": 120, "LSPosition": { - "line": 5, + "line": 6, "character": 9 }, "Name": "1", @@ -33,11 +34,11 @@ }, "range": { "start": { - "line": 5, + "line": 6, "character": 9 }, "end": { - "line": 5, + "line": 6, "character": 16 } } diff --git a/testdata/baselines/reference/fourslash/signatureHelp/signatureHelpBindingPattern.baseline b/testdata/baselines/reference/fourslash/signatureHelp/signatureHelpBindingPattern.baseline index 6ebf97f4191..c6339b43846 100644 --- a/testdata/baselines/reference/fourslash/signatureHelp/signatureHelpBindingPattern.baseline +++ b/testdata/baselines/reference/fourslash/signatureHelp/signatureHelpBindingPattern.baseline @@ -1,5 +1,6 @@ // === SignatureHelp === === /signatureHelpBindingPattern.ts === +// // /** // * @param options An empty object binding pattern. // */ @@ -160,9 +161,9 @@ [ { "marker": { - "Position": 93, + "Position": 94, "LSPosition": { - "line": 4, + "line": 5, "character": 9 }, "Name": "emptyObj", @@ -189,9 +190,9 @@ }, { "marker": { - "Position": 186, + "Position": 187, "LSPosition": { - "line": 10, + "line": 11, "character": 9 }, "Name": "emptyArr", @@ -218,9 +219,9 @@ }, { "marker": { - "Position": 316, + "Position": 317, "LSPosition": { - "line": 16, + "line": 17, "character": 12 }, "Name": "nonEmptyObj", @@ -247,9 +248,9 @@ }, { "marker": { - "Position": 432, + "Position": 433, "LSPosition": { - "line": 22, + "line": 23, "character": 12 }, "Name": "nonEmptyArr", @@ -276,9 +277,9 @@ }, { "marker": { - "Position": 621, + "Position": 622, "LSPosition": { - "line": 29, + "line": 30, "character": 13 }, "Name": "idLeading", @@ -312,9 +313,9 @@ }, { "marker": { - "Position": 637, + "Position": 638, "LSPosition": { - "line": 29, + "line": 30, "character": 29 }, "Name": "bindingTrailing", @@ -348,9 +349,9 @@ }, { "marker": { - "Position": 829, + "Position": 830, "LSPosition": { - "line": 36, + "line": 37, "character": 15 }, "Name": "bindingLeading", @@ -384,9 +385,9 @@ }, { "marker": { - "Position": 849, + "Position": 850, "LSPosition": { - "line": 36, + "line": 37, "character": 35 }, "Name": "idTrailing", @@ -420,9 +421,9 @@ }, { "marker": { - "Position": 1188, + "Position": 1189, "LSPosition": { - "line": 47, + "line": 48, "character": 32 }, "Name": "firstObjParam", @@ -456,9 +457,9 @@ }, { "marker": { - "Position": 1208, + "Position": 1209, "LSPosition": { - "line": 47, + "line": 48, "character": 52 }, "Name": "secondObjParam", diff --git a/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithProjectReferences.baseline b/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithProjectReferences.baseline index a49ff4483ec..f9e946ff48c 100644 --- a/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithProjectReferences.baseline +++ b/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithProjectReferences.baseline @@ -1,4 +1,7 @@ UseCaseSensitiveFileNames: true +//// [/declarationMapsRenameWithProjectReferences.ts] *new* + + //// [/myproject/dependency/FnS.ts] *new* export function fn1() { } export function fn2() { } diff --git a/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithProjectReferencesEdit.baseline b/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithProjectReferencesEdit.baseline index 2fb900dbb68..f8b7e872be7 100644 --- a/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithProjectReferencesEdit.baseline +++ b/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithProjectReferencesEdit.baseline @@ -1,4 +1,7 @@ UseCaseSensitiveFileNames: true +//// [/declarationMapsRenameWithProjectReferencesEdit.ts] *new* + + //// [/myproject/dependency/FnS.ts] *new* export function fn1() { } export function fn2() { } diff --git a/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithProjectReferencesEditEnd.baseline b/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithProjectReferencesEditEnd.baseline index 0bc2e3c1282..bbb73036893 100644 --- a/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithProjectReferencesEditEnd.baseline +++ b/testdata/baselines/reference/fourslash/state/declarationMapsRenameWithProjectReferencesEditEnd.baseline @@ -1,4 +1,7 @@ UseCaseSensitiveFileNames: true +//// [/declarationMapsRenameWithProjectReferencesEditEnd.ts] *new* + + //// [/myproject/dependency/FnS.ts] *new* export function fn1() { } export function fn2() { } diff --git a/testdata/baselines/reference/fourslash/state/findAllRefsRootOfReferencedProject.baseline b/testdata/baselines/reference/fourslash/state/findAllRefsRootOfReferencedProject.baseline index e09956e1dcc..bdd2814813e 100644 --- a/testdata/baselines/reference/fourslash/state/findAllRefsRootOfReferencedProject.baseline +++ b/testdata/baselines/reference/fourslash/state/findAllRefsRootOfReferencedProject.baseline @@ -1,4 +1,7 @@ UseCaseSensitiveFileNames: true +//// [/findAllRefsRootOfReferencedProject.ts] *new* + + //// [/src/common/input/keyboard.test.ts] *new* import { evaluateKeyboardEvent } from 'common/input/keyboard'; function testEvaluateKeyboardEvent() { diff --git a/testdata/baselines/reference/fourslash/syntaxandSemanticDiagnostics/privatePropertyOfUndefinedThis1.baseline b/testdata/baselines/reference/fourslash/syntaxandSemanticDiagnostics/privatePropertyOfUndefinedThis1.baseline index 96c87d9451f..58f91c79cfc 100644 --- a/testdata/baselines/reference/fourslash/syntaxandSemanticDiagnostics/privatePropertyOfUndefinedThis1.baseline +++ b/testdata/baselines/reference/fourslash/syntaxandSemanticDiagnostics/privatePropertyOfUndefinedThis1.baseline @@ -1,9 +1,10 @@ // === Syntax and Semantic Diagnostics === -/privatePropertyOfUndefinedThis1.ts(1,1): error TS2532: Object is possibly 'undefined'. -/privatePropertyOfUndefinedThis1.ts(1,6): error TS18016: Private identifiers are not allowed outside class bodies. +/privatePropertyOfUndefinedThis1.ts(2,1): error TS2532: Object is possibly 'undefined'. +/privatePropertyOfUndefinedThis1.ts(2,6): error TS18016: Private identifiers are not allowed outside class bodies. ==== /privatePropertyOfUndefinedThis1.ts (2 errors) ==== + this.#a = {}; ~~~~ !!! error TS2532: Object is possibly 'undefined'. diff --git a/testdata/baselines/reference/fourslash/syntaxandSemanticDiagnostics/privatePropertyOfUndefinedThis2.baseline b/testdata/baselines/reference/fourslash/syntaxandSemanticDiagnostics/privatePropertyOfUndefinedThis2.baseline index 412dcb47813..feb20890cec 100644 --- a/testdata/baselines/reference/fourslash/syntaxandSemanticDiagnostics/privatePropertyOfUndefinedThis2.baseline +++ b/testdata/baselines/reference/fourslash/syntaxandSemanticDiagnostics/privatePropertyOfUndefinedThis2.baseline @@ -1,9 +1,10 @@ // === Syntax and Semantic Diagnostics === -/privatePropertyOfUndefinedThis2.ts(3,9): error TS2322: Type '{}' is not assignable to type 'boolean'. -/privatePropertyOfUndefinedThis2.ts(3,21): error TS2339: Property '#prop' does not exist on type 'any'. +/privatePropertyOfUndefinedThis2.ts(4,9): error TS2322: Type '{}' is not assignable to type 'boolean'. +/privatePropertyOfUndefinedThis2.ts(4,21): error TS2339: Property '#prop' does not exist on type 'any'. ==== /privatePropertyOfUndefinedThis2.ts (2 errors) ==== + export class C { wat(this: any): boolean { return this.#prop = {}; diff --git a/testdata/baselines/reference/fourslash/syntaxandSemanticDiagnostics/typeErrorAfterStringCompletionsInNestedCall2.baseline b/testdata/baselines/reference/fourslash/syntaxandSemanticDiagnostics/typeErrorAfterStringCompletionsInNestedCall2.baseline index 3a2bd6eedde..4eb7e03a17f 100644 --- a/testdata/baselines/reference/fourslash/syntaxandSemanticDiagnostics/typeErrorAfterStringCompletionsInNestedCall2.baseline +++ b/testdata/baselines/reference/fourslash/syntaxandSemanticDiagnostics/typeErrorAfterStringCompletionsInNestedCall2.baseline @@ -1,5 +1,5 @@ // === Syntax and Semantic Diagnostics === -/typeErrorAfterStringCompletionsInNestedCall2.ts(40,5): error TS2322: Type '{ ({ event }: { event: { type: "FOO"; }; }): void; _out_TEvent?: { type: "BARx"; } | undefined; }' is not assignable to type 'ActionFunction<{ type: "FOO"; }, { type: "FOO"; } | { type: "BAR"; }>'. +/typeErrorAfterStringCompletionsInNestedCall2.ts(41,5): error TS2322: Type '{ ({ event }: { event: { type: "FOO"; }; }): void; _out_TEvent?: { type: "BARx"; } | undefined; }' is not assignable to type 'ActionFunction<{ type: "FOO"; }, { type: "FOO"; } | { type: "BAR"; }>'. Types of property '_out_TEvent' are incompatible. Type '{ type: "BARx"; } | undefined' is not assignable to type '{ type: "FOO"; } | { type: "BAR"; } | undefined'. Type '{ type: "BARx"; }' is not assignable to type '{ type: "FOO"; } | { type: "BAR"; } | undefined'. @@ -10,6 +10,7 @@ ==== /typeErrorAfterStringCompletionsInNestedCall2.ts (1 errors) ==== + type ActionFunction< TExpressionEvent extends { type: string }, out TEvent extends { type: string } @@ -59,7 +60,7 @@ !!! error TS2322: Type '{ type: "BARx"; }' is not assignable to type '{ type: "BAR"; }'. !!! error TS2322: Types of property 'type' are incompatible. !!! error TS2322: Type '"BARx"' is not assignable to type '"BAR"'. -!!! related TS2322 /typeErrorAfterStringCompletionsInNestedCall2.ts:13:7: The expected type comes from property 'FOO' which is declared here on type '{ BAR?: ActionFunction<{ type: "BAR"; }, { type: "FOO"; } | { type: "BAR"; }> | undefined; FOO?: ActionFunction<{ type: "FOO"; }, { type: "FOO"; } | { type: "BAR"; }> | undefined; }' +!!! related TS2322 /typeErrorAfterStringCompletionsInNestedCall2.ts:14:7: The expected type comes from property 'FOO' which is declared here on type '{ BAR?: ActionFunction<{ type: "BAR"; }, { type: "FOO"; } | { type: "BAR"; }> | undefined; FOO?: ActionFunction<{ type: "FOO"; }, { type: "FOO"; } | { type: "BAR"; }> | undefined; }' return { type: "BARx" as const, }; diff --git a/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocCallbackTagRename01.baseline.jsonc b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocCallbackTagRename01.baseline.jsonc index 596dc32276f..7580c8686b7 100644 --- a/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocCallbackTagRename01.baseline.jsonc +++ b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocCallbackTagRename01.baseline.jsonc @@ -1,5 +1,6 @@ // === findRenameLocations === // === /jsDocCallback.js === +// // /** // * @callback /*RENAME*/[|FooCallbackRENAME|] // * @param {string} eventName - Rename should work diff --git a/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocCallbackTagRename01.baseline.jsonc.diff b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocCallbackTagRename01.baseline.jsonc.diff index 4bc0773b3e0..fc73739d2d0 100644 --- a/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocCallbackTagRename01.baseline.jsonc.diff +++ b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocCallbackTagRename01.baseline.jsonc.diff @@ -4,7 +4,5 @@ // === findRenameLocations === - // === /jsDocCallback.js === --// - // /** - // * @callback /*RENAME*/[|FooCallbackRENAME|] - // * @param {string} eventName - Rename should work \ No newline at end of file + // + // /** \ No newline at end of file diff --git a/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename01.baseline.jsonc b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename01.baseline.jsonc index 055844e8b8c..939da78be55 100644 --- a/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename01.baseline.jsonc +++ b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename01.baseline.jsonc @@ -1,5 +1,6 @@ // === findRenameLocations === // === /jsDocTypedef_form1.js === +// // /** @typedef {(string | number)} */ // var /*RENAME*/[|NumberLikeRENAME|]; // @@ -12,6 +13,7 @@ // === findRenameLocations === // === /jsDocTypedef_form1.js === +// // /** @typedef {(string | number)} */ // var [|NumberLikeRENAME|]; // @@ -24,8 +26,7 @@ // === findRenameLocations === // === /jsDocTypedef_form1.js === -// /** @typedef {(string | number)} */ -// var NumberLike; +// --- (line: 3) skipped --- // // NumberLike = 10; // diff --git a/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename01.baseline.jsonc.diff b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename01.baseline.jsonc.diff index 11c6c9ccac6..519aa18cd47 100644 --- a/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename01.baseline.jsonc.diff +++ b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename01.baseline.jsonc.diff @@ -4,9 +4,9 @@ // === findRenameLocations === - // === /jsDocTypedef_form1.js === --// + // // /** @typedef {(string | number)} */ - // var /*RENAME*/[|NumberLikeRENAME|]; +@@= skipped -6, +5 lines =@@ // // [|NumberLikeRENAME|] = 10; // @@ -19,9 +19,9 @@ // === findRenameLocations === - // === /jsDocTypedef_form1.js === --// + // // /** @typedef {(string | number)} */ - // var [|NumberLikeRENAME|]; +@@= skipped -14, +13 lines =@@ // // /*RENAME*/[|NumberLikeRENAME|] = 10; // @@ -35,13 +35,13 @@ - // === /jsDocTypedef_form1.js === -// - // /** @typedef {(string | number)} */ +-// /** @typedef {(string | number)} */ -// var [|NumberLikeRENAME|]; -// -// [|NumberLikeRENAME|] = 10; -// -// /** @type {/*RENAME*/[|NumberLikeRENAME|]} */ -+// var NumberLike; ++// --- (line: 3) skipped --- +// +// NumberLike = 10; +// diff --git a/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename02.baseline.jsonc b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename02.baseline.jsonc index ba445832100..2493ea3358d 100644 --- a/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename02.baseline.jsonc +++ b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename02.baseline.jsonc @@ -1,5 +1,6 @@ // === findRenameLocations === // === /jsDocTypedef_form2.js === +// // /** @typedef {(string | number)} /*RENAME*/[|NumberLikeRENAME|] */ // // /** @type {[|NumberLikeRENAME|]} */ @@ -9,6 +10,7 @@ // === findRenameLocations === // === /jsDocTypedef_form2.js === +// // /** @typedef {(string | number)} [|NumberLikeRENAME|] */ // // /** @type {/*RENAME*/[|NumberLikeRENAME|]} */ diff --git a/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename02.baseline.jsonc.diff b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename02.baseline.jsonc.diff index 7a8d1070cf4..ef9675b3d60 100644 --- a/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename02.baseline.jsonc.diff +++ b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename02.baseline.jsonc.diff @@ -4,17 +4,13 @@ // === findRenameLocations === - // === /jsDocTypedef_form2.js === --// - // /** @typedef {(string | number)} /*RENAME*/[|NumberLikeRENAME|] */ // - // /** @type {[|NumberLikeRENAME|]} */ -@@= skipped -9, +7 lines =@@ + // /** @typedef {(string | number)} /*RENAME*/[|NumberLikeRENAME|] */ +@@= skipped -9, +8 lines =@@ // === findRenameLocations === - // === /jsDocTypedef_form2.js === --// - // /** @typedef {(string | number)} [|NumberLikeRENAME|] */ // - // /** @type {/*RENAME*/[|NumberLikeRENAME|]} */ \ No newline at end of file + // /** @typedef {(string | number)} [|NumberLikeRENAME|] */ \ No newline at end of file diff --git a/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename03.baseline.jsonc b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename03.baseline.jsonc index 7b7c4fd6184..54c91956f24 100644 --- a/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename03.baseline.jsonc +++ b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename03.baseline.jsonc @@ -1,5 +1,6 @@ // === findRenameLocations === // === /jsDocTypedef_form3.js === +// // /** // * @typedef /*RENAME*/[|PersonRENAME|] // * @type {Object} @@ -14,6 +15,7 @@ // === findRenameLocations === // === /jsDocTypedef_form3.js === +// // /** // * @typedef [|PersonRENAME|] // * @type {Object} diff --git a/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename03.baseline.jsonc.diff b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename03.baseline.jsonc.diff index 6ff5604625d..9040663c6e5 100644 --- a/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename03.baseline.jsonc.diff +++ b/testdata/baselines/reference/submodule/fourslash/findRenameLocations/jsdocTypedefTagRename03.baseline.jsonc.diff @@ -4,17 +4,13 @@ // === findRenameLocations === - // === /jsDocTypedef_form3.js === --// + // // /** - // * @typedef /*RENAME*/[|PersonRENAME|] - // * @type {Object} -@@= skipped -14, +12 lines =@@ +@@= skipped -14, +13 lines =@@ // === findRenameLocations === - // === /jsDocTypedef_form3.js === --// - // /** - // * @typedef [|PersonRENAME|] - // * @type {Object} \ No newline at end of file + // + // /** \ No newline at end of file From a17026d330a7e524cd91d31478ac6ab27d7be5ad Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Fri, 27 Mar 2026 10:07:35 -0700 Subject: [PATCH 2/3] Fix the escapedIdentifiers thing --- internal/printer/emitcontext.go | 1 + internal/transformers/tstransforms/runtimesyntax.go | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/printer/emitcontext.go b/internal/printer/emitcontext.go index f07cd13887a..ca5d3959127 100644 --- a/internal/printer/emitcontext.go +++ b/internal/printer/emitcontext.go @@ -77,6 +77,7 @@ func (c *EmitContext) onUpdate(updated *ast.Node, original *ast.Node) { } func (c *EmitContext) onClone(updated *ast.Node, original *ast.Node) { + c.SetOriginal(updated, original) if ast.IsIdentifier(updated) || ast.IsPrivateIdentifier(updated) { if autoGenerate := c.autoGenerate[original]; autoGenerate != nil { autoGenerateCopy := *autoGenerate diff --git a/internal/transformers/tstransforms/runtimesyntax.go b/internal/transformers/tstransforms/runtimesyntax.go index 88a002df332..7f84c791612 100644 --- a/internal/transformers/tstransforms/runtimesyntax.go +++ b/internal/transformers/tstransforms/runtimesyntax.go @@ -784,11 +784,11 @@ func (tx *RuntimeSyntaxTransformer) visitConstructorBody(body *ast.Block, constr for _, parameter := range parameterProperties { if ast.IsIdentifier(parameter.Name()) { propertyName := parameter.Name().Clone(tx.Factory()) - propertyName.Parent = parameter.AsNode() //nolint:customlint // .Parent set to get node to printback using text from original file instead of processed text; TODO: this should be achievable via EmitFlags instead + propertyName.Parent = parameter.Name().Parent //nolint:customlint // .Parent set to get node to printback using text from original file instead of processed text; TODO: this should be achievable via EmitFlags instead tx.EmitContext().AddEmitFlags(propertyName, printer.EFNoComments|printer.EFNoSourceMap) localName := parameter.Name().Clone(tx.Factory()) - localName.Parent = parameter.AsNode() //nolint:customlint // .Parent set to get node to printback using text from original file instead of processed text; TODO: this should be achievable via EmitFlags instead + localName.Parent = parameter.Name().Parent //nolint:customlint // .Parent set to get node to printback using text from original file instead of processed text; TODO: this should be achievable via EmitFlags instead tx.EmitContext().AddEmitFlags(localName, printer.EFNoComments) parameterProperty := tx.Factory().NewExpressionStatement( From 7e0064f0aa0f6040f932d29fe68b1d579b915284 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Fri, 27 Mar 2026 10:10:24 -0700 Subject: [PATCH 3/3] Pull in local version of expando thing after change in main --- internal/ls/codeactions_fixmissingtypeannotation.go | 13 ++++++++++--- internal/printer/printer.go | 4 ++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/internal/ls/codeactions_fixmissingtypeannotation.go b/internal/ls/codeactions_fixmissingtypeannotation.go index 5e4b4d3e8e2..84fa8c88298 100644 --- a/internal/ls/codeactions_fixmissingtypeannotation.go +++ b/internal/ls/codeactions_fixmissingtypeannotation.go @@ -424,18 +424,25 @@ func (f *isolatedDeclarationsFixer) extractAsVariable(span core.TextRange) strin } // findExpandoFunction finds the function declaration that has expando properties assigned to it. +// isExpandoPropertyDeclarationForFix matches TS's isExpandoPropertyDeclaration which includes +// PropertyAccessExpression, ElementAccessExpression, and BinaryExpression. The shared +// ast.IsExpandoPropertyDeclaration was narrowed to BinaryExpression only for checker purposes. +func isExpandoPropertyDeclarationForFix(node *ast.Node) bool { + return node != nil && (ast.IsPropertyAccessExpression(node) || ast.IsElementAccessExpression(node) || ast.IsBinaryExpression(node)) +} + func findExpandoFunction(ch *checker.Checker, node *ast.Node) *ast.Node { expandoDeclaration := ast.FindAncestorOrQuit(node, func(n *ast.Node) ast.FindAncestorResult { if ast.IsStatement(n) { return ast.FindAncestorQuit } - if ast.IsExpandoPropertyDeclaration(n) { + if isExpandoPropertyDeclarationForFix(n) { return ast.FindAncestorTrue } return ast.FindAncestorFalse }) - if expandoDeclaration == nil || !ast.IsExpandoPropertyDeclaration(expandoDeclaration) { + if expandoDeclaration == nil || !isExpandoPropertyDeclarationForFix(expandoDeclaration) { return nil } @@ -443,7 +450,7 @@ func findExpandoFunction(ch *checker.Checker, node *ast.Node) *ast.Node { // Some late bound expando members use the whole expression as the declaration. if ast.IsBinaryExpression(assignmentTarget) { assignmentTarget = assignmentTarget.AsBinaryExpression().Left - if !ast.IsExpandoPropertyDeclaration(assignmentTarget) { + if !isExpandoPropertyDeclarationForFix(assignmentTarget) { return nil } } diff --git a/internal/printer/printer.go b/internal/printer/printer.go index 5878360f9d4..08b68772aca 100644 --- a/internal/printer/printer.go +++ b/internal/printer/printer.go @@ -1201,6 +1201,10 @@ func (p *Printer) emitEntityName(node *ast.EntityName) { p.emitIdentifierReference(node.AsIdentifier()) case ast.KindQualifiedName: p.emitQualifiedName(node.AsQualifiedName()) + case ast.KindPropertyAccessExpression: + // TypeQuery nodes may have PropertyAccessExpression as exprName (e.g. typeof foo.x). + // TS's emitter handles this via generic emit(); we dispatch to expression emitter here. + p.emitExpression(node, ast.OperatorPrecedenceDisallowComma) default: panic(fmt.Sprintf("unexpected EntityName: %v", node.Kind)) }