Skip to content

Wire getReferences to use the new compiler #473

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 52 commits into from
Aug 29, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
8151f5e
extract helpers
mhegazy Aug 9, 2014
5e9b2b5
enbale getReferencesAtPosition
mhegazy Aug 12, 2014
32a5984
expose utility functions
mhegazy Aug 12, 2014
6a92b21
enable reference tests
mhegazy Aug 13, 2014
f45ab42
Enable some more tests
mhegazy Aug 13, 2014
f84d2af
disable resolution for now
mhegazy Aug 13, 2014
901e8a8
Add basic getReferences implementation
mhegazy Aug 13, 2014
69c653d
add some debug methods
mhegazy Aug 13, 2014
bfd1334
Handel getRefrences for labels
mhegazy Aug 13, 2014
fa1033a
add support for getReferences on property string index access
mhegazy Aug 13, 2014
55d0021
support getReferences on object literals
mhegazy Aug 13, 2014
d419982
Support getReferences on contextually typed object literal properties
mhegazy Aug 14, 2014
922d6d6
support getReferences on properties and index access wiht numeric and…
mhegazy Aug 14, 2014
7f53783
add new test for getReferences on enums
mhegazy Aug 14, 2014
f812297
include inherited properties from base classes and interfaces in getR…
mhegazy Aug 14, 2014
3251b7e
Support filtering references based on meaning
mhegazy Aug 18, 2014
2d4cec4
Updates after merge from master
mhegazy Aug 18, 2014
55512fa
Use new tree to get Bloom filters
mhegazy Aug 20, 2014
978c2ef
Fix getReferences for labels
mhegazy Aug 20, 2014
74518a9
respond to code review comments
mhegazy Aug 21, 2014
e0ffc47
Merge branch 'master' into getReferences
mhegazy Aug 21, 2014
bbeeb8d
update getSymbolInfo
mhegazy Aug 21, 2014
6965a06
Support getReferences on rightside of export assignment and import st…
mhegazy Aug 21, 2014
dbf9e47
use isDeclarationOrFunctionExpressionOrCatchVariableName instead of i…
mhegazy Aug 21, 2014
fefe2fb
Implement getScope
mhegazy Aug 22, 2014
c741e26
Support external module names correctelly
mhegazy Aug 23, 2014
8fcc8b2
Ensure range for string literal references are within the quotes to e…
mhegazy Aug 23, 2014
6953794
remove bloom filters
mhegazy Aug 23, 2014
892baf0
use Identifiers list from the parser to filter getReferences instead …
mhegazy Aug 23, 2014
5c1b245
Initial work on getOccurrencesAtPosition.
DanielRosenwasser Aug 25, 2014
aef859f
Merge branch 'master' into getReferences
DanielRosenwasser Aug 25, 2014
144eb8d
Added trivial syntax case.
DanielRosenwasser Aug 25, 2014
f948f5d
Re-added fourslash tests, corrected failures.
DanielRosenwasser Aug 26, 2014
e851e4b
Removed unused method.
DanielRosenwasser Aug 26, 2014
3c97210
add new unit test for used and unused imports
mhegazy Aug 26, 2014
5d15cd2
Beginning special casing for getOccurrencesAtPosition.
DanielRosenwasser Aug 26, 2014
558be4e
Implemented getOccsAtPos for try-catch-finally.
DanielRosenwasser Aug 26, 2014
1f77198
Made getOccs more resilient.
DanielRosenwasser Aug 26, 2014
8ab4df0
Added tests.
DanielRosenwasser Aug 26, 2014
88f37e5
Support for switch/case/default/break in getOccs
DanielRosenwasser Aug 27, 2014
3825c9b
Handled function boundaries.
DanielRosenwasser Aug 27, 2014
232e513
Moved null-guards to appropriate places, added helpers.
DanielRosenwasser Aug 27, 2014
0f9c1ad
Merge branch 'master' into getReferences
mhegazy Aug 27, 2014
50d0cdc
Better coverage against function boundaries.
DanielRosenwasser Aug 27, 2014
ea613fd
Replaced ES5 functions with analogous core.ts ones.
DanielRosenwasser Aug 27, 2014
04456a2
Made 'isAnyFunction' more exhaustive as it should be.
DanielRosenwasser Aug 27, 2014
0ce39a3
Addressed CR feedback.
DanielRosenwasser Aug 28, 2014
5b7da99
Update type baselines
mhegazy Aug 28, 2014
fd93a3b
What's in a name anyhow?
DanielRosenwasser Aug 28, 2014
813f28d
Removed assertion.
DanielRosenwasser Aug 28, 2014
41d8d6c
Merge pull request #549 from Microsoft/getOccurrences_switchCaseDefault
DanielRosenwasser Aug 28, 2014
dc0560a
Merge branch 'master' into getReferences
mhegazy Aug 29, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 44 additions & 66 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ module ts {
var nextNodeId = 1;
var nextMergeId = 1;

export function getDeclarationOfKind(symbol: Symbol, kind: SyntaxKind): Declaration {
var declarations = symbol.declarations;
for (var i = 0; i < declarations.length; i++) {
var declaration = declarations[i];
if (declaration.kind === kind) {
return declaration;
}
}

return undefined;
}

/// fullTypeCheck denotes if this instance of the typechecker will be used to get semantic diagnostics.
/// If fullTypeCheck === true - then typechecker should do every possible check to produce all errors
/// If fullTypeCheck === false - typechecker can shortcut and skip checks that only produce errors.
Expand Down Expand Up @@ -49,7 +61,9 @@ module ts {
getApparentType: getApparentType,
typeToString: typeToString,
symbolToString: symbolToString,
getAugmentedPropertiesOfApparentType: getAugmentedPropertiesOfApparentType
getAugmentedPropertiesOfApparentType: getAugmentedPropertiesOfApparentType,
getRootSymbol: getRootSymbol,
getContextualType: getContextualType
};

var undefinedSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "undefined");
Expand Down Expand Up @@ -568,18 +582,6 @@ module ts {
return false;
}

