Merge branch 'master' into wip-master-statelessOverload

This commit is contained in:
Kanchalai Tanglertsampan
2017-01-24 14:18:39 -08:00
282 changed files with 3319 additions and 1688 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
/* @internal */
namespace ts.Completions {
type Log = (message: string) => void;
export type Log = (message: string) => void;
export function getCompletionsAtPosition(host: LanguageServiceHost, typeChecker: TypeChecker, log: Log, compilerOptions: CompilerOptions, sourceFile: SourceFile, position: number): CompletionInfo | undefined {
if (isInReferenceComment(sourceFile, position)) {
+2 -16
View File
@@ -17,25 +17,11 @@ namespace ts.DocumentHighlights {
}
function getSemanticDocumentHighlights(node: Node, typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFilesToSearch: SourceFile[]): DocumentHighlights[] {
if (node.kind === SyntaxKind.Identifier ||
node.kind === SyntaxKind.ThisKeyword ||
node.kind === SyntaxKind.ThisType ||
node.kind === SyntaxKind.SuperKeyword ||
node.kind === SyntaxKind.StringLiteral ||
isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) {
const referencedSymbols = FindAllReferences.getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFilesToSearch, /*findInStrings*/ false, /*findInComments*/ false, /*implementations*/false);
return convertReferencedSymbols(referencedSymbols);
}
return undefined;
const referencedSymbols = FindAllReferences.getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFilesToSearch, /*findInStrings*/false, /*findInComments*/false, /*implementations*/false);
return referencedSymbols && convertReferencedSymbols(referencedSymbols);
}
function convertReferencedSymbols(referencedSymbols: ReferencedSymbol[]): DocumentHighlights[] {
if (!referencedSymbols) {
return undefined;
}
const fileNameToDocumentHighlights = createMap<DocumentHighlights>();
const result: DocumentHighlights[] = [];
for (const referencedSymbol of referencedSymbols) {
+105 -84
View File
@@ -1,29 +1,16 @@
/* @internal */
namespace ts.FindAllReferences {
export function findReferencedSymbols(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number, findInStrings: boolean, findInComments: boolean): ReferencedSymbol[] {
export function findReferencedSymbols(typeChecker: TypeChecker, cancellationToken: CancellationToken, sourceFiles: SourceFile[], sourceFile: SourceFile, position: number, findInStrings: boolean, findInComments: boolean): ReferencedSymbol[] | undefined {
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocComment*/ true);
if (node === sourceFile) {
return undefined;
}
switch (node.kind) {
case SyntaxKind.NumericLiteral:
if (!isLiteralNameOfPropertyDeclarationOrIndexAccess(node)) {
break;
}
// Fallthrough
case SyntaxKind.Identifier:
case SyntaxKind.ThisKeyword:
// case SyntaxKind.SuperKeyword: TODO:GH#9268
case SyntaxKind.ConstructorKeyword:
case SyntaxKind.StringLiteral:
return getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFiles, findInStrings, findInComments, /*implementations*/false);
}
return undefined;
return getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFiles, findInStrings, findInComments, /*implementations*/false);
}
export function getReferencedSymbolsForNode(typeChecker: TypeChecker, cancellationToken: CancellationToken, node: Node, sourceFiles: SourceFile[], findInStrings: boolean, findInComments: boolean, implementations: boolean): ReferencedSymbol[] {
export function getReferencedSymbolsForNode(typeChecker: TypeChecker, cancellationToken: CancellationToken, node: Node, sourceFiles: SourceFile[], findInStrings: boolean, findInComments: boolean, implementations: boolean): ReferencedSymbol[] | undefined {
if (!implementations) {
if (isTypeKeyword(node.kind)) {
return getAllReferencesForKeyword(sourceFiles, node.kind, cancellationToken);
}
// Labels
if (isLabelName(node)) {
if (isJumpStatementTarget(node)) {
@@ -68,8 +55,6 @@ namespace ts.FindAllReferences {
return undefined;
}
let result: ReferencedSymbol[];
// Compute the meaning from the location and the symbol it references
const searchMeaning = getIntersectingMeaningFromDeclarations(getMeaningFromLocation(node), declarations);
@@ -84,6 +69,7 @@ namespace ts.FindAllReferences {
// Maps from a symbol ID to the ReferencedSymbol entry in 'result'.
const symbolToIndex: number[] = [];
let result: ReferencedSymbol[];
if (scope) {
result = [];
getReferencesInNode(scope, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex, implementations, typeChecker, cancellationToken);
@@ -92,10 +78,7 @@ namespace ts.FindAllReferences {
const internedName = getInternedName(symbol, node);
for (const sourceFile of sourceFiles) {
cancellationToken.throwIfCancellationRequested();
const nameTable = getNameTable(sourceFile);
if (nameTable.get(internedName) !== undefined) {
if (sourceFileHasName(sourceFile, internedName)) {
result = result || [];
getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex, implementations, typeChecker, cancellationToken);
}
@@ -105,9 +88,13 @@ namespace ts.FindAllReferences {
return result;
}
function sourceFileHasName(sourceFile: SourceFile, name: string): boolean {
return getNameTable(sourceFile).get(name) !== undefined;
}
function getDefinition(symbol: Symbol, node: Node, typeChecker: TypeChecker): ReferencedSymbolDefinitionInfo {
const info = SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, node.getSourceFile(), getContainerNode(node), node);
const name = map(info.displayParts, p => p.text).join("");
const { displayParts, symbolKind } = SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker, symbol, node.getSourceFile(), getContainerNode(node), node);
const name = displayParts.map(p => p.text).join("");
const declarations = symbol.declarations;
if (!declarations || declarations.length === 0) {
return undefined;
@@ -117,10 +104,10 @@ namespace ts.FindAllReferences {
containerKind: "",
containerName: "",
name,
kind: info.symbolKind,
kind: symbolKind,
fileName: declarations[0].getSourceFile().fileName,
textSpan: createTextSpan(declarations[0].getStart(), 0),
displayParts: info.displayParts
displayParts
};
}
@@ -351,6 +338,43 @@ namespace ts.FindAllReferences {
}
}
function getAllReferencesForKeyword(sourceFiles: SourceFile[], keywordKind: ts.SyntaxKind, cancellationToken: CancellationToken): ReferencedSymbol[] {
const name = tokenToString(keywordKind);
const definition: ReferencedSymbolDefinitionInfo = {
containerKind: "",
containerName: "",
fileName: "",
kind: ScriptElementKind.keyword,
name,
textSpan: createTextSpan(0, 1),
displayParts: [{ text: name, kind: ScriptElementKind.keyword }]
}
const references: ReferenceEntry[] = [];
for (const sourceFile of sourceFiles) {
cancellationToken.throwIfCancellationRequested();
addReferencesForKeywordInFile(sourceFile, keywordKind, name, cancellationToken, references);
}
return [{ definition, references }];
}
function addReferencesForKeywordInFile(sourceFile: SourceFile, kind: SyntaxKind, searchText: string, cancellationToken: CancellationToken, references: Push<ReferenceEntry>): void {
const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, sourceFile.getStart(), sourceFile.getEnd(), cancellationToken);
for (const position of possiblePositions) {
cancellationToken.throwIfCancellationRequested();
const referenceLocation = getTouchingPropertyName(sourceFile, position);
if (referenceLocation.kind === kind) {
references.push({
textSpan: createTextSpanFromNode(referenceLocation),
fileName: sourceFile.fileName,
isWriteAccess: false,
isDefinition: false,
});
}
}
}
/** Search within node "container" for references for a search value, where the search value is defined as a
* tuple of(searchSymbol, searchText, searchLocation, and searchMeaning).
* searchLocation: a node where the search value
@@ -375,67 +399,64 @@ namespace ts.FindAllReferences {
const parents = getParentSymbolsOfPropertyAccess();
const inheritsFromCache: Map<boolean> = createMap<boolean>();
// Build the set of symbols to search for, initially it has only the current symbol
const searchSymbols = populateSearchSymbolSet(searchSymbol, searchLocation, typeChecker, implementations);
if (possiblePositions.length) {
// Build the set of symbols to search for, initially it has only the current symbol
const searchSymbols = populateSearchSymbolSet(searchSymbol, searchLocation, typeChecker, implementations);
for (const position of possiblePositions) {
cancellationToken.throwIfCancellationRequested();
forEach(possiblePositions, position => {
cancellationToken.throwIfCancellationRequested();
const referenceLocation = getTouchingPropertyName(sourceFile, position);
if (!isValidReferencePosition(referenceLocation, searchText)) {
// This wasn't the start of a token. Check to see if it might be a
// match in a comment or string if that's what the caller is asking
// for.
if (!implementations && ((findInStrings && isInString(sourceFile, position)) ||
(findInComments && isInNonReferenceComment(sourceFile, position)))) {
const referenceLocation = getTouchingPropertyName(sourceFile, position);
if (!isValidReferencePosition(referenceLocation, searchText)) {
// This wasn't the start of a token. Check to see if it might be a
// match in a comment or string if that's what the caller is asking
// for.
if (!implementations && ((findInStrings && isInString(sourceFile, position)) ||
(findInComments && isInNonReferenceComment(sourceFile, position)))) {
// In the case where we're looking inside comments/strings, we don't have
// an actual definition. So just use 'undefined' here. Features like
// 'Rename' won't care (as they ignore the definitions), and features like
// 'FindReferences' will just filter out these results.
result.push({
definition: undefined,
references: [{
fileName: sourceFile.fileName,
textSpan: createTextSpan(position, searchText.length),
isWriteAccess: false,
isDefinition: false
}]
});
}
return;
// In the case where we're looking inside comments/strings, we don't have
// an actual definition. So just use 'undefined' here. Features like
// 'Rename' won't care (as they ignore the definitions), and features like
// 'FindReferences' will just filter out these results.
result.push({
definition: undefined,
references: [{
fileName: sourceFile.fileName,
textSpan: createTextSpan(position, searchText.length),
isWriteAccess: false,
isDefinition: false
}]
});
}
continue;
}
if (!(getMeaningFromLocation(referenceLocation) & searchMeaning)) {
return;
if (!(getMeaningFromLocation(referenceLocation) & searchMeaning)) {
continue;
}
const referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation);
if (referenceSymbol) {
const referenceSymbolDeclaration = referenceSymbol.valueDeclaration;
const shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration);
const relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation,
/*searchLocationIsConstructor*/ searchLocation.kind === SyntaxKind.ConstructorKeyword, parents, inheritsFromCache, typeChecker);
if (relatedSymbol) {
addReferenceToRelatedSymbol(referenceLocation, relatedSymbol);
}
const referenceSymbol = typeChecker.getSymbolAtLocation(referenceLocation);
if (referenceSymbol) {
const referenceSymbolDeclaration = referenceSymbol.valueDeclaration;
const shorthandValueSymbol = typeChecker.getShorthandAssignmentValueSymbol(referenceSymbolDeclaration);
const relatedSymbol = getRelatedSymbol(searchSymbols, referenceSymbol, referenceLocation,
/*searchLocationIsConstructor*/ searchLocation.kind === SyntaxKind.ConstructorKeyword, parents, inheritsFromCache, typeChecker);
if (relatedSymbol) {
addReferenceToRelatedSymbol(referenceLocation, relatedSymbol);
}
/* Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment
* has two meaning : property name and property value. Therefore when we do findAllReference at the position where
* an identifier is declared, the language service should return the position of the variable declaration as well as
* the position in short-hand property assignment excluding property accessing. However, if we do findAllReference at the
* position of property accessing, the referenceEntry of such position will be handled in the first case.
*/
else if (!(referenceSymbol.flags & SymbolFlags.Transient) && searchSymbols.indexOf(shorthandValueSymbol) >= 0) {
addReferenceToRelatedSymbol(referenceSymbolDeclaration.name, shorthandValueSymbol);
}
else if (searchLocation.kind === SyntaxKind.ConstructorKeyword) {
findAdditionalConstructorReferences(referenceSymbol, referenceLocation);
}
/* Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment
* has two meaning : property name and property value. Therefore when we do findAllReference at the position where
* an identifier is declared, the language service should return the position of the variable declaration as well as
* the position in short-hand property assignment excluding property accessing. However, if we do findAllReference at the
* position of property accessing, the referenceEntry of such position will be handled in the first case.
*/
else if (!(referenceSymbol.flags & SymbolFlags.Transient) && searchSymbols.indexOf(shorthandValueSymbol) >= 0) {
addReferenceToRelatedSymbol(referenceSymbolDeclaration.name, shorthandValueSymbol);
}
});
else if (searchLocation.kind === SyntaxKind.ConstructorKeyword) {
findAdditionalConstructorReferences(referenceSymbol, referenceLocation);
}
}
}
return;
+12 -11
View File
@@ -193,9 +193,10 @@ namespace ts {
return undefined;
}
const child = children[0];
return child.kind < SyntaxKind.FirstNode ? child : child.getFirstToken(sourceFile);
const child = ts.find(children, kid => kid.kind < SyntaxKind.FirstJSDocNode || kid.kind > SyntaxKind.LastJSDocNode);
return child.kind < SyntaxKind.FirstNode ?
child :
child.getFirstToken(sourceFile);
}
public getLastToken(sourceFile?: SourceFile): Node {
@@ -379,7 +380,7 @@ namespace ts {
getNumberIndexType(): Type {
return this.checker.getIndexTypeOfType(this, IndexKind.Number);
}
getBaseTypes(): ObjectType[] {
getBaseTypes(): BaseType[] {
return this.flags & TypeFlags.Object && this.objectFlags & (ObjectFlags.Class | ObjectFlags.Interface)
? this.checker.getBaseTypes(<InterfaceType><Type>this)
: undefined;
@@ -1959,11 +1960,9 @@ namespace ts {
function walk(node: Node) {
switch (node.kind) {
case SyntaxKind.Identifier: {
const text = (<Identifier>node).text;
nameTable.set(text, nameTable.get(text) === undefined ? node.pos : -1);
case SyntaxKind.Identifier:
setNameTable((<Identifier>node).text, node);
break;
}
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
// We want to store any numbers/strings if they were a name that could be
@@ -1974,9 +1973,7 @@ namespace ts {
node.parent.kind === SyntaxKind.ExternalModuleReference ||
isArgumentOfElementAccessExpression(node) ||
isLiteralComputedPropertyDeclarationName(node)) {
const text = (<LiteralExpression>node).text;
nameTable.set(text, nameTable.get(text) === undefined ? node.pos : -1);
setNameTable((<LiteralExpression>node).text, node);
}
break;
default:
@@ -1988,6 +1985,10 @@ namespace ts {
}
}
}
function setNameTable(text: string, node: ts.Node): void {
nameTable.set(text, nameTable.get(text) === undefined ? node.pos : -1);
}
}
function isObjectLiteralElement(node: Node): node is ObjectLiteralElement {
+2 -2
View File
@@ -33,7 +33,7 @@ namespace ts {
getConstructSignatures(): Signature[];
getStringIndexType(): Type;
getNumberIndexType(): Type;
getBaseTypes(): ObjectType[];
getBaseTypes(): BaseType[];
getNonNullableType(): Type;
}
@@ -495,7 +495,7 @@ namespace ts {
export interface SymbolDisplayPart {
text: string;
kind: string;
kind: string; // A ScriptElementKind
}
export interface QuickInfo {
+21 -2
View File
@@ -1,4 +1,4 @@
// These utilities are common to multiple language service features.
// These utilities are common to multiple language service features.
/* @internal */
namespace ts {
export const scanner: Scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true);
@@ -72,7 +72,10 @@ namespace ts {
}
export function getMeaningFromLocation(node: Node): SemanticMeaning {
if (node.parent.kind === SyntaxKind.ExportAssignment) {
if (node.kind === SyntaxKind.SourceFile) {
return SemanticMeaning.Value;
}
else if (node.parent.kind === SyntaxKind.ExportAssignment) {
return SemanticMeaning.Value | SemanticMeaning.Type | SemanticMeaning.Namespace;
}
else if (isInRightSideOfImport(node)) {
@@ -1117,6 +1120,22 @@ namespace ts {
export function createTextSpanFromNode(node: Node, sourceFile?: SourceFile): TextSpan {
return createTextSpanFromBounds(node.getStart(sourceFile), node.getEnd());
}
export function isTypeKeyword(kind: SyntaxKind): boolean {
switch (kind) {
case SyntaxKind.AnyKeyword:
case SyntaxKind.BooleanKeyword:
case SyntaxKind.NeverKeyword:
case SyntaxKind.NumberKeyword:
case SyntaxKind.ObjectKeyword:
case SyntaxKind.StringKeyword:
case SyntaxKind.SymbolKeyword:
case SyntaxKind.VoidKeyword:
return true;
default:
return false;
}
}
}
// Display-part writer helpers