diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index 972c191f189f0..21882541ddfdd 100644 --- a/src/harness/fourslashImpl.ts +++ b/src/harness/fourslashImpl.ts @@ -843,8 +843,8 @@ namespace FourSlash { } private verifyCompletionEntry(actual: ts.CompletionEntry, expected: FourSlashInterface.ExpectedCompletionEntry) { - const { insertText, replacementSpan, hasAction, isRecommended, kind, kindModifiers, text, documentation, tags, source, sourceDisplay, sortText } = typeof expected === "string" - ? { insertText: undefined, replacementSpan: undefined, hasAction: undefined, isRecommended: undefined, kind: undefined, kindModifiers: undefined, text: undefined, documentation: undefined, tags: undefined, source: undefined, sourceDisplay: undefined, sortText: undefined } + const { insertText, replacementSpan, hasAction, isRecommended, isFromUncheckedFile, kind, kindModifiers, text, documentation, tags, source, sourceDisplay, sortText } = typeof expected === "string" + ? { insertText: undefined, replacementSpan: undefined, hasAction: undefined, isRecommended: undefined, isFromUncheckedFile: undefined, kind: undefined, kindModifiers: undefined, text: undefined, documentation: undefined, tags: undefined, source: undefined, sourceDisplay: undefined, sortText: undefined } : expected; if (actual.insertText !== insertText) { @@ -867,8 +867,14 @@ namespace FourSlash { } } + if (isFromUncheckedFile !== undefined) { + if (actual.isFromUncheckedFile !== isFromUncheckedFile) { + this.raiseError(`Expected 'isFromUncheckedFile' value '${actual.isFromUncheckedFile}' to equal '${isFromUncheckedFile}'`); + } + } + assert.equal(actual.hasAction, hasAction, `Expected 'hasAction' value '${actual.hasAction}' to equal '${hasAction}'`); - assert.equal(actual.isRecommended, isRecommended, `Expected 'isRecommended' value '${actual.source}' to equal '${isRecommended}'`); + assert.equal(actual.isRecommended, isRecommended, `Expected 'isRecommended' value '${actual.isRecommended}' to equal '${isRecommended}'`); assert.equal(actual.source, source, `Expected 'source' value '${actual.source}' to equal '${source}'`); assert.equal(actual.sortText, sortText || ts.Completions.SortText.LocationPriority, this.messageAtLastKnownMarker(`Actual entry: ${JSON.stringify(actual)}`)); diff --git a/src/harness/fourslashInterfaceImpl.ts b/src/harness/fourslashInterfaceImpl.ts index 91ddf5b6293dd..79aac2047f3a8 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -1472,6 +1472,7 @@ namespace FourSlashInterface { readonly replacementSpan?: FourSlash.Range; readonly hasAction?: boolean; // If not specified, will assert that this is false. readonly isRecommended?: boolean; // If not specified, will assert that this is false. + readonly isFromUncheckedFile?: boolean; // If not specified, won't assert about this readonly kind?: string; // If not specified, won't assert about this readonly kindModifiers?: string; // Must be paired with 'kind' readonly text?: string; diff --git a/src/server/protocol.ts b/src/server/protocol.ts index cabe7dcd55dd1..9f34da8651dd9 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -2086,6 +2086,11 @@ namespace ts.server.protocol { * Then either that enum/class or a namespace containing it will be the recommended symbol. */ isRecommended?: true; + /** + * If true, this completion was generated from traversing the name table of an unchecked JS file, + * and therefore may not be accurate. + */ + isFromUncheckedFile?: true; } /** diff --git a/src/services/completions.ts b/src/services/completions.ts index 471d8e4c142c6..e99170009edb8 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -310,7 +310,8 @@ namespace ts.Completions { name: realName, kind: ScriptElementKind.warning, kindModifiers: "", - sortText: SortText.JavascriptIdentifiers + sortText: SortText.JavascriptIdentifiers, + isFromUncheckedFile: true }); } }); diff --git a/src/services/types.ts b/src/services/types.ts index 3a1627c247fe2..89c8c188ce110 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -988,6 +988,7 @@ namespace ts { hasAction?: true; source?: string; isRecommended?: true; + isFromUncheckedFile?: true; } export interface CompletionEntryDetails { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 5ca50db806704..ec3ab95475173 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -5652,6 +5652,7 @@ declare namespace ts { hasAction?: true; source?: string; isRecommended?: true; + isFromUncheckedFile?: true; } interface CompletionEntryDetails { name: string; @@ -7644,6 +7645,11 @@ declare namespace ts.server.protocol { * Then either that enum/class or a namespace containing it will be the recommended symbol. */ isRecommended?: true; + /** + * If true, this completion was generated from traversing the name table of an unchecked JS file, + * and therefore may not be accurate. + */ + isFromUncheckedFile?: true; } /** * Additional completion entry details, available on demand diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 1143d4c6ebceb..b0f592c95ef9d 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -5652,6 +5652,7 @@ declare namespace ts { hasAction?: true; source?: string; isRecommended?: true; + isFromUncheckedFile?: true; } interface CompletionEntryDetails { name: string; diff --git a/tests/cases/fourslash/completionInUncheckedJSFile.ts b/tests/cases/fourslash/completionInUncheckedJSFile.ts new file mode 100644 index 0000000000000..dcc3d95ed204d --- /dev/null +++ b/tests/cases/fourslash/completionInUncheckedJSFile.ts @@ -0,0 +1,28 @@ +/// + +// @allowJs: true +// @checkJs: false +// @Filename: index.js +////function hello() { +//// +////} +//// +////const goodbye = 5; +//// +////console./*0*/ + +verify.completions({ + marker: "0", + includes: [ + { + name: "hello", + sortText: completion.SortText.JavascriptIdentifiers, + isFromUncheckedFile: true + }, + { + name: "goodbye", + sortText: completion.SortText.JavascriptIdentifiers, + isFromUncheckedFile: true + } + ] +}); \ No newline at end of file diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 84b770fc394c1..cc5720ca9d6e8 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -609,6 +609,7 @@ declare namespace FourSlashInterface { readonly replacementSpan?: Range; readonly hasAction?: boolean; readonly isRecommended?: boolean; + readonly isFromUncheckedFile?: boolean; readonly kind?: string; readonly kindModifiers?: string; readonly sortText?: completion.SortText;