function getDeclarationOfKind(symbol: Symbol, kind: SyntaxKind): Declaration {
var declarations = symbol.declarations;
for (var i = 0; i < declarations.length; i++) {
var declaration = declarations[i];
if (declaration.kind === kind) {
return declaration;
}
}

return undefined;
}

function findConstructorDeclaration(node: ClassDeclaration): ConstructorDeclaration {
var members = node.members;
for (var i = 0; i < members.length; i++) {
Expand Down Expand Up @@ -3148,6 +3150,7 @@ module ts {
symbol.declarations = p.declarations;
symbol.parent = p.parent;
symbol.type = widenedTypes[index++];
symbol.target = p;
if (p.valueDeclaration) symbol.valueDeclaration = p.valueDeclaration;
members[symbol.name] = symbol;
});
Expand Down Expand Up @@ -3821,6 +3824,7 @@ module ts {
prop.parent = member.parent;
if (member.valueDeclaration) prop.valueDeclaration = member.valueDeclaration;
prop.type = type;
prop.target = member;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth commenting why it is transient

member = prop;
}
else {
Expand Down Expand Up @@ -6584,24 +6588,6 @@ module ts {
(<Declaration>name.parent).name === name;
}

// True if the given identifier, string literal, or number literal is the name of a declaration node
function isDeclarationOrFunctionExpressionOrCatchVariableName(name: Node): boolean {
if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) {
return false;
}

var parent = name.parent;
if (isDeclaration(parent) || parent.kind === SyntaxKind.FunctionExpression) {
return (<Declaration>parent).name === name;
}

if (parent.kind === SyntaxKind.CatchBlock) {
return (<CatchBlock>parent).variable === name;
}

return false;
}

function isTypeDeclaration(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.TypeParameter:
Expand All @@ -6612,28 +6598,6 @@ module ts {
}
}

function isDeclaration(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.TypeParameter:
case SyntaxKind.Parameter:
case SyntaxKind.VariableDeclaration:
case SyntaxKind.Property:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.EnumMember:
case SyntaxKind.Method:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ImportDeclaration:
return true;
}
return false;
}

