diff --git a/Jakefile.js b/Jakefile.js index 2df29911125..2b0f0fe1f42 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -330,7 +330,7 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, opts options += " --lib " + opts.lib } else { - options += " --lib es5,scripthost" + options += " --lib es5" } options += " --noUnusedLocals --noUnusedParameters"; @@ -584,13 +584,13 @@ var cancellationTokenFile = path.join(builtLocalDirectory, "cancellationToken.js compileFile(cancellationTokenFile, cancellationTokenSources, [builtLocalDirectory].concat(cancellationTokenSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], outDir: builtLocalDirectory, noOutFile: true, lib: "es6" }); var typingsInstallerFile = path.join(builtLocalDirectory, "typingsInstaller.js"); -compileFile(typingsInstallerFile, typingsInstallerSources, [builtLocalDirectory].concat(typingsInstallerSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], outDir: builtLocalDirectory, noOutFile: false, lib: "es6,scripthost" }); +compileFile(typingsInstallerFile, typingsInstallerSources, [builtLocalDirectory].concat(typingsInstallerSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], outDir: builtLocalDirectory, noOutFile: false, lib: "es6" }); var watchGuardFile = path.join(builtLocalDirectory, "watchGuard.js"); compileFile(watchGuardFile, watchGuardSources, [builtLocalDirectory].concat(watchGuardSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], outDir: builtLocalDirectory, noOutFile: false, lib: "es6" }); var serverFile = path.join(builtLocalDirectory, "tsserver.js"); -compileFile(serverFile, serverSources, [builtLocalDirectory, copyright, cancellationTokenFile, typingsInstallerFile, watchGuardFile].concat(serverSources).concat(servicesSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], preserveConstEnums: true, lib: "es6,scripthost" }); +compileFile(serverFile, serverSources, [builtLocalDirectory, copyright, cancellationTokenFile, typingsInstallerFile, watchGuardFile].concat(serverSources).concat(servicesSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], preserveConstEnums: true, lib: "es6" }); var tsserverLibraryFile = path.join(builtLocalDirectory, "tsserverlibrary.js"); var tsserverLibraryDefinitionFile = path.join(builtLocalDirectory, "tsserverlibrary.d.ts"); compileFile( @@ -714,7 +714,7 @@ compileFile( /*prereqs*/[builtLocalDirectory, tscFile].concat(libraryTargets).concat(servicesSources).concat(harnessSources), /*prefixes*/[], /*useBuiltCompiler:*/ true, - /*opts*/ { inlineSourceMap: true, types: ["node", "mocha", "chai"], lib: "es6,scripthost" }); + /*opts*/ { inlineSourceMap: true, types: ["node", "mocha", "chai"], lib: "es6" }); var internalTests = "internal/"; diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 318f06ceeaa..919158645a4 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2413,10 +2413,6 @@ "category": "Error", "code": 5012 }, - "Unsupported file encoding.": { - "category": "Error", - "code": 5013 - }, "Failed to parse file '{0}': {1}.": { "category": "Error", "code": 5014 diff --git a/src/compiler/program.ts b/src/compiler/program.ts index abb8b0b2f09..e117761a3a3 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -87,9 +87,6 @@ namespace ts { return sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); } - // returned by CScript sys environment - const unsupportedFileEncodingErrorCode = -2147024809; - function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile { let text: string; try { @@ -100,9 +97,7 @@ namespace ts { } catch (e) { if (onError) { - onError(e.number === unsupportedFileEncodingErrorCode - ? createCompilerDiagnostic(Diagnostics.Unsupported_file_encoding).messageText - : e.message); + onError(e.message); } text = ""; } diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 2a15df80102..3f585900654 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -74,13 +74,6 @@ namespace ts { return parseInt(version.substring(1, dot)); } - declare class Enumerator { - public atEnd(): boolean; - public moveNext(): boolean; - public item(): any; - constructor(o: any); - } - declare var ChakraHost: { args: string[]; currentDirectory: string; @@ -104,152 +97,6 @@ namespace ts { }; export let sys: System = (function() { - - function getWScriptSystem(): System { - - const fso = new ActiveXObject("Scripting.FileSystemObject"); - const shell = new ActiveXObject("WScript.Shell"); - - const fileStream = new ActiveXObject("ADODB.Stream"); - fileStream.Type = 2 /*text*/; - - const binaryStream = new ActiveXObject("ADODB.Stream"); - binaryStream.Type = 1 /*binary*/; - - const args: string[] = []; - for (let i = 0; i < WScript.Arguments.length; i++) { - args[i] = WScript.Arguments.Item(i); - } - - function readFile(fileName: string, encoding?: string): string { - if (!fso.FileExists(fileName)) { - return undefined; - } - fileStream.Open(); - try { - if (encoding) { - fileStream.Charset = encoding; - fileStream.LoadFromFile(fileName); - } - else { - // Load file and read the first two bytes into a string with no interpretation - fileStream.Charset = "x-ansi"; - fileStream.LoadFromFile(fileName); - const bom = fileStream.ReadText(2) || ""; - // Position must be at 0 before encoding can be changed - fileStream.Position = 0; - // [0xFF,0xFE] and [0xFE,0xFF] mean utf-16 (little or big endian), otherwise default to utf-8 - fileStream.Charset = bom.length >= 2 && (bom.charCodeAt(0) === 0xFF && bom.charCodeAt(1) === 0xFE || bom.charCodeAt(0) === 0xFE && bom.charCodeAt(1) === 0xFF) ? "unicode" : "utf-8"; - } - // ReadText method always strips byte order mark from resulting string - return fileStream.ReadText(); - } - catch (e) { - throw e; - } - finally { - fileStream.Close(); - } - } - - function writeFile(fileName: string, data: string, writeByteOrderMark?: boolean): void { - fileStream.Open(); - binaryStream.Open(); - try { - // Write characters in UTF-8 encoding - fileStream.Charset = "utf-8"; - fileStream.WriteText(data); - // If we don't want the BOM, then skip it by setting the starting location to 3 (size of BOM). - // If not, start from position 0, as the BOM will be added automatically when charset==utf8. - if (writeByteOrderMark) { - fileStream.Position = 0; - } - else { - fileStream.Position = 3; - } - fileStream.CopyTo(binaryStream); - binaryStream.SaveToFile(fileName, 2 /*overwrite*/); - } - finally { - binaryStream.Close(); - fileStream.Close(); - } - } - - function getNames(collection: any): string[] { - const result: string[] = []; - for (const e = new Enumerator(collection); !e.atEnd(); e.moveNext()) { - result.push(e.item().Name); - } - return result.sort(); - } - - function getDirectories(path: string): string[] { - const folder = fso.GetFolder(path); - return getNames(folder.subfolders); - } - - function getAccessibleFileSystemEntries(path: string): FileSystemEntries { - try { - const folder = fso.GetFolder(path || "."); - const files = getNames(folder.files); - const directories = getNames(folder.subfolders); - return { files, directories }; - } - catch (e) { - return { files: [], directories: [] }; - } - } - - function readDirectory(path: string, extensions?: string[], excludes?: string[], includes?: string[]): string[] { - return matchFiles(path, extensions, excludes, includes, /*useCaseSensitiveFileNames*/ false, shell.CurrentDirectory, getAccessibleFileSystemEntries); - } - - const wscriptSystem: System = { - args, - newLine: "\r\n", - useCaseSensitiveFileNames: false, - write(s: string): void { - WScript.StdOut.Write(s); - }, - readFile, - writeFile, - resolvePath(path: string): string { - return fso.GetAbsolutePathName(path); - }, - fileExists(path: string): boolean { - return fso.FileExists(path); - }, - directoryExists(path: string) { - return fso.FolderExists(path); - }, - createDirectory(directoryName: string) { - if (!wscriptSystem.directoryExists(directoryName)) { - fso.CreateFolder(directoryName); - } - }, - getExecutingFilePath() { - return WScript.ScriptFullName; - }, - getCurrentDirectory() { - return shell.CurrentDirectory; - }, - getDirectories, - getEnvironmentVariable(name: string) { - return new ActiveXObject("WScript.Shell").ExpandEnvironmentStrings(`%${name}%`); - }, - readDirectory, - exit(exitCode?: number): void { - try { - WScript.Quit(exitCode); - } - catch (e) { - } - } - }; - return wscriptSystem; - } - function getNodeSystem(): System { const _fs = require("fs"); const _path = require("path"); @@ -646,9 +493,6 @@ namespace ts { if (typeof ChakraHost !== "undefined") { sys = getChakraSystem(); } - else if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") { - sys = getWScriptSystem(); - } else if (typeof process !== "undefined" && process.nextTick && !process.browser && typeof require !== "undefined") { // process and process.nextTick checks if current environment is node-like // process.browser check excludes webpack and browserify diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 08370480aa4..0863b8e2d48 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -928,9 +928,13 @@ namespace FourSlash { } function rangeToReferenceEntry(r: Range) { - let { isWriteAccess, isDefinition } = (r.marker && r.marker.data) || { isWriteAccess: false, isDefinition: false }; + let { isWriteAccess, isDefinition, isInString } = (r.marker && r.marker.data) || { isWriteAccess: false, isDefinition: false, isInString: undefined }; isWriteAccess = !!isWriteAccess; isDefinition = !!isDefinition; - return { fileName: r.fileName, textSpan: { start: r.start, length: r.end - r.start }, isWriteAccess, isDefinition }; + const result: any = { fileName: r.fileName, textSpan: { start: r.start, length: r.end - r.start }, isWriteAccess, isDefinition }; + if (isInString !== undefined) { + result.isInString = isInString; + } + return result; } } @@ -1855,17 +1859,41 @@ namespace FourSlash { const unsatisfiedRanges: Range[] = []; + const delayedErrors: string[] = []; for (const range of ranges) { const length = range.end - range.start; const matchingImpl = ts.find(implementations, impl => range.fileName === impl.fileName && range.start === impl.textSpan.start && length === impl.textSpan.length); if (matchingImpl) { + if (range.marker && range.marker.data) { + const expected = <{ displayParts?: ts.SymbolDisplayPart[], parts: string[], kind?: string }>range.marker.data; + if (expected.displayParts) { + if (!ts.arrayIsEqualTo(expected.displayParts, matchingImpl.displayParts, displayPartIsEqualTo)) { + delayedErrors.push(`Mismatched display parts: expected ${JSON.stringify(expected.displayParts)}, actual ${JSON.stringify(matchingImpl.displayParts)}`); + } + } + else if (expected.parts) { + const actualParts = matchingImpl.displayParts.map(p => p.text); + if (!ts.arrayIsEqualTo(expected.parts, actualParts)) { + delayedErrors.push(`Mismatched non-tagged display parts: expected ${JSON.stringify(expected.parts)}, actual ${JSON.stringify(actualParts)}`); + } + } + if (expected.kind !== undefined) { + if (expected.kind !== matchingImpl.kind) { + delayedErrors.push(`Mismatched kind: expected ${JSON.stringify(expected.kind)}, actual ${JSON.stringify(matchingImpl.kind)}`); + } + } + } + matchingImpl.matched = true; } else { unsatisfiedRanges.push(range); } } + if (delayedErrors.length) { + this.raiseError(delayedErrors.join("\n")); + } const unmatchedImplementations = implementations.filter(impl => !impl.matched); if (unmatchedImplementations.length || unsatisfiedRanges.length) { @@ -1890,6 +1918,10 @@ namespace FourSlash { function implementationsAreEqual(a: ImplementationLocationInformation, b: ImplementationLocationInformation) { return a.fileName === b.fileName && TestState.textSpansEqual(a.textSpan, b.textSpan); } + + function displayPartIsEqualTo(a: ts.SymbolDisplayPart, b: ts.SymbolDisplayPart): boolean { + return a.kind === b.kind && a.text === b.text; + } } public getMarkers(): Marker[] { diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 23e8106864a..29eec356148 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -34,12 +34,6 @@ var _chai: typeof chai = require("chai"); var assert: typeof _chai.assert = _chai.assert; declare var __dirname: string; // Node-specific var global: NodeJS.Global = Function("return this").call(undefined); -declare namespace NodeJS { - export interface Global { - WScript: typeof WScript; - ActiveXObject: typeof ActiveXObject; - } -} declare var window: {}; declare var XMLHttpRequest: { @@ -60,14 +54,10 @@ namespace Utils { export const enum ExecutionEnvironment { Node, Browser, - CScript } export function getExecutionEnvironment() { - if (typeof WScript !== "undefined" && typeof ActiveXObject === "function") { - return ExecutionEnvironment.CScript; - } - else if (typeof window !== "undefined") { + if (typeof window !== "undefined") { return ExecutionEnvironment.Browser; } else { @@ -93,7 +83,6 @@ namespace Utils { export function evalFile(fileContents: string, fileName: string, nodeContext?: any) { const environment = getExecutionEnvironment(); switch (environment) { - case ExecutionEnvironment.CScript: case ExecutionEnvironment.Browser: eval(fileContents); break; @@ -516,83 +505,6 @@ namespace Harness { export const virtualFileSystemRoot = "/"; namespace IOImpl { - declare class Enumerator { - public atEnd(): boolean; - public moveNext(): boolean; - public item(): any; - constructor(o: any); - } - - export namespace CScript { - let fso: any; - if (global.ActiveXObject) { - fso = new global.ActiveXObject("Scripting.FileSystemObject"); - } - else { - fso = {}; - } - - export const args = () => ts.sys.args; - export const getExecutingFilePath = () => ts.sys.getExecutingFilePath(); - export const exit = (exitCode: number) => ts.sys.exit(exitCode); - export const resolvePath = (path: string) => ts.sys.resolvePath(path); - export const getCurrentDirectory = () => ts.sys.getCurrentDirectory(); - export const newLine = () => harnessNewLine; - export const useCaseSensitiveFileNames = () => ts.sys.useCaseSensitiveFileNames; - - export const readFile: typeof IO.readFile = path => ts.sys.readFile(path); - export const writeFile: typeof IO.writeFile = (path, content) => ts.sys.writeFile(path, content); - export const directoryName: typeof IO.directoryName = fso.GetParentFolderName; - export const getDirectories: typeof IO.getDirectories = dir => ts.sys.getDirectories(dir); - export const directoryExists: typeof IO.directoryExists = fso.FolderExists; - export const fileExists: typeof IO.fileExists = fso.FileExists; - export const log: typeof IO.log = global.WScript && global.WScript.StdOut.WriteLine; - export const getEnvironmentVariable: typeof IO.getEnvironmentVariable = name => ts.sys.getEnvironmentVariable(name); - export const readDirectory: typeof IO.readDirectory = (path, extension, exclude, include) => ts.sys.readDirectory(path, extension, exclude, include); - - export function createDirectory(path: string) { - if (directoryExists(path)) { - fso.CreateFolder(path); - } - } - - export function deleteFile(path: string) { - if (fileExists(path)) { - fso.DeleteFile(path, true); // true: delete read-only files - } - } - - export let listFiles: typeof IO.listFiles = (path, spec?, options?) => { - options = options || <{ recursive?: boolean; }>{}; - function filesInFolder(folder: any, root: string): string[] { - let paths: string[] = []; - let fc: any; - - if (options.recursive) { - fc = new Enumerator(folder.subfolders); - - for (; !fc.atEnd(); fc.moveNext()) { - paths = paths.concat(filesInFolder(fc.item(), root + "\\" + fc.item().Name)); - } - } - - fc = new Enumerator(folder.files); - - for (; !fc.atEnd(); fc.moveNext()) { - if (!spec || fc.item().Name.match(spec)) { - paths.push(root + "\\" + fc.item().Name); - } - } - - return paths; - } - - const folder: any = fso.GetFolder(path); - - return filesInFolder(folder, path); - }; - } - export namespace Node { declare const require: any; let fs: any, pathModule: any; @@ -840,16 +752,16 @@ namespace Harness { } } - switch (Utils.getExecutionEnvironment()) { - case Utils.ExecutionEnvironment.CScript: - IO = IOImpl.CScript; - break; + const environment = Utils.getExecutionEnvironment(); + switch (environment) { case Utils.ExecutionEnvironment.Node: IO = IOImpl.Node; break; case Utils.ExecutionEnvironment.Browser: IO = IOImpl.Network; break; + default: + throw new Error(`Unknown value '${environment}' for ExecutionEnvironment.`); } } @@ -873,7 +785,7 @@ namespace Harness { /** Aggregate various writes into a single array of lines. Useful for passing to the * TypeScript compiler to fill with source code or errors. */ - export class WriterAggregator implements ITextWriter { + export class WriterAggregator { public lines: string[] = []; public currentLine = undefined; diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 4d1b2a0b10c..a13835fa7f3 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -3489,6 +3489,52 @@ namespace ts.projectSystem { }); }); + describe("occurence highlight on string", () => { + it("should be marked if only on string values", () => { + const file1: FileOrFolder = { + path: "/a/b/file1.ts", + content: `let t1 = "div";\nlet t2 = "div";\nlet t3 = { "div": 123 };\nlet t4 = t3["div"];` + }; + + const host = createServerHost([file1]); + const session = createSession(host); + const projectService = session.getProjectService(); + + projectService.openClientFile(file1.path); + { + const highlightRequest = makeSessionRequest( + CommandNames.Occurrences, + { file: file1.path, line: 1, offset: 11 } + ); + const highlightResponse = session.executeCommand(highlightRequest).response as protocol.OccurrencesResponseItem[]; + const firstOccurence = highlightResponse[0]; + assert.isTrue(firstOccurence.isInString, "Highlights should be marked with isInString"); + } + + { + const highlightRequest = makeSessionRequest( + CommandNames.Occurrences, + { file: file1.path, line: 3, offset: 13 } + ); + const highlightResponse = session.executeCommand(highlightRequest).response as protocol.OccurrencesResponseItem[]; + assert.isTrue(highlightResponse.length === 2); + const firstOccurence = highlightResponse[0]; + assert.isUndefined(firstOccurence.isInString, "Highlights should not be marked with isInString if on property name"); + } + + { + const highlightRequest = makeSessionRequest( + CommandNames.Occurrences, + { file: file1.path, line: 4, offset: 14 } + ); + const highlightResponse = session.executeCommand(highlightRequest).response as protocol.OccurrencesResponseItem[]; + assert.isTrue(highlightResponse.length === 2); + const firstOccurence = highlightResponse[0]; + assert.isUndefined(firstOccurence.isInString, "Highlights should not be marked with isInString if on indexer"); + } + }); + }); + describe("maxNodeModuleJsDepth for inferred projects", () => { it("should be set to 2 if the project has js root files", () => { const file1: FileOrFolder = { diff --git a/src/server/client.ts b/src/server/client.ts index 6f784db1682..8e81a423837 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -382,7 +382,9 @@ namespace ts.server { const end = this.lineOffsetToPosition(fileName, entry.end); return { fileName, - textSpan: ts.createTextSpanFromBounds(start, end) + textSpan: ts.createTextSpanFromBounds(start, end), + kind: ScriptElementKind.unknown, + displayParts: [] }; }); } diff --git a/src/server/protocol.ts b/src/server/protocol.ts index d12aa2e0a48..5096eefc1fc 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -621,6 +621,11 @@ namespace ts.server.protocol { * True if the occurrence is a write location, false otherwise. */ isWriteAccess: boolean; + + /** + * True if the occurrence is in a string, undefined otherwise; + */ + isInString?: true; } export interface OccurrencesResponse extends Response { diff --git a/src/server/session.ts b/src/server/session.ts index 64fce61a095..f82d11ba91b 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -651,16 +651,21 @@ namespace ts.server { } return occurrences.map(occurrence => { - const { fileName, isWriteAccess, textSpan } = occurrence; + const { fileName, isWriteAccess, textSpan, isInString } = occurrence; const scriptInfo = project.getScriptInfo(fileName); const start = scriptInfo.positionToLineOffset(textSpan.start); const end = scriptInfo.positionToLineOffset(ts.textSpanEnd(textSpan)); - return { + const result: protocol.OccurrencesResponseItem = { start, end, file: fileName, isWriteAccess, }; + // no need to serialize the property if it is not true + if (isInString) { + result.isInString = isInString; + } + return result; }); } diff --git a/src/services/documentHighlights.ts b/src/services/documentHighlights.ts index ff2b819ec26..7308ad235fc 100644 --- a/src/services/documentHighlights.ts +++ b/src/services/documentHighlights.ts @@ -17,7 +17,8 @@ namespace ts.DocumentHighlights { } function getSemanticDocumentHighlights(node: Node, typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFilesToSearch: SourceFile[]): DocumentHighlights[] { - const referencedSymbols = FindAllReferences.getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFilesToSearch); + const context = new FindAllReferences.DefaultFindReferencesContext(typeChecker, cancellationToken); + const referencedSymbols = FindAllReferences.getReferencedSymbolsForNode(context, node, sourceFilesToSearch); return referencedSymbols && convertReferencedSymbols(referencedSymbols); } @@ -37,7 +38,8 @@ namespace ts.DocumentHighlights { documentHighlights.highlightSpans.push({ textSpan: referenceEntry.textSpan, - kind: referenceEntry.isWriteAccess ? HighlightSpanKind.writtenReference : HighlightSpanKind.reference + kind: referenceEntry.isWriteAccess ? HighlightSpanKind.writtenReference : HighlightSpanKind.reference, + isInString: referenceEntry.isInString }); } } diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index bc1e50391c8..725b9b99506 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -1,21 +1,75 @@ /* @internal */ namespace ts.FindAllReferences { + + export interface FindReferencesContext { + readonly typeChecker: TypeChecker; + readonly cancellationToken: CancellationToken; + getReferenceEntryFromNode(node: Node, isInString?: boolean): T; + getReferenceEntryForSpanInFile(fileName: string, span: TextSpan): T; + } + + export class DefaultFindReferencesContext implements FindReferencesContext { + constructor(readonly typeChecker: TypeChecker, readonly cancellationToken: CancellationToken) { + } + getReferenceEntryFromNode(node: Node, isInString?: boolean): ReferenceEntry { + const reference = getReferenceEntryFromNode(node); + if (isInString) { + reference.isInString = true; + } + return reference; + } + getReferenceEntryForSpanInFile(fileName: string, textSpan: TextSpan): ReferenceEntry { + return { textSpan, fileName, isWriteAccess: false, isDefinition: false }; + } + } + + export class FindImplementationsContext implements FindReferencesContext { + constructor(readonly typeChecker: TypeChecker, readonly cancellationToken: CancellationToken) { + } + getReferenceEntryFromNode(node: Node): ImplementationLocation { + const entry = getReferenceEntryFromNode(node); + const symbol = this.typeChecker.getSymbolAtLocation(isDeclaration(node) && node.name ? node.name : node); + if (symbol) { + const def = getDefinition(symbol, node, this.typeChecker); + entry.kind = def.kind; + entry.displayParts = def.displayParts; + } + else if (node.kind === SyntaxKind.ObjectLiteralExpression) { + entry.kind = ScriptElementKind.interfaceElement; + entry.displayParts = [punctuationPart(SyntaxKind.OpenParenToken), textPart("object literal"), punctuationPart(SyntaxKind.CloseParenToken)] + } + else if (node.kind === SyntaxKind.ClassExpression) { + entry.kind = ScriptElementKind.localClassElement; + entry.displayParts = [punctuationPart(SyntaxKind.OpenParenToken), textPart("anonymous local class"), punctuationPart(SyntaxKind.CloseParenToken)] + } + else { + entry.kind = getNodeKind(node); + entry.displayParts = []; + } + return entry; + } + getReferenceEntryForSpanInFile(fileName: string, textSpan: TextSpan): ImplementationLocation { + return { textSpan, fileName, kind: ScriptElementKind.unknown, displayParts: [] }; + } + } + export function findReferencedSymbols(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number, findInStrings: boolean, findInComments: boolean, isForRename: boolean): ReferencedSymbol[] | undefined { const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true); - return getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFiles, findInStrings, findInComments, isForRename); + return getReferencedSymbolsForNode(new DefaultFindReferencesContext(typeChecker, cancellationToken), node, sourceFiles, findInStrings, findInComments, isForRename); } export function convertReferences(referenceSymbols: ReferencedSymbol[]): ReferenceEntry[] { return referenceSymbols && flatMap(referenceSymbols, r => r.references); } - export function getReferencedSymbolsForNode(typeChecker: TypeChecker, cancellationToken: CancellationToken, node: Node, sourceFiles: SourceFile[], findInStrings?: boolean, findInComments?: boolean, isForRename?: boolean, implementations?: boolean): ReferencedSymbol[] | undefined { + export function getReferencedSymbolsForNode(context: FindReferencesContext, node: Node, sourceFiles: SourceFile[], findInStrings?: boolean, findInComments?: boolean, isForRename?: boolean, implementations?: boolean): ReferencedSymbolOf[] | undefined { if (!implementations) { - const special = getReferencedSymbolsSpecial(node, sourceFiles, typeChecker, cancellationToken); + const special = getReferencedSymbolsSpecial(node, sourceFiles, context); if (special) { return special; } } + const { typeChecker, cancellationToken } = context; // `getSymbolAtLocation` normally returns the symbol of the class when given the constructor keyword, // so we have to specify that we want the constructor symbol. @@ -24,7 +78,7 @@ namespace ts.FindAllReferences { // Could not find a symbol e.g. unknown identifier if (!symbol) { if (!implementations && node.kind === SyntaxKind.StringLiteral) { - return getReferencesForStringLiteral(node, sourceFiles, typeChecker, cancellationToken); + return getReferencesForStringLiteral(node, sourceFiles, context); } // Can't have references to something that we have no symbol for. return undefined; @@ -49,7 +103,7 @@ namespace ts.FindAllReferences { // Compute the meaning from the location and the symbol it references const searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations); - const result: ReferencedSymbol[] = []; + const result: ReferencedSymbolOf[] = []; // Maps from a symbol ID to the ReferencedSymbol entry in 'result'. const symbolToIndex: number[] = []; const inheritsFromCache: Map = createMap(); @@ -81,14 +135,14 @@ namespace ts.FindAllReferences { function getRefs(scope: ts.Node, searchName: string): void { getReferencesInNode(scope, symbol, searchName, node, searchMeaning, findInStrings, findInComments, result, - symbolToIndex, implementations, typeChecker, cancellationToken, searchSymbols, inheritsFromCache); + symbolToIndex, implementations, context, searchSymbols, inheritsFromCache); } } /** getReferencedSymbols for special node kinds. */ - function getReferencedSymbolsSpecial(node: Node, sourceFiles: SourceFile[], typeChecker: TypeChecker, cancellationToken: CancellationToken): ReferencedSymbol[] | undefined { + function getReferencedSymbolsSpecial(node: Node, sourceFiles: SourceFile[], context: FindReferencesContext): ReferencedSymbolOf[] | undefined { if (isTypeKeyword(node.kind)) { - return getAllReferencesForKeyword(sourceFiles, node.kind, cancellationToken); + return getAllReferencesForKeyword(context, sourceFiles, node.kind); } // Labels @@ -97,20 +151,20 @@ namespace ts.FindAllReferences { const labelDefinition = getTargetLabel((node.parent), (node).text); // if we have a label definition, look within its statement for references, if not, then // the label is undefined and we have no results.. - return labelDefinition && getLabelReferencesInNode(labelDefinition.parent, labelDefinition, cancellationToken); + return labelDefinition && getLabelReferencesInNode(labelDefinition.parent, labelDefinition, context); } else { // it is a label definition and not a target, search within the parent labeledStatement - return getLabelReferencesInNode(node.parent, node, cancellationToken); + return getLabelReferencesInNode(node.parent, node, context); } } if (isThis(node)) { - return getReferencesForThisKeyword(node, sourceFiles, typeChecker, cancellationToken); + return getReferencesForThisKeyword(node, sourceFiles, context); } if (node.kind === SyntaxKind.SuperKeyword) { - return getReferencesForSuperKeyword(node, typeChecker, cancellationToken); + return getReferencesForSuperKeyword(node, context); } return undefined; @@ -352,10 +406,11 @@ namespace ts.FindAllReferences { return positions; } - function getLabelReferencesInNode(container: Node, targetLabel: Identifier, cancellationToken: CancellationToken): ReferencedSymbol[] { - const references: ReferenceEntry[] = []; + function getLabelReferencesInNode(container: Node, targetLabel: Identifier, context: FindReferencesContext): ReferencedSymbolOf[] { + const references: T[] = []; const sourceFile = container.getSourceFile(); const labelName = targetLabel.text; + const { cancellationToken } = context; const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd(), cancellationToken); forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); @@ -368,7 +423,7 @@ namespace ts.FindAllReferences { // Only pick labels that are either the target label, or have a target that is the target label if (node === targetLabel || (isJumpStatementTarget(node) && getTargetLabel(node, labelName) === targetLabel)) { - references.push(getReferenceEntryFromNode(node)); + references.push(context.getReferenceEntryFromNode(node)); } }); @@ -404,12 +459,13 @@ namespace ts.FindAllReferences { } } - function getAllReferencesForKeyword(sourceFiles: SourceFile[], keywordKind: ts.SyntaxKind, cancellationToken: CancellationToken): ReferencedSymbol[] { + function getAllReferencesForKeyword(context: FindReferencesContext, sourceFiles: SourceFile[], keywordKind: ts.SyntaxKind): ReferencedSymbolOf[] { + const { cancellationToken } = context; const name = tokenToString(keywordKind); - const references: ReferenceEntry[] = []; + const references: T[] = []; for (const sourceFile of sourceFiles) { cancellationToken.throwIfCancellationRequested(); - addReferencesForKeywordInFile(sourceFile, keywordKind, name, cancellationToken, references); + addReferencesForKeywordInFile(sourceFile, keywordKind, name, context, references); } if (!references.length) return undefined; @@ -427,18 +483,14 @@ namespace ts.FindAllReferences { return [{ definition, references }]; } - function addReferencesForKeywordInFile(sourceFile: SourceFile, kind: SyntaxKind, searchText: string, cancellationToken: CancellationToken, references: Push): void { + function addReferencesForKeywordInFile(sourceFile: SourceFile, kind: SyntaxKind, searchText: string, context: FindReferencesContext, references: Push): void { + const { cancellationToken } = context; const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, sourceFile.getStart(), sourceFile.getEnd(), cancellationToken); for (const position of possiblePositions) { cancellationToken.throwIfCancellationRequested(); const referenceLocation = getTouchingPropertyName(sourceFile, position); if (referenceLocation.kind === kind) { - references.push({ - textSpan: createTextSpanFromNode(referenceLocation), - fileName: sourceFile.fileName, - isWriteAccess: false, - isDefinition: false, - }); + references.push(context.getReferenceEntryForSpanInFile(sourceFile.fileName, createTextSpanFromNode(referenceLocation))); } } } @@ -447,22 +499,22 @@ namespace ts.FindAllReferences { * tuple of(searchSymbol, searchText, searchLocation, and searchMeaning). * searchLocation: a node where the search value */ - function getReferencesInNode(container: Node, + function getReferencesInNode(container: Node, searchSymbol: Symbol, searchText: string, searchLocation: Node, searchMeaning: SemanticMeaning, findInStrings: boolean, findInComments: boolean, - result: ReferencedSymbol[], + result: ReferencedSymbolOf[], symbolToIndex: number[], implementations: boolean, - typeChecker: TypeChecker, - cancellationToken: CancellationToken, + context: FindReferencesContext, searchSymbols: Symbol[], inheritsFromCache: Map): void { const sourceFile = container.getSourceFile(); + const { typeChecker, cancellationToken } = context; const start = findInComments ? container.getFullStart() : container.getStart(); const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, start, container.getEnd(), cancellationToken); @@ -486,12 +538,7 @@ namespace ts.FindAllReferences { // 'FindReferences' will just filter out these results. result.push({ definition: undefined, - references: [{ - fileName: sourceFile.fileName, - textSpan: createTextSpan(position, searchText.length), - isWriteAccess: false, - isDefinition: false - }] + references: [context.getReferenceEntryForSpanInFile(sourceFile.fileName, createTextSpan(position, searchText.length))] }); } continue; @@ -571,11 +618,11 @@ namespace ts.FindAllReferences { function addReferences(references: Node[]): void { if (references.length) { const referencedSymbol = getReferencedSymbol(searchSymbol); - addRange(referencedSymbol.references, map(references, getReferenceEntryFromNode)); + addRange(referencedSymbol.references, map(references, n => context.getReferenceEntryFromNode(n))); } } - function getReferencedSymbol(symbol: Symbol): ReferencedSymbol { + function getReferencedSymbol(symbol: Symbol): ReferencedSymbolOf { const symbolId = getSymbolId(symbol); let index = symbolToIndex[symbolId]; if (index === undefined) { @@ -594,10 +641,10 @@ namespace ts.FindAllReferences { function addReferenceToRelatedSymbol(node: Node, relatedSymbol: Symbol) { const references = getReferencedSymbol(relatedSymbol).references; if (implementations) { - getImplementationReferenceEntryForNode(node, references, typeChecker); + getImplementationReferenceEntryForNode(node, references, context); } else { - references.push(getReferenceEntryFromNode(node)); + references.push(context.getReferenceEntryFromNode(node)); } } } @@ -658,21 +705,21 @@ namespace ts.FindAllReferences { return result; } - function getImplementationReferenceEntryForNode(refNode: Node, result: ReferenceEntry[], typeChecker: TypeChecker): void { + function getImplementationReferenceEntryForNode(refNode: Node, result: T[], context: FindReferencesContext): void { // Check if we found a function/propertyAssignment/method with an implementation or initializer if (isDeclarationName(refNode) && isImplementation(refNode.parent)) { - result.push(getReferenceEntryFromNode(refNode.parent)); + result.push(context.getReferenceEntryFromNode(refNode.parent)); } else if (refNode.kind === SyntaxKind.Identifier) { if (refNode.parent.kind === SyntaxKind.ShorthandPropertyAssignment) { // Go ahead and dereference the shorthand assignment by going to its definition - getReferenceEntriesForShorthandPropertyAssignment(refNode, typeChecker, result); + getReferenceEntriesForShorthandPropertyAssignment(refNode, context, result); } // Check if the node is within an extends or implements clause const containingClass = getContainingClassIfInHeritageClause(refNode); if (containingClass) { - result.push(getReferenceEntryFromNode(containingClass)); + result.push(context.getReferenceEntryFromNode(containingClass)); return; } @@ -681,22 +728,22 @@ namespace ts.FindAllReferences { if (containingTypeReference) { const parent = containingTypeReference.parent; if (isVariableLike(parent) && parent.type === containingTypeReference && parent.initializer && isImplementationExpression(parent.initializer)) { - maybeAdd(getReferenceEntryFromNode(parent.initializer)); + maybeAdd(context.getReferenceEntryFromNode(parent.initializer)); } else if (isFunctionLike(parent) && parent.type === containingTypeReference && parent.body) { if (parent.body.kind === SyntaxKind.Block) { forEachReturnStatement(parent.body, returnStatement => { if (returnStatement.expression && isImplementationExpression(returnStatement.expression)) { - maybeAdd(getReferenceEntryFromNode(returnStatement.expression)); + maybeAdd(context.getReferenceEntryFromNode(returnStatement.expression)); } }); } else if (isImplementationExpression(parent.body)) { - maybeAdd(getReferenceEntryFromNode(parent.body)); + maybeAdd(context.getReferenceEntryFromNode(parent.body)); } } else if (isAssertionExpression(parent) && isImplementationExpression(parent.expression)) { - maybeAdd(getReferenceEntryFromNode(parent.expression)); + maybeAdd(context.getReferenceEntryFromNode(parent.expression)); } } } @@ -706,7 +753,7 @@ namespace ts.FindAllReferences { // Because we are returning the implementation locations and not the identifier locations, // duplicate entries would be returned here as each of the type references is part of // the same implementation. For that reason, check before we add a new entry - function maybeAdd(a: ReferenceEntry) { + function maybeAdd(a: T) { if (!forEach(result, b => a.fileName === b.fileName && a.textSpan.start === b.textSpan.start && a.textSpan.length === b.textSpan.length)) { result.push(a); } @@ -845,7 +892,7 @@ namespace ts.FindAllReferences { } } - function getReferencesForSuperKeyword(superKeyword: Node, typeChecker: TypeChecker, cancellationToken: CancellationToken): ReferencedSymbol[] { + function getReferencesForSuperKeyword(superKeyword: Node, context: FindReferencesContext): ReferencedSymbolOf[] { let searchSpaceNode = getSuperContainer(superKeyword, /*stopOnFunctions*/ false); if (!searchSpaceNode) { return undefined; @@ -868,7 +915,8 @@ namespace ts.FindAllReferences { return undefined; } - const references: ReferenceEntry[] = []; + const references: T[] = []; + const { typeChecker, cancellationToken } = context; const sourceFile = searchSpaceNode.getSourceFile(); const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd(), cancellationToken); @@ -887,7 +935,7 @@ namespace ts.FindAllReferences { // Now make sure the owning class is the same as the search-space // and has the same static qualifier as the original 'super's owner. if (container && (ModifierFlags.Static & getModifierFlags(container)) === staticFlag && container.parent.symbol === searchSpaceNode.symbol) { - references.push(getReferenceEntryFromNode(node)); + references.push(context.getReferenceEntryFromNode(node)); } } @@ -895,8 +943,9 @@ namespace ts.FindAllReferences { return [{ definition, references }]; } - function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: SourceFile[], typeChecker: TypeChecker, cancellationToken: CancellationToken): ReferencedSymbol[] { + function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: SourceFile[], context: FindReferencesContext): ReferencedSymbolOf[] { let searchSpaceNode = getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false); + const { typeChecker, cancellationToken } = context; // Whether 'this' occurs in a static context within a class. let staticFlag = ModifierFlags.Static; @@ -930,7 +979,7 @@ namespace ts.FindAllReferences { return undefined; } - const references: ReferenceEntry[] = []; + const references: T[] = []; let possiblePositions: number[]; if (searchSpaceNode.kind === SyntaxKind.SourceFile) { @@ -963,7 +1012,7 @@ namespace ts.FindAllReferences { references: references }]; - function getThisReferencesInFile(sourceFile: SourceFile, searchSpaceNode: Node, possiblePositions: number[], result: ReferenceEntry[]): void { + function getThisReferencesInFile(sourceFile: SourceFile, searchSpaceNode: Node, possiblePositions: number[], result: T[]): void { forEach(possiblePositions, position => { cancellationToken.throwIfCancellationRequested(); @@ -978,13 +1027,13 @@ namespace ts.FindAllReferences { case SyntaxKind.FunctionExpression: case SyntaxKind.FunctionDeclaration: if (searchSpaceNode.symbol === container.symbol) { - result.push(getReferenceEntryFromNode(node)); + result.push(context.getReferenceEntryFromNode(node)); } break; case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: if (isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol) { - result.push(getReferenceEntryFromNode(node)); + result.push(context.getReferenceEntryFromNode(node)); } break; case SyntaxKind.ClassExpression: @@ -992,12 +1041,12 @@ namespace ts.FindAllReferences { // Make sure the container belongs to the same class // and has the appropriate static modifier from the original container. if (container.parent && searchSpaceNode.symbol === container.parent.symbol && (getModifierFlags(container) & ModifierFlags.Static) === staticFlag) { - result.push(getReferenceEntryFromNode(node)); + result.push(context.getReferenceEntryFromNode(node)); } break; case SyntaxKind.SourceFile: if (container.kind === SyntaxKind.SourceFile && !isExternalModule(container)) { - result.push(getReferenceEntryFromNode(node)); + result.push(context.getReferenceEntryFromNode(node)); } break; } @@ -1005,7 +1054,8 @@ namespace ts.FindAllReferences { } } - function getReferencesForStringLiteral(node: StringLiteral, sourceFiles: SourceFile[], typeChecker: TypeChecker, cancellationToken: CancellationToken): ReferencedSymbol[] { + function getReferencesForStringLiteral(node: StringLiteral, sourceFiles: SourceFile[], context: FindReferencesContext): ReferencedSymbolOf[] { + const { typeChecker, cancellationToken } = context; const type = getStringLiteralTypeForNode(node, typeChecker); if (!type) { @@ -1013,7 +1063,7 @@ namespace ts.FindAllReferences { return undefined; } - const references: ReferenceEntry[] = []; + const references: T[] = []; for (const sourceFile of sourceFiles) { const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, type.text, sourceFile.getStart(), sourceFile.getEnd(), cancellationToken); @@ -1033,7 +1083,7 @@ namespace ts.FindAllReferences { references: references }]; - function getReferencesForStringLiteralInFile(sourceFile: SourceFile, searchType: Type, possiblePositions: number[], references: ReferenceEntry[]): void { + function getReferencesForStringLiteralInFile(sourceFile: SourceFile, searchType: Type, possiblePositions: number[], references: T[]): void { for (const position of possiblePositions) { cancellationToken.throwIfCancellationRequested(); @@ -1044,7 +1094,7 @@ namespace ts.FindAllReferences { const type = getStringLiteralTypeForNode(node, typeChecker); if (type === searchType) { - references.push(getReferenceEntryFromNode(node)); + references.push(context.getReferenceEntryFromNode(node, /*isInString*/ true)); } } } @@ -1357,14 +1407,15 @@ namespace ts.FindAllReferences { } } - export function getReferenceEntriesForShorthandPropertyAssignment(node: Node, typeChecker: TypeChecker, result: ReferenceEntry[]): void { + export function getReferenceEntriesForShorthandPropertyAssignment(node: Node, context: FindReferencesContext, result: T[]): void { + const { typeChecker } = context; const refSymbol = typeChecker.getSymbolAtLocation(node); const shorthandSymbol = typeChecker.getShorthandAssignmentValueSymbol(refSymbol.valueDeclaration); if (shorthandSymbol) { for (const declaration of shorthandSymbol.getDeclarations()) { if (getMeaningFromDeclaration(declaration) & SemanticMeaning.Value) { - result.push(getReferenceEntryFromNode(declaration)); + result.push(context.getReferenceEntryFromNode(declaration)); } } } diff --git a/src/services/goToImplementation.ts b/src/services/goToImplementation.ts index 9135e1fe0f0..dd3c06174af 100644 --- a/src/services/goToImplementation.ts +++ b/src/services/goToImplementation.ts @@ -1,25 +1,25 @@ /* @internal */ namespace ts.GoToImplementation { export function getImplementationAtPosition(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], node: Node): ImplementationLocation[] { + const context = new FindAllReferences.FindImplementationsContext(typeChecker, cancellationToken); // If invoked directly on a shorthand property assignment, then return // the declaration of the symbol being assigned (not the symbol being assigned to). if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) { - const result: ReferenceEntry[] = []; - FindAllReferences.getReferenceEntriesForShorthandPropertyAssignment(node, typeChecker, result); + const result: ImplementationLocation[] = []; + FindAllReferences.getReferenceEntriesForShorthandPropertyAssignment(node, context, result); return result.length > 0 ? result : undefined; } else if (node.kind === SyntaxKind.SuperKeyword || isSuperProperty(node.parent)) { // References to and accesses on the super keyword only have one possible implementation, so no // need to "Find all References" const symbol = typeChecker.getSymbolAtLocation(node); - return symbol.valueDeclaration && [FindAllReferences.getReferenceEntryFromNode(symbol.valueDeclaration)]; + return symbol.valueDeclaration && [context.getReferenceEntryFromNode(symbol.valueDeclaration)]; } else { // Perform "Find all References" and retrieve only those that are implementations - const referencedSymbols = FindAllReferences.getReferencedSymbolsForNode(typeChecker, cancellationToken, + const referencedSymbols = FindAllReferences.getReferencedSymbolsForNode(context, node, sourceFiles, /*findInStrings*/false, /*findInComments*/false, /*isForRename*/false, /*implementations*/true); - const result = flatMap(referencedSymbols, symbol => - map(symbol.references, ({ textSpan, fileName }) => ({ textSpan, fileName }))); + const result = flatMap(referencedSymbols, symbol => symbol.references); return result && result.length > 0 ? result : undefined; } diff --git a/src/services/services.ts b/src/services/services.ts index e370dccac32..a2931a39ab0 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1396,7 +1396,8 @@ namespace ts { fileName: entry.fileName, textSpan: highlightSpan.textSpan, isWriteAccess: highlightSpan.kind === HighlightSpanKind.writtenReference, - isDefinition: false + isDefinition: false, + isInString: highlightSpan.isInString, }); } } diff --git a/src/services/types.ts b/src/services/types.ts index 149bb4340dc..856b03330bf 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -354,21 +354,23 @@ namespace ts { caretOffset: number; } - export interface RenameLocation { + export interface DocumentSpan { textSpan: TextSpan; fileName: string; } - export interface ReferenceEntry { - textSpan: TextSpan; - fileName: string; + export interface RenameLocation extends DocumentSpan { + } + + export interface ReferenceEntry extends DocumentSpan { isWriteAccess: boolean; isDefinition: boolean; + isInString?: true; } - export interface ImplementationLocation { - textSpan: TextSpan; - fileName: string; + export interface ImplementationLocation extends DocumentSpan { + kind: string; + displayParts: SymbolDisplayPart[]; } export interface DocumentHighlights { @@ -385,6 +387,7 @@ namespace ts { export interface HighlightSpan { fileName?: string; + isInString?: true; textSpan: TextSpan; kind: string; } @@ -476,9 +479,12 @@ namespace ts { displayParts: SymbolDisplayPart[]; } - export interface ReferencedSymbol { + export interface ReferencedSymbolOf { definition: ReferencedSymbolDefinitionInfo; - references: ReferenceEntry[]; + references: T[]; + } + + export interface ReferencedSymbol extends ReferencedSymbolOf { } export enum SymbolDisplayPartKind { diff --git a/src/tsconfig-base.json b/src/tsconfig-base.json index 078fdcc91e7..caf8e880fad 100644 --- a/src/tsconfig-base.json +++ b/src/tsconfig-base.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "lib": ["es5", "scripthost"], + "lib": ["es5"], "noEmitOnError": true, "noImplicitAny": true, "noImplicitThis": true, @@ -13,4 +13,4 @@ "target": "es5", "types": [] } -} \ No newline at end of file +} diff --git a/tests/cases/fourslash/findAllRefsForStringLiteralTypes.ts b/tests/cases/fourslash/findAllRefsForStringLiteralTypes.ts index e450102c127..312bce4a3ad 100644 --- a/tests/cases/fourslash/findAllRefsForStringLiteralTypes.ts +++ b/tests/cases/fourslash/findAllRefsForStringLiteralTypes.ts @@ -1,6 +1,6 @@ /// -////type Options = "[|option 1|]" | "option 2"; -////let myOption: Options = "[|option 1|]"; +////type Options = "[|{| "isInString": true |}option 1|]" | "option 2"; +////let myOption: Options = "[|{| "isInString": true |}option 1|]"; verify.singleReferenceGroup('"option 1"'); diff --git a/tests/cases/fourslash/goToImplementationClassMethod_00.ts b/tests/cases/fourslash/goToImplementationClassMethod_00.ts index 6fc8d9bf7cc..09bece0c1a2 100644 --- a/tests/cases/fourslash/goToImplementationClassMethod_00.ts +++ b/tests/cases/fourslash/goToImplementationClassMethod_00.ts @@ -3,7 +3,7 @@ // Should handle calls made on members declared in a class //// class Bar { -//// [|hello() {}|] +//// [|{|"parts": ["(","method",")"," ","Bar",".","hello","(",")",":"," ","void"], "kind": "method"|}hello() {}|] //// } //// //// new Bar().hel/*reference*/lo; diff --git a/tests/cases/fourslash/goToImplementationInterface_00.ts b/tests/cases/fourslash/goToImplementationInterface_00.ts index 8fc36b4bab5..33ff9fbd045 100644 --- a/tests/cases/fourslash/goToImplementationInterface_00.ts +++ b/tests/cases/fourslash/goToImplementationInterface_00.ts @@ -8,12 +8,12 @@ //// //// interface Baz extends Foo {} //// -//// var bar: Foo = [|{ hello: helloImpl /**0*/ }|]; +//// var bar: Foo = [|{|"parts": ["(","object literal",")"], "kind": "interface"|}{ hello: helloImpl /**0*/ }|]; //// var baz: Foo[] = [|[{ hello: helloImpl /**4*/ }]|]; //// //// function helloImpl () {} //// -//// function whatever(x: Foo = [|{ hello() {/**1*/} }|] ) { +//// function whatever(x: Foo = [|{|"parts": ["(","object literal",")"], "kind": "interface"|}{ hello() {/**1*/} }|] ) { //// } //// //// class Bar { diff --git a/tests/cases/fourslash/goToImplementationInterface_07.ts b/tests/cases/fourslash/goToImplementationInterface_07.ts index 6d874b3dc76..960072004b4 100644 --- a/tests/cases/fourslash/goToImplementationInterface_07.ts +++ b/tests/cases/fourslash/goToImplementationInterface_07.ts @@ -19,6 +19,8 @@ //// let x7: (new() => Foo) = [|class { hello () { /**constructorType*/} }|]; //// let x8: Foo[] = [|[{ hello () { /**arrayType*/} }]|]; //// let x9: { y: Foo } = [|{ y: { hello () { /**typeLiteral*/} } }|]; +//// let x10 = [|{|"parts": ["(","anonymous local class",")"], "kind": "local class"|}class implements Foo { hello() {} }|] +//// let x11 = [|{|"parts": ["(","local class",")"," ","C"], "kind": "local class"|}class C implements Foo { hello() {} }|] //// //// // Should not do anything for type predicates //// function isFoo(a: any): a is Foo { diff --git a/tests/cases/fourslash/referencesForIndexProperty2.ts b/tests/cases/fourslash/referencesForIndexProperty2.ts index a4d5c75a908..0f87c82f7d3 100644 --- a/tests/cases/fourslash/referencesForIndexProperty2.ts +++ b/tests/cases/fourslash/referencesForIndexProperty2.ts @@ -3,6 +3,6 @@ // References to a unknown index property ////var a; -////a["[|blah|]"]; +////a["[|{| "isInString": true |}blah|]"]; verify.singleReferenceGroup('"blah"');