diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 34b49a33ae3..67a62165e0d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7,6 +7,15 @@ module ts { /* @internal */ export let checkTime = 0; + /* @internal */ + export function getSymbolId(symbol: Symbol): number { + if (!symbol.id) { + symbol.id = nextSymbolId++; + } + + return symbol.id; + } + export function createTypeChecker(host: TypeCheckerHost, produceDiagnostics: boolean): TypeChecker { let Symbol = objectAllocator.getSymbolConstructor(); let Type = objectAllocator.getTypeConstructor(); @@ -250,8 +259,8 @@ module ts { function getSymbolLinks(symbol: Symbol): SymbolLinks { if (symbol.flags & SymbolFlags.Transient) return symbol; - if (!symbol.id) symbol.id = nextSymbolId++; - return symbolLinks[symbol.id] || (symbolLinks[symbol.id] = {}); + var id = getSymbolId(symbol); + return symbolLinks[id] || (symbolLinks[id] = {}); } function getNodeLinks(node: Node): NodeLinks { diff --git a/src/compiler/program.ts b/src/compiler/program.ts index f902cb3b13a..cb12e6da4d5 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -10,6 +10,22 @@ module ts { /** The version of the TypeScript compiler release */ export let version = "1.5.0.0"; + export function findConfigFile(searchPath: string): string { + var fileName = "tsconfig.json"; + while (true) { + if (sys.fileExists(fileName)) { + return fileName; + } + var parentPath = getDirectoryPath(searchPath); + if (parentPath === searchPath) { + break; + } + searchPath = parentPath; + fileName = "../" + fileName; + } + return undefined; + } + export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost { let currentDirectory: string; let existingDirectories: Map = {}; @@ -87,6 +103,11 @@ module ts { export function getPreEmitDiagnostics(program: Program): Diagnostic[] { let diagnostics = program.getSyntacticDiagnostics().concat(program.getGlobalDiagnostics()).concat(program.getSemanticDiagnostics()); + + if (program.getCompilerOptions().declaration) { + diagnostics.concat(program.getDeclarationDiagnostics()); + } + return sortAndDeduplicateDiagnostics(diagnostics); } diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 3f82d6c8cf5..a0d21106f43 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -132,23 +132,6 @@ module ts { return typeof JSON === "object" && typeof JSON.parse === "function"; } - function findConfigFile(): string { - var searchPath = normalizePath(sys.getCurrentDirectory()); - var fileName = "tsconfig.json"; - while (true) { - if (sys.fileExists(fileName)) { - return fileName; - } - var parentPath = getDirectoryPath(searchPath); - if (parentPath === searchPath) { - break; - } - searchPath = parentPath; - fileName = "../" + fileName; - } - return undefined; - } - export function executeCommandLine(args: string[]): void { var commandLine = parseCommandLine(args); var configFileName: string; // Configuration file name (if any) @@ -198,7 +181,8 @@ module ts { } } else if (commandLine.fileNames.length === 0 && isJSONSupported()) { - configFileName = findConfigFile(); + var searchPath = normalizePath(sys.getCurrentDirectory()); + configFileName = findConfigFile(searchPath); } if (commandLine.fileNames.length === 0 && !configFileName) { diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index 68ac8d916fb..299ba52bdeb 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -330,6 +330,9 @@ module Harness.LanguageService { getReferencesAtPosition(fileName: string, position: number): ts.ReferenceEntry[] { return unwrapJSONCallResult(this.shim.getReferencesAtPosition(fileName, position)); } + findReferences(fileName: string, position: number): ts.ReferencedSymbol[] { + return unwrapJSONCallResult(this.shim.findReferences(fileName, position)); + } getOccurrencesAtPosition(fileName: string, position: number): ts.ReferenceEntry[] { return unwrapJSONCallResult(this.shim.getOccurrencesAtPosition(fileName, position)); } diff --git a/src/server/client.ts b/src/server/client.ts index 07c742db4f8..875e3ffdb5b 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -300,6 +300,11 @@ module ts.server { }); } + findReferences(fileName: string, position: number): ReferencedSymbol[]{ + // Not yet implemented. + return []; + } + getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] { var lineOffset = this.positionToOneBasedLineOffset(fileName, position); var args: protocol.FileLocationRequestArgs = { diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 1f9df9b46f0..034549ab464 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -272,14 +272,24 @@ module ts.server { export class Project { compilerService: CompilerService; - projectOptions: ProjectOptions; projectFilename: string; program: ts.Program; filenameToSourceFile: ts.Map = {}; updateGraphSeq = 0; + /** Used for configured projects which may have multiple open roots */ + openRefCount = 0; - constructor(public projectService: ProjectService) { - this.compilerService = new CompilerService(this); + constructor(public projectService: ProjectService, public projectOptions?: ProjectOptions) { + this.compilerService = new CompilerService(this,projectOptions && projectOptions.compilerOptions); + } + + addOpenRef() { + this.openRefCount++; + } + + deleteOpenRef() { + this.openRefCount--; + return this.openRefCount; } openReferencedFile(filename: string) { @@ -299,6 +309,10 @@ module ts.server { } } + isRoot(info: ScriptInfo) { + return this.compilerService.host.roots.some(root => root === info); + } + removeReferencedFile(info: ScriptInfo) { this.compilerService.host.removeReferencedFile(info); this.updateGraph(); @@ -375,11 +389,16 @@ module ts.server { export class ProjectService { filenameToScriptInfo: ts.Map = {}; - // open, non-configured files in two lists + // open, non-configured root files openFileRoots: ScriptInfo[] = []; - openFilesReferenced: ScriptInfo[] = []; - // projects covering open files + // projects built from openFileRoots inferredProjects: Project[] = []; + // projects specified by a tsconfig.json file + configuredProjects: Project[] = []; + // open files referenced by a project + openFilesReferenced: ScriptInfo[] = []; + // open files that are roots of a configured project + openFileRootsConfigured: ScriptInfo[] = []; hostConfiguration: HostConfiguration; constructor(public host: ServerHost, public psLogger: Logger, public eventHandler?: ProjectServiceEventHandler) { @@ -484,44 +503,77 @@ module ts.server { this.printProjects(); } - addOpenFile(info: ScriptInfo) { - this.findReferencingProjects(info); - if (info.defaultProject) { - this.openFilesReferenced.push(info); - } - else { - // create new inferred project p with the newly opened file as root - info.defaultProject = this.createInferredProject(info); - var openFileRoots: ScriptInfo[] = []; - // for each inferred project root r - for (var i = 0, len = this.openFileRoots.length; i < len; i++) { - var r = this.openFileRoots[i]; - // if r referenced by the new project - if (info.defaultProject.getSourceFile(r)) { - // remove project rooted at r - this.inferredProjects = - copyListRemovingItem(r.defaultProject, this.inferredProjects); - // put r in referenced open file list - this.openFilesReferenced.push(r); - // set default project of r to the new project - r.defaultProject = info.defaultProject; - } - else { - // otherwise, keep r as root of inferred project - openFileRoots.push(r); - } + updateConfiguredProjectList() { + var configuredProjects: Project[] = []; + for (var i = 0, len = this.configuredProjects.length; i < len; i++) { + if (this.configuredProjects[i].openRefCount > 0) { + configuredProjects.push(this.configuredProjects[i]); } - this.openFileRoots = openFileRoots; - this.openFileRoots.push(info); } + this.configuredProjects = configuredProjects; } + setConfiguredProjectRoot(info: ScriptInfo) { + for (var i = 0, len = this.configuredProjects.length; i < len; i++) { + let configuredProject = this.configuredProjects[i]; + if (configuredProject.isRoot(info)) { + info.defaultProject = configuredProject; + configuredProject.addOpenRef(); + return true; + } + } + return false; + } + + addOpenFile(info: ScriptInfo) { + if (this.setConfiguredProjectRoot(info)) { + this.openFileRootsConfigured.push(info); + } + else { + this.findReferencingProjects(info); + if (info.defaultProject) { + this.openFilesReferenced.push(info); + } + else { + // create new inferred project p with the newly opened file as root + info.defaultProject = this.createInferredProject(info); + var openFileRoots: ScriptInfo[] = []; + // for each inferred project root r + for (var i = 0, len = this.openFileRoots.length; i < len; i++) { + var r = this.openFileRoots[i]; + // if r referenced by the new project + if (info.defaultProject.getSourceFile(r)) { + // remove project rooted at r + this.inferredProjects = + copyListRemovingItem(r.defaultProject, this.inferredProjects); + // put r in referenced open file list + this.openFilesReferenced.push(r); + // set default project of r to the new project + r.defaultProject = info.defaultProject; + } + else { + // otherwise, keep r as root of inferred project + openFileRoots.push(r); + } + } + this.openFileRoots = openFileRoots; + this.openFileRoots.push(info); + } + } + this.updateConfiguredProjectList(); + } + + /** + * Remove this file from the set of open, non-configured files. + * @param info The file that has been closed or newly configured + * @param openedByConfig True if info has become a root of a configured project + */ closeOpenFile(info: ScriptInfo) { var openFileRoots: ScriptInfo[] = []; var removedProject: Project; for (var i = 0, len = this.openFileRoots.length; i < len; i++) { // if closed file is root of project - if (info == this.openFileRoots[i]) { + if (info === this.openFileRoots[i]) { // remove that project and remember it removedProject = info.defaultProject; } @@ -530,9 +582,29 @@ module ts.server { } } this.openFileRoots = openFileRoots; + if (!removedProject) { + var openFileRootsConfigured: ScriptInfo[] = []; + + for (var i = 0, len = this.openFileRootsConfigured.length; i < len; i++) { + if (info === this.openFileRootsConfigured[i]) { + if (info.defaultProject.deleteOpenRef() === 0) { + removedProject = info.defaultProject; + } + } + else { + openFileRootsConfigured.push(this.openFileRootsConfigured[i]); + } + } + + this.openFileRootsConfigured = openFileRootsConfigured; + } if (removedProject) { - // remove project from inferred projects list - this.inferredProjects = copyListRemovingItem(removedProject, this.inferredProjects); + if (removedProject.isConfiguredProject()) { + this.configuredProjects = copyListRemovingItem(removedProject, this.configuredProjects); + } + else { + this.inferredProjects = copyListRemovingItem(removedProject, this.inferredProjects); + } var openFilesReferenced: ScriptInfo[] = []; var orphanFiles: ScriptInfo[] = []; // for all open, referenced files f @@ -564,14 +636,22 @@ module ts.server { var referencingProjects: Project[] = []; info.defaultProject = undefined; for (var i = 0, len = this.inferredProjects.length; i < len; i++) { - this.inferredProjects[i].updateGraph(); - if (this.inferredProjects[i] != excludedProject) { - if (this.inferredProjects[i].getSourceFile(info)) { - info.defaultProject = this.inferredProjects[i]; - referencingProjects.push(this.inferredProjects[i]); + var inferredProject = this.inferredProjects[i]; + inferredProject.updateGraph(); + if (inferredProject != excludedProject) { + if (inferredProject.getSourceFile(info)) { + info.defaultProject = inferredProject; + referencingProjects.push(inferredProject); } } } + for (var i = 0, len = this.configuredProjects.length; i < len; i++) { + var configuredProject = this.configuredProjects[i]; + configuredProject.updateGraph(); + if (configuredProject.getSourceFile(info)) { + info.defaultProject = configuredProject; + } + } return referencingProjects; } @@ -676,9 +756,23 @@ module ts.server { * @param filename is absolute pathname */ - openClientFile(filename: string) { - // TODO: tsconfig check - var info = this.openFile(filename, true); + openClientFile(fileName: string) { + var searchPath = ts.normalizePath(getDirectoryPath(fileName)); + var configFileName = ts.findConfigFile(searchPath); + if (configFileName) { + configFileName = getAbsolutePath(configFileName, searchPath); + } + if (configFileName && (!this.configProjectIsActive(configFileName))) { + var configResult = this.openConfigFile(configFileName, fileName); + if (!configResult.success) { + this.log("Error opening config file " + configFileName + " " + configResult.errorMsg); + } + else { + this.log("Opened configuration file " + configFileName,"Info"); + this.configuredProjects.push(configResult.project); + } + } + var info = this.openFile(fileName, true); this.addOpenFile(info); this.printProjects(); return info; @@ -699,19 +793,6 @@ module ts.server { this.printProjects(); } - getProjectsReferencingFile(filename: string) { - var scriptInfo = ts.lookUp(this.filenameToScriptInfo, filename); - if (scriptInfo) { - var projects: Project[] = []; - for (var i = 0, len = this.inferredProjects.length; i < len; i++) { - if (this.inferredProjects[i].getSourceFile(scriptInfo)) { - projects.push(this.inferredProjects[i]); - } - } - return projects; - } - } - getProjectForFile(filename: string) { var scriptInfo = ts.lookUp(this.filenameToScriptInfo, filename); if (scriptInfo) { @@ -724,9 +805,9 @@ module ts.server { if (scriptInfo) { this.psLogger.startGroup(); this.psLogger.info("Projects for " + filename) - var projects = this.getProjectsReferencingFile(filename); + var projects = this.findReferencingProjects(scriptInfo); for (var i = 0, len = projects.length; i < len; i++) { - this.psLogger.info("Inferred Project " + i.toString()); + this.psLogger.info("Project " + i.toString()); } this.psLogger.endGroup(); } @@ -744,18 +825,42 @@ module ts.server { this.psLogger.info(project.filesToString()); this.psLogger.info("-----------------------------------------------"); } - this.psLogger.info("Open file roots: ") + for (var i = 0, len = this.configuredProjects.length; i < len; i++) { + var project = this.configuredProjects[i]; + project.updateGraph(); + this.psLogger.info("Project (configured) " + (i+this.inferredProjects.length).toString()); + this.psLogger.info(project.filesToString()); + this.psLogger.info("-----------------------------------------------"); + } + this.psLogger.info("Open file roots of inferred projects: ") for (var i = 0, len = this.openFileRoots.length; i < len; i++) { this.psLogger.info(this.openFileRoots[i].fileName); } - this.psLogger.info("Open files referenced: ") + this.psLogger.info("Open files referenced by inferred or configured projects: ") for (var i = 0, len = this.openFilesReferenced.length; i < len; i++) { - this.psLogger.info(this.openFilesReferenced[i].fileName); + var fileInfo = this.openFilesReferenced[i].fileName; + if (this.openFilesReferenced[i].defaultProject.isConfiguredProject()) { + fileInfo += " (configured)"; + } + this.psLogger.info(fileInfo); + } + this.psLogger.info("Open file roots of configured projects: ") + for (var i = 0, len = this.openFileRootsConfigured.length; i < len; i++) { + this.psLogger.info(this.openFileRootsConfigured[i].fileName); } this.psLogger.endGroup(); } - openConfigFile(configFilename: string): ProjectOpenResult { + configProjectIsActive(fileName: string) { + for (var i = 0, len = this.configuredProjects.length; i < len; i++) { + if (this.configuredProjects[i].projectFilename == fileName) { + return true; + } + } + return false; + } + + openConfigFile(configFilename: string, clientFileName?: string): ProjectOpenResult { configFilename = ts.normalizePath(configFilename); // file references will be relative to dirPath (or absolute) var dirPath = ts.getDirectoryPath(configFilename); @@ -764,33 +869,27 @@ module ts.server { return { errorMsg: "tsconfig syntax error" }; } else { - // REVIEW: specify no base path so can get absolute path below - var parsedCommandLine = ts.parseConfigFile(rawConfig); - - if (parsedCommandLine.errors) { - // TODO: gather diagnostics and transmit + var parsedCommandLine = ts.parseConfigFile(rawConfig, dirPath); + if (parsedCommandLine.errors && (parsedCommandLine.errors.length > 0)) { return { errorMsg: "tsconfig option errors" }; } else if (parsedCommandLine.fileNames) { - var proj = this.createProject(configFilename); + var projectOptions: ProjectOptions = { + files: parsedCommandLine.fileNames, + compilerOptions: parsedCommandLine.options + }; + var proj = this.createProject(configFilename, projectOptions); for (var i = 0, len = parsedCommandLine.fileNames.length; i < len; i++) { var rootFilename = parsedCommandLine.fileNames[i]; - var normRootFilename = ts.normalizePath(rootFilename); - normRootFilename = getAbsolutePath(normRootFilename, dirPath); - if (this.host.fileExists(normRootFilename)) { - // TODO: pass true for file exiplicitly opened - var info = this.openFile(normRootFilename, false); + if (ts.sys.fileExists(rootFilename)) { + var info = this.openFile(rootFilename, clientFileName == rootFilename); proj.addRoot(info); } else { return { errorMsg: "specified file " + rootFilename + " not found" }; } } - var projectOptions: ProjectOptions = { - files: parsedCommandLine.fileNames, - compilerOptions: parsedCommandLine.options - }; - proj.setProjectOptions(projectOptions); + proj.finishGraph(); return { success: true, project: proj }; } else { @@ -799,10 +898,10 @@ module ts.server { } } - createProject(projectFilename: string) { - var eproj = new Project(this); - eproj.projectFilename = projectFilename; - return eproj; + createProject(projectFilename: string, projectOptions?: ProjectOptions) { + var project = new Project(this, projectOptions); + project.projectFilename = projectFilename; + return project; } } @@ -811,14 +910,17 @@ module ts.server { host: LSHost; languageService: ts.LanguageService; classifier: ts.Classifier; - settings = ts.getDefaultCompilerOptions(); + settings: ts.CompilerOptions; documentRegistry = ts.createDocumentRegistry(); - constructor(public project: Project) { + constructor(public project: Project, opt?: ts.CompilerOptions) { this.host = new LSHost(project.projectService.host, project); - // override default ES6 (remove when compiler default back at ES5) - this.settings.target = ts.ScriptTarget.ES5; - this.host.setCompilationSettings(this.settings); + if (opt) { + this.setCompilerOptions(opt); + } + else { + this.setCompilerOptions(ts.getDefaultCompilerOptions()); + } this.languageService = ts.createLanguageService(this.host, this.documentRegistry); this.classifier = ts.createClassifier(); } diff --git a/src/server/session.ts b/src/server/session.ts index 79eefb879da..47ef40a8809 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -550,11 +550,11 @@ module ts.server { } return completions.entries.reduce((result: protocol.CompletionEntry[], entry: ts.CompletionEntry) => { - if (completions.isMemberCompletion || entry.name.indexOf(prefix) == 0) { + if (completions.isMemberCompletion || (entry.name.toLowerCase().indexOf(prefix.toLowerCase()) == 0)) { result.push(entry); } return result; - }, []); + }, []).sort((a, b) => a.name.localeCompare(b.name)); } getCompletionEntryDetails(line: number, offset: number, diff --git a/src/server/tsconfig.json b/src/server/tsconfig.json new file mode 100644 index 00000000000..2c8538c61e3 --- /dev/null +++ b/src/server/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "module": "commonjs", + "noImplicitAny": true, + "removeComments": true, + "preserveConstEnums": true, + "out": "../../built/local/tsserver.js", + "sourceMap": true + }, + "files": [ + "node.d.ts", + "editorServices.ts", + "protocol.d.ts", + "server.ts", + "session.ts" + ] +} diff --git a/src/services/services.ts b/src/services/services.ts index 9de88f2a7e7..23ff602ea4d 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -940,6 +940,7 @@ module ts { getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[]; getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[]; + findReferences(fileName: string, position: number): ReferencedSymbol[]; getNavigateToItems(searchValue: string, maxResultCount?: number): NavigateToItem[]; getNavigationBarItems(fileName: string): NavigationBarItem[]; @@ -1045,6 +1046,11 @@ module ts { containerName: string; } + export interface ReferencedSymbol { + definition: DefinitionInfo; + references: ReferenceEntry[]; + } + export enum SymbolDisplayPartKind { aliasName, className, @@ -2383,7 +2389,7 @@ module ts { // If '-d' is enabled, check for emitter error. One example of emitter error is export class implements non-export interface let declarationDiagnostics = program.getDeclarationDiagnostics(targetSourceFile); - return semanticDiagnostics.concat(declarationDiagnostics); + return concatenate(semanticDiagnostics, declarationDiagnostics); } function getCompilerOptionsDiagnostics() { @@ -3461,6 +3467,17 @@ module ts { }; } + function createDefinitionInfo(node: Node, symbolKind: string, symbolName: string, containerName: string): DefinitionInfo { + return { + fileName: node.getSourceFile().fileName, + textSpan: createTextSpanFromBounds(node.getStart(), node.getEnd()), + kind: symbolKind, + name: symbolName, + containerKind: undefined, + containerName + }; + } + /// Goto definition function getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[] { synchronizeHostData(); @@ -3476,7 +3493,7 @@ module ts { if (isJumpStatementTarget(node)) { let labelName = (node).text; let label = getTargetLabel((node.parent), (node).text); - return label ? [getDefinitionInfo(label, ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined; + return label ? [createDefinitionInfo(label, ScriptElementKind.label, labelName, /*containerName*/ undefined)] : undefined; } /// Triple slash reference comments @@ -3507,7 +3524,7 @@ module ts { // If this is an alias, and the request came at the declaration location // get the aliased symbol instead. This allows for goto def on an import e.g. // import {A, B} from "mod"; - // to jump to the implementation directelly. + // to jump to the implementation directly. if (symbol.flags & SymbolFlags.Alias) { let declaration = symbol.declarations[0]; if (node.kind === SyntaxKind.Identifier && node.parent === declaration) { @@ -3515,7 +3532,6 @@ module ts { } } - // Because name in short-hand property assignment has two different meanings: property name and property value, // using go-to-definition at such position should go to the variable declaration of the property value rather than // go to the declaration of the property name (in this case stay at the same position). However, if go-to-definition @@ -3532,7 +3548,7 @@ module ts { let shorthandSymbolName = typeInfoResolver.symbolToString(shorthandSymbol); let shorthandContainerName = typeInfoResolver.symbolToString(symbol.parent, node); return map(shorthandDeclarations, - declaration => getDefinitionInfo(declaration, shorthandSymbolKind, shorthandSymbolName, shorthandContainerName)); + declaration => createDefinitionInfo(declaration, shorthandSymbolKind, shorthandSymbolName, shorthandContainerName)); } let result: DefinitionInfo[] = []; @@ -3546,47 +3562,12 @@ module ts { !tryAddCallSignature(symbol, node, symbolKind, symbolName, containerName, result)) { // Just add all the declarations. forEach(declarations, declaration => { - result.push(getDefinitionInfo(declaration, symbolKind, symbolName, containerName)); + result.push(createDefinitionInfo(declaration, symbolKind, symbolName, containerName)); }); } return result; - function getDefinitionInfo(node: Node, symbolKind: string, symbolName: string, containerName: string): DefinitionInfo { - return { - fileName: node.getSourceFile().fileName, - textSpan: createTextSpanFromBounds(node.getStart(), node.getEnd()), - kind: symbolKind, - name: symbolName, - containerKind: undefined, - containerName - }; - } - - function tryAddSignature(signatureDeclarations: Declaration[], selectConstructors: boolean, symbolKind: string, symbolName: string, containerName: string, result: DefinitionInfo[]) { - let declarations: Declaration[] = []; - let definition: Declaration; - - forEach(signatureDeclarations, d => { - if ((selectConstructors && d.kind === SyntaxKind.Constructor) || - (!selectConstructors && (d.kind === SyntaxKind.FunctionDeclaration || d.kind === SyntaxKind.MethodDeclaration || d.kind === SyntaxKind.MethodSignature))) { - declarations.push(d); - if ((d).body) definition = d; - } - }); - - if (definition) { - result.push(getDefinitionInfo(definition, symbolKind, symbolName, containerName)); - return true; - } - else if (declarations.length) { - result.push(getDefinitionInfo(declarations[declarations.length - 1], symbolKind, symbolName, containerName)); - return true; - } - - return false; - } - function tryAddConstructSignature(symbol: Symbol, location: Node, symbolKind: string, symbolName: string, containerName: string, result: DefinitionInfo[]) { // Applicable only if we are in a new expression, or we are on a constructor declaration // and in either case the symbol has a construct signature definition, i.e. class @@ -3607,6 +3588,30 @@ module ts { } return false; } + + function tryAddSignature(signatureDeclarations: Declaration[], selectConstructors: boolean, symbolKind: string, symbolName: string, containerName: string, result: DefinitionInfo[]) { + let declarations: Declaration[] = []; + let definition: Declaration; + + forEach(signatureDeclarations, d => { + if ((selectConstructors && d.kind === SyntaxKind.Constructor) || + (!selectConstructors && (d.kind === SyntaxKind.FunctionDeclaration || d.kind === SyntaxKind.MethodDeclaration || d.kind === SyntaxKind.MethodSignature))) { + declarations.push(d); + if ((d).body) definition = d; + } + }); + + if (definition) { + result.push(createDefinitionInfo(definition, symbolKind, symbolName, containerName)); + return true; + } + else if (declarations.length) { + result.push(createDefinitionInfo(declarations[declarations.length - 1], symbolKind, symbolName, containerName)); + return true; + } + + return false; + } } /// References and Occurrences @@ -3622,7 +3627,7 @@ module ts { if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.ThisKeyword || node.kind === SyntaxKind.SuperKeyword || isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || isNameOfExternalModuleImportOrDeclaration(node)) { - return getReferencesForNode(node, [sourceFile], /*searchOnlyInCurrentFile*/ true, /*findInStrings:*/ false, /*findInComments:*/ false); + return convertReferences(getReferencesForNode(node, [sourceFile], /*searchOnlyInCurrentFile*/ true, /*findInStrings:*/ false, /*findInComments:*/ false)); } switch (node.kind) { @@ -3922,7 +3927,7 @@ module ts { return map(keywords, getReferenceEntryFromNode); } - function getSwitchCaseDefaultOccurrences(switchStatement: SwitchStatement) { + function getSwitchCaseDefaultOccurrences(switchStatement: SwitchStatement): ReferenceEntry[] { let keywords: Node[] = []; pushKeywordIf(keywords, switchStatement.getFirstToken(), SyntaxKind.SwitchKeyword); @@ -4045,7 +4050,7 @@ module ts { } } - function getModifierOccurrences(modifier: SyntaxKind, declaration: Node) { + function getModifierOccurrences(modifier: SyntaxKind, declaration: Node): ReferenceEntry[] { let container = declaration.parent; // Make sure we only highlight the keyword when it makes sense to do so. @@ -4150,15 +4155,36 @@ module ts { } } - function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] { - return findReferences(fileName, position, findInStrings, findInComments); + function convertReferences(referenceSymbols: ReferencedSymbol[]): ReferenceEntry[]{ + if (!referenceSymbols) { + return undefined; + } + + let referenceEntries: ReferenceEntry[] = []; + for (let referenceSymbol of referenceSymbols) { + addRange(referenceEntries, referenceSymbol.references); + } + return referenceEntries; + } + + function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[]{ + var referencedSymbols = findReferencedSymbols(fileName, position, findInStrings, findInComments); + return convertReferences(referencedSymbols); } function getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[] { - return findReferences(fileName, position, /*findInStrings:*/ false, /*findInComments:*/ false); + var referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings:*/ false, /*findInComments:*/ false); + return convertReferences(referencedSymbols); } - function findReferences(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): ReferenceEntry[] { + function findReferences(fileName: string, position: number): ReferencedSymbol[]{ + var referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings:*/ false, /*findInComments:*/ false); + + // Only include referenced symbols that have a valid definition. + return filter(referencedSymbols, rs => !!rs.definition); + } + + function findReferencedSymbols(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): ReferencedSymbol[] { synchronizeHostData(); let sourceFile = getValidSourceFile(fileName); @@ -4181,14 +4207,14 @@ module ts { return getReferencesForNode(node, program.getSourceFiles(), /*searchOnlyInCurrentFile*/ false, findInStrings, findInComments); } - function getReferencesForNode(node: Node, sourceFiles: SourceFile[], searchOnlyInCurrentFile: boolean, findInStrings: boolean, findInComments: boolean): ReferenceEntry[] { + function getReferencesForNode(node: Node, sourceFiles: SourceFile[], searchOnlyInCurrentFile: boolean, findInStrings: boolean, findInComments: boolean): ReferencedSymbol[]{ // Labels if (isLabelName(node)) { if (isJumpStatementTarget(node)) { let 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, just return a set of one for the current node. - return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : [getReferenceEntryFromNode(node)]; + // the label is undefined and we have no results.. + return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : undefined; } else { // it is a label definition and not a target, search within the parent labeledStatement @@ -4208,9 +4234,8 @@ module ts { // Could not find a symbol e.g. unknown identifier if (!symbol) { - // Even if we did not find a symbol, we have an identifier, so there is at least - // one reference that we know of. return that instead of undefined. - return [getReferenceEntryFromNode(node)]; + // Can't have references to something that we have no symbol for. + return undefined; } let declarations = symbol.declarations; @@ -4220,7 +4245,7 @@ module ts { return undefined; } - let result: ReferenceEntry[]; + let result: ReferencedSymbol[]; // Compute the meaning from the location and the symbol it references let searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations); @@ -4232,15 +4257,18 @@ module ts { // otherwise we'll need to search globally (i.e. include each file). let scope = getSymbolScope(symbol); + // Maps from a symbol ID to the ReferencedSymbol entry in 'result'. + let symbolToIndex: number[] = []; + if (scope) { result = []; - getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result); + getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex); } else { if (searchOnlyInCurrentFile) { Debug.assert(sourceFiles.length === 1); result = []; - getReferencesInNode(sourceFiles[0], symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result); + getReferencesInNode(sourceFiles[0], symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex); } else { let internedName = getInternedName(symbol, node, declarations) @@ -4251,7 +4279,7 @@ module ts { if (lookUp(nameTable, internedName)) { result = result || []; - getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result); + getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex); } }); } @@ -4259,6 +4287,24 @@ module ts { return result; + function getDefinition(symbol: Symbol): DefinitionInfo { + let info = getSymbolDisplayPartsDocumentationAndSymbolKind(symbol, node.getSourceFile(), getContainerNode(node), typeInfoResolver, node); + let name = map(info.displayParts, p => p.text).join(""); + let declarations = symbol.declarations; + if (!declarations || declarations.length === 0) { + return undefined; + } + + return { + containerKind: "", + containerName: "", + name, + kind: info.symbolKind, + fileName: declarations[0].getSourceFile().fileName, + textSpan: createTextSpan(declarations[0].getStart(), 0) + }; + } + function isImportOrExportSpecifierName(location: Node): boolean { return location.parent && (location.parent.kind === SyntaxKind.ImportSpecifier || location.parent.kind === SyntaxKind.ExportSpecifier) && @@ -4416,8 +4462,8 @@ module ts { return positions; } - function getLabelReferencesInNode(container: Node, targetLabel: Identifier): ReferenceEntry[] { - let result: ReferenceEntry[] = []; + function getLabelReferencesInNode(container: Node, targetLabel: Identifier): ReferencedSymbol[] { + let references: ReferenceEntry[] = []; let sourceFile = container.getSourceFile(); let labelName = targetLabel.text; let possiblePositions = getPossibleSymbolReferencePositions(sourceFile, labelName, container.getStart(), container.getEnd()); @@ -4432,10 +4478,20 @@ module ts { // 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)) { - result.push(getReferenceEntryFromNode(node)); + references.push(getReferenceEntryFromNode(node)); } }); - return result; + + var definition: DefinitionInfo = { + containerKind: "", + containerName: "", + fileName: targetLabel.getSourceFile().fileName, + kind: ScriptElementKind.label, + name: labelName, + textSpan: createTextSpanFromBounds(targetLabel.getStart(), targetLabel.getEnd()) + } + + return [{ definition, references }]; } function isValidReferencePosition(node: Node, searchSymbolName: string): boolean { @@ -4475,7 +4531,9 @@ module ts { searchMeaning: SemanticMeaning, findInStrings: boolean, findInComments: boolean, - result: ReferenceEntry[]): void { + result: ReferencedSymbol[], + symbolToIndex: number[]): void { + let sourceFile = container.getSourceFile(); let tripleSlashDirectivePrefixRegex = /^\/\/\/\s*= 0) { - result.push(getReferenceEntryFromNode(referenceSymbolDeclaration.name)); + var referencedSymbol = getReferencedSymbol(shorthandValueSymbol); + referencedSymbol.references.push(getReferenceEntryFromNode(referenceSymbolDeclaration.name)); } } }); } + return; + + function getReferencedSymbol(symbol: Symbol): ReferencedSymbol { + var symbolId = getSymbolId(symbol); + var index = symbolToIndex[symbolId]; + if (index === undefined) { + index = result.length; + symbolToIndex[symbolId] = index; + + result.push({ + definition: getDefinition(symbol), + references: [] + }); + } + + return result[index]; + } + function isInString(position: number) { let token = getTokenAtPosition(sourceFile, position); return token && token.kind === SyntaxKind.StringLiteral && position > token.getStart(); @@ -4555,7 +4643,7 @@ module ts { } } - function getReferencesForSuperKeyword(superKeyword: Node): ReferenceEntry[] { + function getReferencesForSuperKeyword(superKeyword: Node): ReferencedSymbol[] { let searchSpaceNode = getSuperContainer(superKeyword, /*includeFunctions*/ false); if (!searchSpaceNode) { return undefined; @@ -4578,7 +4666,7 @@ module ts { return undefined; } - let result: ReferenceEntry[] = []; + let references: ReferenceEntry[] = []; let sourceFile = searchSpaceNode.getSourceFile(); let possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); @@ -4597,14 +4685,15 @@ module ts { // 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 && (NodeFlags.Static & container.flags) === staticFlag && container.parent.symbol === searchSpaceNode.symbol) { - result.push(getReferenceEntryFromNode(node)); + references.push(getReferenceEntryFromNode(node)); } }); - return result; + var definition = getDefinition(searchSpaceNode.symbol); + return [{ definition, references }]; } - function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: SourceFile[]): ReferenceEntry[] { + function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: SourceFile[]): ReferencedSymbol[] { let searchSpaceNode = getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false); // Whether 'this' occurs in a static context within a class. @@ -4639,22 +4728,32 @@ module ts { return undefined; } - let result: ReferenceEntry[] = []; + let references: ReferenceEntry[] = []; let possiblePositions: number[]; if (searchSpaceNode.kind === SyntaxKind.SourceFile) { forEach(sourceFiles, sourceFile => { possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", sourceFile.getStart(), sourceFile.getEnd()); - getThisReferencesInFile(sourceFile, sourceFile, possiblePositions, result); + getThisReferencesInFile(sourceFile, sourceFile, possiblePositions, references); }); } else { let sourceFile = searchSpaceNode.getSourceFile(); possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); - getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, result); + getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, references); } - return result; + return [{ + definition: { + containerKind: "", + containerName: "", + fileName: node.getSourceFile().fileName, + kind: ScriptElementKind.variableElement, + name: "this", + textSpan: createTextSpanFromBounds(node.getStart(), node.getEnd()) + }, + references: references + }]; function getThisReferencesInFile(sourceFile: SourceFile, searchSpaceNode: Node, possiblePositions: number[], result: ReferenceEntry[]): void { forEach(possiblePositions, position => { @@ -4777,16 +4876,18 @@ module ts { } } - function isRelatableToSearchSet(searchSymbols: Symbol[], referenceSymbol: Symbol, referenceLocation: Node): boolean { + function getRelatedSymbol(searchSymbols: Symbol[], referenceSymbol: Symbol, referenceLocation: Node): Symbol { if (searchSymbols.indexOf(referenceSymbol) >= 0) { - return true; + return referenceSymbol; } // If the reference symbol is an alias, check if what it is aliasing is one of the search // symbols. - if (isImportOrExportSpecifierImportSymbol(referenceSymbol) && - searchSymbols.indexOf(typeInfoResolver.getAliasedSymbol(referenceSymbol)) >= 0) { - return true; + if (isImportOrExportSpecifierImportSymbol(referenceSymbol)) { + var aliasedSymbol = typeInfoResolver.getAliasedSymbol(referenceSymbol); + if (searchSymbols.indexOf(aliasedSymbol) >= 0) { + return aliasedSymbol; + } } // If the reference location is in an object literal, try to get the contextual type for the @@ -4794,7 +4895,7 @@ module ts { // compare to our searchSymbol if (isNameOfPropertyAssignment(referenceLocation)) { return forEach(getPropertySymbolsFromContextualType(referenceLocation), contextualSymbol => { - return forEach(typeInfoResolver.getRootSymbols(contextualSymbol), s => searchSymbols.indexOf(s) >= 0); + return forEach(typeInfoResolver.getRootSymbols(contextualSymbol), s => searchSymbols.indexOf(s) >= 0 ? s : undefined); }); } @@ -4803,7 +4904,7 @@ module ts { return forEach(typeInfoResolver.getRootSymbols(referenceSymbol), rootSymbol => { // if it is in the list, then we are done if (searchSymbols.indexOf(rootSymbol) >= 0) { - return true; + return rootSymbol; } // Finally, try all properties with the same name in any type the containing type extended or implemented, and @@ -4811,10 +4912,10 @@ module ts { if (rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { let result: Symbol[] = []; getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result); - return forEach(result, s => searchSymbols.indexOf(s) >= 0); + return forEach(result, s => searchSymbols.indexOf(s) >= 0 ? s : undefined); } - return false; + return undefined; }); } @@ -5770,6 +5871,7 @@ module ts { getQuickInfoAtPosition, getDefinitionAtPosition, getReferencesAtPosition, + findReferences, getOccurrencesAtPosition, getNameOrDottedNameSpan, getBreakpointStatementAtPosition, diff --git a/src/services/shims.ts b/src/services/shims.ts index 63e3c9e23ae..adcec5ada2b 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -127,6 +127,12 @@ module ts { * { fileName: string; textSpan: { start: number; length: number}; isWriteAccess: boolean }[] */ getReferencesAtPosition(fileName: string, position: number): string; + + /** + * Returns a JSON-encoded value of the type: + * { definition: ; references: [] }[] + */ + findReferences(fileName: string, position: number): string; /** * Returns a JSON-encoded value of the type: @@ -555,11 +561,6 @@ module ts { /// GET REFERENCES - /** - * Return references to a symbol at the requested position. - * References are separated by "\n". - * Each reference is a "fileindex min lim" sub-string. - */ public getReferencesAtPosition(fileName: string, position: number): string { return this.forwardJSONCall( "getReferencesAtPosition('" + fileName + "', " + position + ")", @@ -568,6 +569,14 @@ module ts { }); } + public findReferences(fileName: string, position: number): string { + return this.forwardJSONCall( + "findReferences('" + fileName + "', " + position + ")", + () => { + return this.languageService.findReferences(fileName, position); + }); + } + public getOccurrencesAtPosition(fileName: string, position: number): string { return this.forwardJSONCall( "getOccurrencesAtPosition('" + fileName + "', " + position + ")", diff --git a/tests/baselines/reference/APISample_compile.js b/tests/baselines/reference/APISample_compile.js index 625c49177fd..31012de5380 100644 --- a/tests/baselines/reference/APISample_compile.js +++ b/tests/baselines/reference/APISample_compile.js @@ -1475,6 +1475,7 @@ declare module "typescript" { declare module "typescript" { /** The version of the TypeScript compiler release */ let version: string; + function findConfigFile(searchPath: string): string; function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost; function getPreEmitDiagnostics(program: Program): Diagnostic[]; function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string; @@ -1589,6 +1590,7 @@ declare module "typescript" { getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[]; getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[]; + findReferences(fileName: string, position: number): ReferencedSymbol[]; getNavigateToItems(searchValue: string, maxResultCount?: number): NavigateToItem[]; getNavigationBarItems(fileName: string): NavigationBarItem[]; getOutliningSpans(fileName: string): OutliningSpan[]; @@ -1675,6 +1677,10 @@ declare module "typescript" { containerKind: string; containerName: string; } + interface ReferencedSymbol { + definition: DefinitionInfo; + references: ReferenceEntry[]; + } enum SymbolDisplayPartKind { aliasName = 0, className = 1, diff --git a/tests/baselines/reference/APISample_compile.types b/tests/baselines/reference/APISample_compile.types index d22b4499391..383882b68b0 100644 --- a/tests/baselines/reference/APISample_compile.types +++ b/tests/baselines/reference/APISample_compile.types @@ -4739,6 +4739,10 @@ declare module "typescript" { let version: string; >version : string + function findConfigFile(searchPath: string): string; +>findConfigFile : (searchPath: string) => string +>searchPath : string + function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost; >createCompilerHost : (options: CompilerOptions, setParentNodes?: boolean) => CompilerHost >options : CompilerOptions @@ -5157,6 +5161,12 @@ declare module "typescript" { >position : number >ReferenceEntry : ReferenceEntry + findReferences(fileName: string, position: number): ReferencedSymbol[]; +>findReferences : (fileName: string, position: number) => ReferencedSymbol[] +>fileName : string +>position : number +>ReferencedSymbol : ReferencedSymbol + getNavigateToItems(searchValue: string, maxResultCount?: number): NavigateToItem[]; >getNavigateToItems : (searchValue: string, maxResultCount?: number) => NavigateToItem[] >searchValue : string @@ -5427,6 +5437,17 @@ declare module "typescript" { containerName: string; >containerName : string + } + interface ReferencedSymbol { +>ReferencedSymbol : ReferencedSymbol + + definition: DefinitionInfo; +>definition : DefinitionInfo +>DefinitionInfo : DefinitionInfo + + references: ReferenceEntry[]; +>references : ReferenceEntry[] +>ReferenceEntry : ReferenceEntry } enum SymbolDisplayPartKind { >SymbolDisplayPartKind : SymbolDisplayPartKind diff --git a/tests/baselines/reference/APISample_linter.js b/tests/baselines/reference/APISample_linter.js index 93dd106e65e..764814f664a 100644 --- a/tests/baselines/reference/APISample_linter.js +++ b/tests/baselines/reference/APISample_linter.js @@ -1506,6 +1506,7 @@ declare module "typescript" { declare module "typescript" { /** The version of the TypeScript compiler release */ let version: string; + function findConfigFile(searchPath: string): string; function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost; function getPreEmitDiagnostics(program: Program): Diagnostic[]; function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string; @@ -1620,6 +1621,7 @@ declare module "typescript" { getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[]; getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[]; + findReferences(fileName: string, position: number): ReferencedSymbol[]; getNavigateToItems(searchValue: string, maxResultCount?: number): NavigateToItem[]; getNavigationBarItems(fileName: string): NavigationBarItem[]; getOutliningSpans(fileName: string): OutliningSpan[]; @@ -1706,6 +1708,10 @@ declare module "typescript" { containerKind: string; containerName: string; } + interface ReferencedSymbol { + definition: DefinitionInfo; + references: ReferenceEntry[]; + } enum SymbolDisplayPartKind { aliasName = 0, className = 1, diff --git a/tests/baselines/reference/APISample_linter.types b/tests/baselines/reference/APISample_linter.types index 0a4577817e3..78989d5132a 100644 --- a/tests/baselines/reference/APISample_linter.types +++ b/tests/baselines/reference/APISample_linter.types @@ -4885,6 +4885,10 @@ declare module "typescript" { let version: string; >version : string + function findConfigFile(searchPath: string): string; +>findConfigFile : (searchPath: string) => string +>searchPath : string + function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost; >createCompilerHost : (options: CompilerOptions, setParentNodes?: boolean) => CompilerHost >options : CompilerOptions @@ -5303,6 +5307,12 @@ declare module "typescript" { >position : number >ReferenceEntry : ReferenceEntry + findReferences(fileName: string, position: number): ReferencedSymbol[]; +>findReferences : (fileName: string, position: number) => ReferencedSymbol[] +>fileName : string +>position : number +>ReferencedSymbol : ReferencedSymbol + getNavigateToItems(searchValue: string, maxResultCount?: number): NavigateToItem[]; >getNavigateToItems : (searchValue: string, maxResultCount?: number) => NavigateToItem[] >searchValue : string @@ -5573,6 +5583,17 @@ declare module "typescript" { containerName: string; >containerName : string + } + interface ReferencedSymbol { +>ReferencedSymbol : ReferencedSymbol + + definition: DefinitionInfo; +>definition : DefinitionInfo +>DefinitionInfo : DefinitionInfo + + references: ReferenceEntry[]; +>references : ReferenceEntry[] +>ReferenceEntry : ReferenceEntry } enum SymbolDisplayPartKind { >SymbolDisplayPartKind : SymbolDisplayPartKind diff --git a/tests/baselines/reference/APISample_transform.js b/tests/baselines/reference/APISample_transform.js index eb870ba15e3..a1acb80c773 100644 --- a/tests/baselines/reference/APISample_transform.js +++ b/tests/baselines/reference/APISample_transform.js @@ -1507,6 +1507,7 @@ declare module "typescript" { declare module "typescript" { /** The version of the TypeScript compiler release */ let version: string; + function findConfigFile(searchPath: string): string; function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost; function getPreEmitDiagnostics(program: Program): Diagnostic[]; function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string; @@ -1621,6 +1622,7 @@ declare module "typescript" { getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[]; getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[]; + findReferences(fileName: string, position: number): ReferencedSymbol[]; getNavigateToItems(searchValue: string, maxResultCount?: number): NavigateToItem[]; getNavigationBarItems(fileName: string): NavigationBarItem[]; getOutliningSpans(fileName: string): OutliningSpan[]; @@ -1707,6 +1709,10 @@ declare module "typescript" { containerKind: string; containerName: string; } + interface ReferencedSymbol { + definition: DefinitionInfo; + references: ReferenceEntry[]; + } enum SymbolDisplayPartKind { aliasName = 0, className = 1, diff --git a/tests/baselines/reference/APISample_transform.types b/tests/baselines/reference/APISample_transform.types index 6afd50403f2..3055eadbc7e 100644 --- a/tests/baselines/reference/APISample_transform.types +++ b/tests/baselines/reference/APISample_transform.types @@ -4835,6 +4835,10 @@ declare module "typescript" { let version: string; >version : string + function findConfigFile(searchPath: string): string; +>findConfigFile : (searchPath: string) => string +>searchPath : string + function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost; >createCompilerHost : (options: CompilerOptions, setParentNodes?: boolean) => CompilerHost >options : CompilerOptions @@ -5253,6 +5257,12 @@ declare module "typescript" { >position : number >ReferenceEntry : ReferenceEntry + findReferences(fileName: string, position: number): ReferencedSymbol[]; +>findReferences : (fileName: string, position: number) => ReferencedSymbol[] +>fileName : string +>position : number +>ReferencedSymbol : ReferencedSymbol + getNavigateToItems(searchValue: string, maxResultCount?: number): NavigateToItem[]; >getNavigateToItems : (searchValue: string, maxResultCount?: number) => NavigateToItem[] >searchValue : string @@ -5523,6 +5533,17 @@ declare module "typescript" { containerName: string; >containerName : string + } + interface ReferencedSymbol { +>ReferencedSymbol : ReferencedSymbol + + definition: DefinitionInfo; +>definition : DefinitionInfo +>DefinitionInfo : DefinitionInfo + + references: ReferenceEntry[]; +>references : ReferenceEntry[] +>ReferenceEntry : ReferenceEntry } enum SymbolDisplayPartKind { >SymbolDisplayPartKind : SymbolDisplayPartKind diff --git a/tests/baselines/reference/APISample_watcher.js b/tests/baselines/reference/APISample_watcher.js index a7ee033d855..830639c9d22 100644 --- a/tests/baselines/reference/APISample_watcher.js +++ b/tests/baselines/reference/APISample_watcher.js @@ -1544,6 +1544,7 @@ declare module "typescript" { declare module "typescript" { /** The version of the TypeScript compiler release */ let version: string; + function findConfigFile(searchPath: string): string; function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost; function getPreEmitDiagnostics(program: Program): Diagnostic[]; function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string; @@ -1658,6 +1659,7 @@ declare module "typescript" { getDefinitionAtPosition(fileName: string, position: number): DefinitionInfo[]; getReferencesAtPosition(fileName: string, position: number): ReferenceEntry[]; getOccurrencesAtPosition(fileName: string, position: number): ReferenceEntry[]; + findReferences(fileName: string, position: number): ReferencedSymbol[]; getNavigateToItems(searchValue: string, maxResultCount?: number): NavigateToItem[]; getNavigationBarItems(fileName: string): NavigationBarItem[]; getOutliningSpans(fileName: string): OutliningSpan[]; @@ -1744,6 +1746,10 @@ declare module "typescript" { containerKind: string; containerName: string; } + interface ReferencedSymbol { + definition: DefinitionInfo; + references: ReferenceEntry[]; + } enum SymbolDisplayPartKind { aliasName = 0, className = 1, diff --git a/tests/baselines/reference/APISample_watcher.types b/tests/baselines/reference/APISample_watcher.types index 30e97cc5ba2..6b30746938f 100644 --- a/tests/baselines/reference/APISample_watcher.types +++ b/tests/baselines/reference/APISample_watcher.types @@ -5008,6 +5008,10 @@ declare module "typescript" { let version: string; >version : string + function findConfigFile(searchPath: string): string; +>findConfigFile : (searchPath: string) => string +>searchPath : string + function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost; >createCompilerHost : (options: CompilerOptions, setParentNodes?: boolean) => CompilerHost >options : CompilerOptions @@ -5426,6 +5430,12 @@ declare module "typescript" { >position : number >ReferenceEntry : ReferenceEntry + findReferences(fileName: string, position: number): ReferencedSymbol[]; +>findReferences : (fileName: string, position: number) => ReferencedSymbol[] +>fileName : string +>position : number +>ReferencedSymbol : ReferencedSymbol + getNavigateToItems(searchValue: string, maxResultCount?: number): NavigateToItem[]; >getNavigateToItems : (searchValue: string, maxResultCount?: number) => NavigateToItem[] >searchValue : string @@ -5696,6 +5706,17 @@ declare module "typescript" { containerName: string; >containerName : string + } + interface ReferencedSymbol { +>ReferencedSymbol : ReferencedSymbol + + definition: DefinitionInfo; +>definition : DefinitionInfo +>DefinitionInfo : DefinitionInfo + + references: ReferenceEntry[]; +>references : ReferenceEntry[] +>ReferenceEntry : ReferenceEntry } enum SymbolDisplayPartKind { >SymbolDisplayPartKind : SymbolDisplayPartKind diff --git a/tests/cases/fourslash/findAllRefsInsideWithBlock.ts b/tests/cases/fourslash/findAllRefsInsideWithBlock.ts index 394d30d89d3..fc8a94eaa2d 100644 --- a/tests/cases/fourslash/findAllRefsInsideWithBlock.ts +++ b/tests/cases/fourslash/findAllRefsInsideWithBlock.ts @@ -13,4 +13,4 @@ goTo.marker('1'); verify.referencesCountIs(3); goTo.marker('2'); -verify.referencesCountIs(1); \ No newline at end of file +verify.referencesCountIs(0); \ No newline at end of file diff --git a/tests/cases/fourslash/getOccurrencesOfUndefinedSymbol.ts b/tests/cases/fourslash/getOccurrencesOfUndefinedSymbol.ts index 4893a6079d1..96c3cdc2e39 100644 --- a/tests/cases/fourslash/getOccurrencesOfUndefinedSymbol.ts +++ b/tests/cases/fourslash/getOccurrencesOfUndefinedSymbol.ts @@ -17,4 +17,4 @@ // "any" should not be highlighted goTo.marker(); -verify.occurrencesAtPositionCount(1); +verify.occurrencesAtPositionCount(0); diff --git a/tests/cases/fourslash/getOccurrencesSwitchCaseDefaultBroken.ts b/tests/cases/fourslash/getOccurrencesSwitchCaseDefaultBroken.ts index 018280a4032..25ee54f8115 100644 --- a/tests/cases/fourslash/getOccurrencesSwitchCaseDefaultBroken.ts +++ b/tests/cases/fourslash/getOccurrencesSwitchCaseDefaultBroken.ts @@ -39,8 +39,6 @@ for (var i = 1; i <= test.markers().length; i++) { verify.occurrencesAtPositionCount(8); break; case 4: - case 5: - case 8: verify.occurrencesAtPositionCount(1); break; case 6: @@ -48,6 +46,8 @@ for (var i = 1; i <= test.markers().length; i++) { case 9: verify.occurrencesAtPositionCount(8); break; + case 5: + case 8: case 10: case 11: case 12: diff --git a/tests/cases/fourslash/getOccurrencesThisNegatives2.ts b/tests/cases/fourslash/getOccurrencesThisNegatives2.ts index 65fb37d09b4..0a8b5860feb 100644 --- a/tests/cases/fourslash/getOccurrencesThisNegatives2.ts +++ b/tests/cases/fourslash/getOccurrencesThisNegatives2.ts @@ -143,5 +143,5 @@ test.markers().forEach(m => { goTo.position(m.position, m.fileName) - verify.occurrencesAtPositionCount(1); + verify.occurrencesAtPositionCount(0); }); diff --git a/tests/cases/fourslash/getOccurrencesTryCatchFinallyBroken.ts b/tests/cases/fourslash/getOccurrencesTryCatchFinallyBroken.ts index c866ed96398..01a202a677c 100644 --- a/tests/cases/fourslash/getOccurrencesTryCatchFinallyBroken.ts +++ b/tests/cases/fourslash/getOccurrencesTryCatchFinallyBroken.ts @@ -36,6 +36,8 @@ for (var i = 1; i <= test.markers().length; i++) { switch (i) { case 1: + verify.occurrencesAtPositionCount(0); + break; case 2: case 3: verify.occurrencesAtPositionCount(1); diff --git a/tests/cases/fourslash/getSemanticDiagnosticForDeclaration1.ts b/tests/cases/fourslash/getSemanticDiagnosticForDeclaration1.ts new file mode 100644 index 00000000000..13a2dccfd26 --- /dev/null +++ b/tests/cases/fourslash/getSemanticDiagnosticForDeclaration1.ts @@ -0,0 +1,9 @@ +/// + +// @declaration: true +// @Filename: File.d.ts +//// declare var v: string; + +verify.numberOfErrorsInCurrentFile(0); + + diff --git a/tests/cases/fourslash/localGetReferences.ts b/tests/cases/fourslash/localGetReferences.ts index 6d5f541dd51..e5873efeeb4 100644 --- a/tests/cases/fourslash/localGetReferences.ts +++ b/tests/cases/fourslash/localGetReferences.ts @@ -223,7 +223,7 @@ verify.referencesCountIs(7); // References to unresolved symbol. goTo.marker("12"); -verify.referencesCountIs(1); +verify.referencesCountIs(0); // References to no context. goTo.marker("13"); diff --git a/tests/cases/fourslash/referencesForIllegalAssignment.ts b/tests/cases/fourslash/referencesForIllegalAssignment.ts index 81a45f64153..403bf0432a7 100644 --- a/tests/cases/fourslash/referencesForIllegalAssignment.ts +++ b/tests/cases/fourslash/referencesForIllegalAssignment.ts @@ -6,10 +6,10 @@ ////ba/*4*/r = b/*5*/ar + 1; goTo.marker("1"); -verify.referencesCountIs(1); +verify.referencesCountIs(0); goTo.marker("2"); -verify.referencesCountIs(1); +verify.referencesCountIs(0); goTo.marker("3"); verify.referencesCountIs(3); diff --git a/tests/cases/fourslash/referencesForIndexProperty2.ts b/tests/cases/fourslash/referencesForIndexProperty2.ts index fd9cf0e7183..9dcba3163c6 100644 --- a/tests/cases/fourslash/referencesForIndexProperty2.ts +++ b/tests/cases/fourslash/referencesForIndexProperty2.ts @@ -6,4 +6,4 @@ ////a[/*1*/"blah"]; goTo.marker("1"); -verify.referencesCountIs(1); \ No newline at end of file +verify.referencesCountIs(0); \ No newline at end of file diff --git a/tests/cases/fourslash/referencesForLabel2.ts b/tests/cases/fourslash/referencesForLabel2.ts index 054ce562864..ccb441d60b9 100644 --- a/tests/cases/fourslash/referencesForLabel2.ts +++ b/tests/cases/fourslash/referencesForLabel2.ts @@ -9,4 +9,4 @@ ////} goTo.marker("1"); -verify.referencesCountIs(1); +verify.referencesCountIs(0);