// True if the given identifier is part of a type reference
function isTypeReferenceIdentifier(entityName: EntityName): boolean {
var node: Node = entityName;
Expand Down Expand Up @@ -6852,6 +6816,17 @@ module ts {
}

function getSymbolInfo(node: Node) {
if (isDeclarationOrFunctionExpressionOrCatchVariableName(node)) {
// This is a declaration, call getSymbolOfNode
return getSymbolOfNode(node.parent);
}

if (node.kind === SyntaxKind.Identifier && isInRightSideOfImportOrExportAssignment(node)) {
return node.parent.kind === SyntaxKind.ExportAssignment
? getSymbolOfEntityName(<Identifier>node)
: getSymbolOfPartOfRightHandSideOfImport(node);
}

switch (node.kind) {
case SyntaxKind.Identifier:
case SyntaxKind.PropertyAccess:
Expand All @@ -6862,7 +6837,7 @@ module ts {
case SyntaxKind.SuperKeyword:
var type = checkExpression(node);
return type.symbol;

case SyntaxKind.ConstructorKeyword:
// constructor keyword for an overload, should take us to the definition if it exist
var constructorDeclaration = node.parent;
Expand All @@ -6872,23 +6847,22 @@ module ts {
return undefined;

case SyntaxKind.StringLiteral:
// Property access
if (node.parent.kind === SyntaxKind.IndexedAccess && (<IndexedAccess>node.parent).index === node) {
var objectType = checkExpression((<IndexedAccess>node.parent).object);
if (objectType === unknownType) return undefined;
var apparentType = getApparentType(objectType);
if (<Type>apparentType === unknownType) return undefined;
return getPropertyOfApparentType(apparentType, (<LiteralExpression>node).text);
}
// External module name in an import declaration
else if (node.parent.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node.parent).externalModuleName === node) {
if (node.parent.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node.parent).externalModuleName === node) {
var importSymbol = getSymbolOfNode(node.parent);
var moduleType = getTypeOfSymbol(importSymbol);
return moduleType ? moduleType.symbol : undefined;
}
// External module name in an ambient declaration
else if (node.parent.kind === SyntaxKind.ModuleDeclaration) {
return getSymbolOfNode(node.parent);

// Intentinal fallthrough
case SyntaxKind.NumericLiteral:
// index access
if (node.parent.kind == SyntaxKind.IndexedAccess && (<IndexedAccess>node.parent).index === node) {
var objectType = checkExpression((<IndexedAccess>node.parent).object);
if (objectType === unknownType) return undefined;
var apparentType = getApparentType(objectType);
if (<Type>apparentType === unknownType) return undefined;
return getPropertyOfApparentType(apparentType, (<LiteralExpression>node).text);
}
break;
}
Expand Down Expand Up @@ -6978,6 +6952,10 @@ module ts {
}
}

function getRootSymbol(symbol: Symbol) {
return (symbol.flags & SymbolFlags.Transient) ? getSymbolLinks(symbol).target : symbol;
}

// Emitter support

function isExternalModuleSymbol(symbol: Symbol): boolean {
Expand Down
94 changes: 72 additions & 22 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,46 @@ module ts {
return false;
}

export function isDeclaration(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.TypeParameter:
case SyntaxKind.Parameter:
case SyntaxKind.VariableDeclaration:
case SyntaxKind.Property:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.EnumMember:
case SyntaxKind.Method:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.ImportDeclaration:
return true;
}
return false;
}

// True if the given identifier, string literal, or number literal is the name of a declaration node
export function isDeclarationOrFunctionExpressionOrCatchVariableName(name: Node): boolean {
if (name.kind !== SyntaxKind.Identifier && name.kind !== SyntaxKind.StringLiteral && name.kind !== SyntaxKind.NumericLiteral) {
return false;
}

var parent = name.parent;
if (isDeclaration(parent) || parent.kind === SyntaxKind.FunctionExpression) {
return (<Declaration>parent).name === name;
}

if (parent.kind === SyntaxKind.CatchBlock) {
return (<CatchBlock>parent).variable === name;
}

return false;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, put these back in checker, since they use parent.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Think about moving these to a module, which would contain all syntax utilities that assume parent pointers have been set up

enum ParsingContext {
SourceElements, // Elements in source file
ModuleElements, // Elements in module declaration
Expand Down Expand Up @@ -444,6 +484,22 @@ module ts {
nodeIsNestedInLabel(label: Identifier, requireIterationStatement: boolean, stopAtFunctionBoundary: boolean): ControlBlockContext;
}

export function isKeyword(token: SyntaxKind): boolean {
return SyntaxKind.FirstKeyword <= token && token <= SyntaxKind.LastKeyword;
}

export function isModifier(token: SyntaxKind): boolean {
switch (token) {
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.StaticKeyword:
case SyntaxKind.ExportKeyword:
case SyntaxKind.DeclareKeyword:
return true;
}
return false;
}

export function createSourceFile(filename: string, sourceText: string, languageVersion: ScriptTarget, version: string, isOpen: boolean = false): SourceFile {
var file: SourceFile;
var scanner: Scanner;
Expand Down Expand Up @@ -775,6 +831,10 @@ module ts {
return createNode(SyntaxKind.Missing);
}

function internIdentifier(text: string): string {
return hasProperty(identifiers, text) ? identifiers[text] : (identifiers[text] = text);
}

// An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues
// with magic property names like '__proto__'. The 'identifiers' object is used to share a single string instance for
// each identifier in order to reduce memory consumption.
Expand All @@ -783,7 +843,7 @@ module ts {
if (isIdentifier) {
var node = <Identifier>createNode(SyntaxKind.Identifier);
var text = escapeIdentifier(scanner.getTokenValue());
node.text = hasProperty(identifiers, text) ? identifiers[text] : (identifiers[text] = text);
node.text = internIdentifier(text);
nextToken();
return finishNode(node);
}
Expand All @@ -805,28 +865,11 @@ module ts {

function parsePropertyName(): Identifier {
if (token === SyntaxKind.StringLiteral || token === SyntaxKind.NumericLiteral) {
return <LiteralExpression>parsePrimaryExpression();
return parseLiteralNode(/*internName:*/ true);
}
return parseIdentifierName();
}


function isKeyword(token: SyntaxKind): boolean {
return SyntaxKind.FirstKeyword <= token && token <= SyntaxKind.LastKeyword;
}

function isModifier(token: SyntaxKind): boolean {
switch (token) {
case SyntaxKind.PublicKeyword:
case SyntaxKind.PrivateKeyword:
case SyntaxKind.StaticKeyword:
case SyntaxKind.ExportKeyword:
case SyntaxKind.DeclareKeyword:
return true;
}
return false;
}

function parseContextualModifier(t: SyntaxKind): boolean {
return token === t && tryParse(() => {
nextToken();
Expand Down Expand Up @@ -1086,9 +1129,11 @@ module ts {
return finishNode(node);
}

function parseLiteralNode(): LiteralExpression {
function parseLiteralNode(internName?:boolean): LiteralExpression {
var node = <LiteralExpression>createNode(token);
node.text = scanner.getTokenValue();
var text = scanner.getTokenValue();
node.text = internName ? internIdentifier(text) : text;

var tokenPos = scanner.getTokenPos();
nextToken();
finishNode(node);
Expand All @@ -1115,7 +1160,7 @@ module ts {
}

function parseStringLiteral(): LiteralExpression {
if (token === SyntaxKind.StringLiteral) return parseLiteralNode();
if (token === SyntaxKind.StringLiteral) return parseLiteralNode(/*internName:*/ true);
error(Diagnostics.String_literal_expected);
return <LiteralExpression>createMissingNode();
}
Expand Down Expand Up @@ -2019,6 +2064,10 @@ module ts {
}
else {
indexedAccess.index = parseExpression();
if (indexedAccess.index.kind === SyntaxKind.StringLiteral || indexedAccess.index.kind === SyntaxKind.NumericLiteral) {
var literal = <LiteralExpression>indexedAccess.index;
literal.text = internIdentifier(literal.text);
}
parseExpected(SyntaxKind.CloseBracketToken);
}

Expand Down Expand Up @@ -3569,6 +3618,7 @@ module ts {
file.version = version;
file.isOpen = isOpen;
file.languageVersion = languageVersion;
file.identifiers = identifiers;
return file;
}

Expand Down
12 changes: 12 additions & 0 deletions src/compiler/scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,18 @@ module ts {
return getCommentRanges(text, pos, /*trailing*/ true);
}

export function isIdentifierStart(ch: number, languageVersion: ScriptTarget): boolean {
return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z ||
ch === CharacterCodes.$ || ch === CharacterCodes._ ||
ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierStart(ch, languageVersion);
}

export function isIdentifierPart(ch: number, languageVersion: ScriptTarget): boolean {
return ch >= CharacterCodes.A && ch <= CharacterCodes.Z || ch >= CharacterCodes.a && ch <= CharacterCodes.z ||
ch >= CharacterCodes._0 && ch <= CharacterCodes._9 || ch === CharacterCodes.$ || ch === CharacterCodes._ ||
ch > CharacterCodes.maxAsciiCharacter && isUnicodeIdentifierPart(ch, languageVersion);
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are already here! Make sure they are not duplicated

export function createScanner(languageVersion: ScriptTarget, text?: string, onError?: ErrorCallback, onComment?: CommentCallback): Scanner {
var pos: number; // Current position (end position of text of current token)
var len: number; // Length of text
Expand Down
3 changes: 3 additions & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,7 @@ module ts {
isOpen: boolean;
version: string;
languageVersion: ScriptTarget;
identifiers: Map<string>;
}

export interface Program {
Expand Down Expand Up @@ -616,6 +617,8 @@ module ts {
typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string;
getAugmentedPropertiesOfApparentType(type: Type): Symbol[];
getRootSymbol(symbol: Symbol): Symbol;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment what this does

getContextualType(node: Node): Type;
}

export interface TextWriter {
Expand Down
Loading