Skip to content

Commit ab05b75

Browse files
committed
Merge pull request #326 from Microsoft/getDefinition
Wire getDefinitionAtPosition using the new compiler implementation
2 parents 017a76b + 2ae1432 commit ab05b75

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+727
-329
lines changed

src/compiler/checker.ts

Lines changed: 78 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,13 @@ module ts {
8282
getTypeOfSymbol: getTypeOfSymbol,
8383
getDeclaredTypeOfSymbol: getDeclaredTypeOfSymbol,
8484
getPropertiesOfType: getPropertiesOfType,
85+
getPropertyOfType: getPropertyOfType,
8586
getSignaturesOfType: getSignaturesOfType,
8687
getIndexTypeOfType: getIndexTypeOfType,
8788
getReturnTypeOfSignature: getReturnTypeOfSignature,
8889
resolveEntityName: resolveEntityName,
8990
getSymbolsInScope: getSymbolsInScope,
90-
getSymbolOfIdentifier: getSymbolOfIdentifier,
91+
getSymbolInfo: getSymbolInfo,
9192
getTypeOfExpression: getTypeOfExpression,
9293
typeToString: typeToString,
9394
symbolToString: symbolToString,
@@ -6338,9 +6339,9 @@ module ts {
63386339
}
63396340

63406341
// True if the given identifier is part of a type reference
6341-
function isTypeReferenceIdentifier(identifier: Identifier): boolean {
6342-
var node: Node = identifier;
6343-
if (node.parent && node.parent.kind === SyntaxKind.QualifiedName) node = node.parent;
6342+
function isTypeReferenceIdentifier(entityName: EntityName): boolean {
6343+
var node: Node = entityName;
6344+
while (node.parent && node.parent.kind === SyntaxKind.QualifiedName) node = node.parent;
63446345
return node.parent && node.parent.kind === SyntaxKind.TypeReference;
63456346
}
63466347

@@ -6404,39 +6405,96 @@ module ts {
64046405
return false;
64056406
}
64066407

6407-
function isRightSideOfQualifiedName(node: Node) {
6408+
function isRightSideOfQualifiedNameOrPropertyAccess(node: Node) {
64086409
return (node.parent.kind === SyntaxKind.QualifiedName || node.parent.kind === SyntaxKind.PropertyAccess) &&
64096410
(<QualifiedName>node.parent).right === node;
64106411
}
64116412

64126413
function getSymbolOfIdentifier(identifier: Identifier) {
6413-
if (isExpression(identifier)) {
6414-
if (isRightSideOfQualifiedName(identifier)) {
6415-
var node = <QualifiedName>identifier.parent;
6416-
var symbol = getNodeLinks(node).resolvedSymbol;
6414+
if (isDeclarationIdentifier(identifier)) {
6415+
return getSymbolOfNode(identifier.parent);
6416+
}
6417+
6418+
var entityName: Node = identifier;
6419+
while (isRightSideOfQualifiedNameOrPropertyAccess(entityName))
6420+
entityName = entityName.parent;
6421+
6422+
if (isExpression(entityName)) {
6423+
if (entityName.kind === SyntaxKind.Identifier) {
6424+
// Include Import in the meaning, this ensures that we do not follow aliases to where they point and instead
6425+
// return the alias symbol.
6426+
var meaning: SymbolFlags = SymbolFlags.Value | SymbolFlags.Import;
6427+
return resolveEntityName(entityName, entityName, meaning);
6428+
}
6429+
else if (entityName.kind === SyntaxKind.QualifiedName || entityName.kind === SyntaxKind.PropertyAccess) {
6430+
var symbol = getNodeLinks(entityName).resolvedSymbol;
64176431
if (!symbol) {
6418-
checkPropertyAccess(node);
6432+
checkPropertyAccess(<PropertyAccess>entityName);
64196433
}
6420-
return getNodeLinks(node).resolvedSymbol;
6434+
return getNodeLinks(entityName).resolvedSymbol;
6435+
}
6436+
else {
6437+
// Missing identifier
6438+
return;
64216439
}
6422-
return resolveEntityName(identifier, identifier, SymbolFlags.Value);
6423-
}
6424-
if (isDeclarationIdentifier(identifier)) {
6425-
return getSymbolOfNode(identifier.parent);
64266440
}
6427-
if (isTypeReferenceIdentifier(identifier)) {
6428-
var entityName = isRightSideOfQualifiedName(identifier) ? identifier.parent : identifier;
6441+
else if (isTypeReferenceIdentifier(entityName)) {
64296442
var meaning = entityName.parent.kind === SyntaxKind.TypeReference ? SymbolFlags.Type : SymbolFlags.Namespace;
6443+
// Include Import in the meaning, this ensures that we do not follow aliases to where they point and instead
6444+
// return the alias symbol.
6445+
meaning |= SymbolFlags.Import;
64306446
return resolveEntityName(entityName, entityName, meaning);
64316447
}
64326448
}
64336449

6450+
function getSymbolInfo(node: Node) {
6451+
switch (node.kind) {
6452+
case SyntaxKind.Identifier:
6453+
return getSymbolOfIdentifier(<Identifier>node);
6454+
6455+
case SyntaxKind.ThisKeyword:
6456+
case SyntaxKind.SuperKeyword:
6457+
var type = checkExpression(node);
6458+
return type.symbol;
6459+
6460+
case SyntaxKind.ConstructorKeyword:
6461+
// constructor keyword for an overload, should take us to the definition if it exist
6462+
var constructorDeclaration = node.parent;
6463+
if (constructorDeclaration && constructorDeclaration.kind === SyntaxKind.Constructor) {
6464+
return (<ClassDeclaration>constructorDeclaration.parent).symbol;
6465+
}
6466+
return undefined;
6467+
6468+
case SyntaxKind.StringLiteral:
6469+
// Property access
6470+
if (node.parent.kind === SyntaxKind.IndexedAccess && (<IndexedAccess>node.parent).index === node) {
6471+
var objectType = checkExpression((<IndexedAccess>node.parent).object);
6472+
if (objectType === unknownType) return undefined;
6473+
var apparentType = getApparentType(objectType);
6474+
if (<Type>apparentType === unknownType) return undefined;
6475+
return getPropertyOfApparentType(apparentType, (<LiteralExpression>node).text);
6476+
}
6477+
// External module name in an import declaration
6478+
else if (node.parent.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node.parent).externalModuleName === node) {
6479+
var importSymbol = getSymbolOfNode(node.parent);
6480+
var moduleType = getTypeOfSymbol(importSymbol);
6481+
return moduleType ? moduleType.symbol : undefined;
6482+
}
6483+
// External module name in an ambient declaration
6484+
else if (node.parent.kind === SyntaxKind.ModuleDeclaration) {
6485+
return getSymbolOfNode(node.parent);
6486+
}
6487+
break;
6488+
}
6489+
return undefined;
6490+
}
6491+
64346492
function getTypeOfExpression(node: Node) {
64356493
if (isExpression(node)) {
6436-
while (isRightSideOfQualifiedName(node)) {
6494+
while (isRightSideOfQualifiedNameOrPropertyAccess(node)) {
64376495
node = node.parent;
64386496
}
6439-
return <Type>getApparentType(checkExpression(node));
6497+
return <Type>getApparentType(checkExpression(node));
64406498
}
64416499
return unknownType;
64426500
}
@@ -6477,6 +6535,7 @@ module ts {
64776535
return getPropertiesOfType(<Type>apparentType);
64786536
}
64796537
}
6538+
64806539
// Emitter support
64816540

64826541
function isExternalModuleSymbol(symbol: Symbol): boolean {

src/compiler/parser.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ module ts {
417417
nodeIsNestedInLabel(label: Identifier, requireIterationStatement: boolean, stopAtFunctionBoundary: boolean): ControlBlockContext;
418418
}
419419

420-
export function createSourceFile(filename: string, sourceText: string, languageVersion: ScriptTarget): SourceFile {
420+
export function createSourceFile(filename: string, sourceText: string, languageVersion: ScriptTarget, byteOrderMark: ByteOrderMark, version: number = 0, isOpen: boolean = false): SourceFile {
421421
var file: SourceFile;
422422
var scanner: Scanner;
423423
var token: SyntaxKind;
@@ -3523,6 +3523,10 @@ module ts {
35233523
file.externalModuleIndicator = getExternalModuleIndicator();
35243524
file.nodeCount = nodeCount;
35253525
file.identifierCount = identifierCount;
3526+
file.version = version;
3527+
file.byteOrderMark = byteOrderMark;
3528+
file.isOpen = isOpen;
3529+
file.languageVersion = languageVersion;
35263530
return file;
35273531
}
35283532

src/compiler/tc.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ module ts {
135135
}
136136
text = "";
137137
}
138-
return text !== undefined ? createSourceFile(filename, text, languageVersion) : undefined;
138+
return text !== undefined ? createSourceFile(filename, text, languageVersion, ByteOrderMark.None) : undefined;
139139
}
140140

141141
function writeFile(fileName: string, data: string, onError?: (message: string) => void) {

src/compiler/types.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,10 @@ module ts {
525525
nodeCount: number;
526526
identifierCount: number;
527527
symbolCount: number;
528+
byteOrderMark: ByteOrderMark;
529+
isOpen: boolean;
530+
version: number;
531+
languageVersion: ScriptTarget;
528532
}
529533

530534
export interface Program {
@@ -595,12 +599,13 @@ module ts {
595599
getTypeOfSymbol(symbol: Symbol): Type;
596600
getDeclaredTypeOfSymbol(symbol: Symbol): Type;
597601
getPropertiesOfType(type: Type): Symbol[];
602+
getPropertyOfType(type: Type, propetyName: string): Symbol;
598603
getSignaturesOfType(type: Type, kind: SignatureKind): Signature[];
599604
getIndexTypeOfType(type: Type, kind: IndexKind): Type;
600605
getReturnTypeOfSignature(signature: Signature): Type;
601606
resolveEntityName(location: Node, name: EntityName, meaning: SymbolFlags): Symbol;
602607
getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];
603-
getSymbolOfIdentifier(identifier: Identifier): Symbol;
608+
getSymbolInfo(node: Node): Symbol;
604609
getTypeOfExpression(node: Expression, contextualType?: Type, contextualMapper?: TypeMapper): Type;
605610
typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
606611
symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string;

src/harness/fourslash.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1895,12 +1895,12 @@ module FourSlash {
18951895
var result = '';
18961896
var fourslashFilename = 'fourslash.ts';
18971897
var tsFn = 'tests/cases/fourslash/' + fourslashFilename;
1898-
fourslashSourceFile = fourslashSourceFile || ts.createSourceFile(tsFn, Harness.IO.readFile(tsFn), ts.ScriptTarget.ES5);
1899-
libdtsSourceFile = libdtsSourceFile || ts.createSourceFile('lib.d.ts', Harness.Compiler.libTextMinimal, ts.ScriptTarget.ES3);
1898+
fourslashSourceFile = fourslashSourceFile || ts.createSourceFile(tsFn, Harness.IO.readFile(tsFn), ts.ScriptTarget.ES5, ts.ByteOrderMark.None, /*version*/ 0, /*isOpen*/ false);
1899+
libdtsSourceFile = libdtsSourceFile || ts.createSourceFile('lib.d.ts', Harness.Compiler.libTextMinimal, ts.ScriptTarget.ES3, ts.ByteOrderMark.None, /*version*/ 0, /*isOpen*/ false);
19001900

19011901
var files: { [filename: string]: ts.SourceFile; } = {};
19021902
files[fourslashFilename] = fourslashSourceFile;
1903-
files[fileName] = ts.createSourceFile(fileName, content, ts.ScriptTarget.ES5);
1903+
files[fileName] = ts.createSourceFile(fileName, content, ts.ScriptTarget.ES5, ts.ByteOrderMark.None, /*version*/ 0, /*isOpen*/ false);
19041904
files['lib.d.ts'] = libdtsSourceFile;
19051905

19061906
var host = Harness.Compiler.createCompilerHost(files, (fn, contents) => result = contents);

src/harness/harness.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ module Harness {
544544
} else {
545545
var lib = 'lib.d.ts';
546546
if (fn.substr(fn.length - lib.length) === lib) {
547-
return filemap[fn] = ts.createSourceFile('lib.d.ts', libTextMinimal, languageVersion);
547+
return filemap[fn] = ts.createSourceFile('lib.d.ts', libTextMinimal, languageVersion, ts.ByteOrderMark.None);
548548
}
549549
// Don't throw here -- the compiler might be looking for a test that actually doesn't exist as part of the TC
550550
return null;
@@ -720,7 +720,7 @@ module Harness {
720720
var filemap: { [name: string]: ts.SourceFile; } = {};
721721
var register = (file: { unitName: string; content: string; }) => {
722722
var filename = Path.switchToForwardSlashes(file.unitName);
723-
filemap[filename] = ts.createSourceFile(filename, file.content, options.target);
723+
filemap[filename] = ts.createSourceFile(filename, file.content, options.target, ts.ByteOrderMark.None);
724724
};
725725
inputFiles.forEach(register);
726726
otherFiles.forEach(register);

src/harness/harnessLanguageService.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,20 +147,19 @@ module Harness.LanguageService {
147147
scriptSnapshot: TypeScript.IScriptSnapshot,
148148
byteOrderMark: ts.ByteOrderMark,
149149
version: number,
150-
isOpen: boolean,
151-
referencedFiles: string[]= []): ts.Document {
152-
return ts.createDocument(compilationSettings, fileName, scriptSnapshot, byteOrderMark, version, isOpen, referencedFiles);
150+
isOpen: boolean): ts.SourceFile {
151+
return ts.createSourceFile(fileName, scriptSnapshot.getText(0, scriptSnapshot.getLength()), compilationSettings.target, byteOrderMark, version, isOpen);
153152
}
154153

155154
public updateDocument(
156-
document: ts.Document,
155+
document: ts.SourceFile,
157156
fileName: string,
158157
compilationSettings: ts.CompilerOptions,
159158
scriptSnapshot: TypeScript.IScriptSnapshot,
160159
version: number,
161160
isOpen: boolean,
162161
textChangeRange: TypeScript.TextChangeRange
163-
): ts.Document {
162+
): ts.SourceFile {
164163
return document.update(scriptSnapshot, version, isOpen, textChangeRange);
165164
}
166165

src/harness/projectsRunner.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ class ProjectRunner extends RunnerBase {
139139
function getSourceFile(filename: string, languageVersion: ts.ScriptTarget): ts.SourceFile {
140140
var sourceFile: ts.SourceFile = undefined;
141141
if (filename === 'lib.d.ts') {
142-
sourceFile = ts.createSourceFile('lib.d.ts', Harness.Compiler.libTextMinimal, languageVersion);
142+
sourceFile = ts.createSourceFile('lib.d.ts', Harness.Compiler.libTextMinimal, languageVersion, ts.ByteOrderMark.None);
143143
}
144144
else {
145145
assert.isTrue(!ts.filter(readInputFiles, sourceFile => sourceFile.filename == filename).length, "Compiler trying to read same file again: " + filename);
@@ -154,7 +154,7 @@ class ProjectRunner extends RunnerBase {
154154
}
155155

156156
if (text !== undefined) {
157-
sourceFile = ts.createSourceFile(filename, text, languageVersion)
157+
sourceFile = ts.createSourceFile(filename, text, languageVersion, ts.ByteOrderMark.None);
158158
}
159159
}
160160

src/harness/rwcRunner.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ module RWC {
107107
catch (e) {
108108
// Leave fileContents undefined;
109109
}
110-
return ts.createSourceFile(fileName, fileContents, languageVersion);
110+
return ts.createSourceFile(fileName, fileContents, languageVersion, ts.ByteOrderMark.None);
111111
},
112112
getDefaultLibFilename: () => libPath,
113113
writeFile: (fn, contents) => emitterIOHost.writeFile(fn, contents, false),

0 commit comments

Comments
 (0)