diff --git a/src/harness/fourslashImpl.ts b/src/harness/fourslashImpl.ts index ea6ccd68fbc..bb7da149f79 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 14356ecc479..a74785b8271 100644 --- a/src/harness/fourslashInterfaceImpl.ts +++ b/src/harness/fourslashInterfaceImpl.ts @@ -1480,6 +1480,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 7f4399842a4..94bc3085e92 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -2121,6 +2121,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 db1b1ba5510..2d2ee7c328b 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 d1e1629a4b8..44f73626a8f 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 89cc8429f05..e13717cbbaf 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -5666,6 +5666,7 @@ declare namespace ts { hasAction?: true; source?: string; isRecommended?: true; + isFromUncheckedFile?: true; } interface CompletionEntryDetails { name: string; @@ -7673,6 +7674,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 86978589be6..01fcff4eaec 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -5666,6 +5666,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 00000000000..dcc3d95ed20 --- /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 6e76b6fc0a9..f7c2932511a 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -611,6 +611,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;