mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 03:23:08 -06:00
wire in getCompletions
This commit is contained in:
parent
8eda35afa0
commit
346809ba2b
@ -63,7 +63,33 @@ module ts {
|
||||
var diagnostics: Diagnostic[] = [];
|
||||
var diagnosticsModified: boolean = false;
|
||||
|
||||
var checker: TypeChecker;
|
||||
var checker: TypeChecker = {
|
||||
getProgram: () => program,
|
||||
getDiagnostics: getDiagnostics,
|
||||
getGlobalDiagnostics: getGlobalDiagnostics,
|
||||
getNodeCount: () => sum(program.getSourceFiles(), "nodeCount"),
|
||||
getIdentifierCount: () => sum(program.getSourceFiles(), "identifierCount"),
|
||||
getSymbolCount: () => sum(program.getSourceFiles(), "symbolCount"),
|
||||
getTypeCount: () => typeCount,
|
||||
checkProgram: checkProgram,
|
||||
emitFiles: invokeEmitter,
|
||||
getSymbolOfNode: getSymbolOfNode,
|
||||
getParentOfSymbol: getParentOfSymbol,
|
||||
getTypeOfSymbol: getTypeOfSymbol,
|
||||
getDeclaredTypeOfSymbol: getDeclaredTypeOfSymbol,
|
||||
getPropertiesOfType: getPropertiesOfType,
|
||||
getSignaturesOfType: getSignaturesOfType,
|
||||
getIndexTypeOfType: getIndexTypeOfType,
|
||||
getReturnTypeOfSignature: getReturnTypeOfSignature,
|
||||
resolveEntityName: resolveEntityName,
|
||||
getSymbolsInScope: getSymbolsInScope,
|
||||
getSymbolOfIdentifier: getSymbolOfIdentifier,
|
||||
getTypeOfExpression: getTypeOfExpression,
|
||||
typeToString: typeToString,
|
||||
symbolToString: symbolToString,
|
||||
writeTypeToTextWriter: writeTypeToTextWriter,
|
||||
getAugmentedPropertiesOfApparentType: getAugmentedPropertiesOfApparentType
|
||||
};
|
||||
|
||||
function addDiagnostic(diagnostic: Diagnostic) {
|
||||
diagnostics.push(diagnostic);
|
||||
@ -4784,14 +4810,6 @@ module ts {
|
||||
return (node.flags & NodeFlags.Private) && isInAmbientContext(node);
|
||||
}
|
||||
|
||||
function isInAmbientContext(node: Node): boolean {
|
||||
while (node) {
|
||||
if (node.flags & (NodeFlags.Ambient | NodeFlags.DeclarationFile)) return true;
|
||||
node = node.parent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkSpecializedSignatureDeclaration(signatureDeclarationNode: SignatureDeclaration): void {
|
||||
var signature = getSignatureFromDeclaration(signatureDeclarationNode);
|
||||
if (!signature.hasStringLiterals) {
|
||||
@ -6191,9 +6209,14 @@ module ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function isRightSideOfQualifiedName(node: Node) {
|
||||
return (node.parent.kind === SyntaxKind.QualifiedName || node.parent.kind === SyntaxKind.PropertyAccess) &&
|
||||
(<QualifiedName>node.parent).right === node;
|
||||
}
|
||||
|
||||
function getSymbolOfIdentifier(identifier: Identifier) {
|
||||
if (isExpression(identifier)) {
|
||||
if (isRightSideOfQualifiedName()) {
|
||||
if (isRightSideOfQualifiedName(identifier)) {
|
||||
var node = <QualifiedName>identifier.parent;
|
||||
var symbol = getNodeLinks(node).resolvedSymbol;
|
||||
if (!symbol) {
|
||||
@ -6207,16 +6230,58 @@ module ts {
|
||||
return getSymbolOfNode(identifier.parent);
|
||||
}
|
||||
if (isTypeReferenceIdentifier(identifier)) {
|
||||
var entityName = isRightSideOfQualifiedName() ? identifier.parent : identifier;
|
||||
var entityName = isRightSideOfQualifiedName(identifier) ? identifier.parent : identifier;
|
||||
var meaning = entityName.parent.kind === SyntaxKind.TypeReference ? SymbolFlags.Type : SymbolFlags.Namespace;
|
||||
return resolveEntityName(entityName, entityName, meaning);
|
||||
}
|
||||
function isRightSideOfQualifiedName() {
|
||||
return (identifier.parent.kind === SyntaxKind.QualifiedName || identifier.parent.kind === SyntaxKind.PropertyAccess) &&
|
||||
(<QualifiedName>identifier.parent).right === identifier;
|
||||
}
|
||||
}
|
||||
|
||||
function getTypeOfExpression(node: Node) {
|
||||
if (isExpression(node)) {
|
||||
while (isRightSideOfQualifiedName(node)) {
|
||||
node = node.parent;
|
||||
}
|
||||
return <Type>getApparentType(checkExpression(node));
|
||||
}
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
function getAugmentedPropertiesOfApparentType(type: Type): Symbol[]{
|
||||
var apparentType = getApparentType(type);
|
||||
|
||||
if (apparentType.flags & TypeFlags.ObjectType) {
|
||||
// Augment the apprent type with Function and Object memeber as applicaple
|
||||
var propertiesByName: Map<Symbol> = {};
|
||||
var results: Symbol[] = [];
|
||||
|
||||
forEach(getPropertiesOfType(apparentType), (s) => {
|
||||
propertiesByName[s.name] = s;
|
||||
results.push(s);
|
||||
});
|
||||
|
||||
var resolved = resolveObjectTypeMembers(<ObjectType>type);
|
||||
forEachValue(resolved.members, (s) => {
|
||||
if (symbolIsValue(s) && !propertiesByName[s.name]) {
|
||||
propertiesByName[s.name] = s;
|
||||
results.push(s);
|
||||
}
|
||||
});
|
||||
|
||||
if (resolved === anyFunctionType || resolved.callSignatures.length || resolved.constructSignatures.length) {
|
||||
forEach(getPropertiesOfType(globalFunctionType), (s) => {
|
||||
if (!propertiesByName[s.name]) {
|
||||
propertiesByName[s.name] = s;
|
||||
results.push(s);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
else {
|
||||
return getPropertiesOfType(<Type>apparentType);
|
||||
}
|
||||
}
|
||||
// Emitter support
|
||||
|
||||
function isExternalModuleSymbol(symbol: Symbol): boolean {
|
||||
@ -6410,32 +6475,7 @@ module ts {
|
||||
}
|
||||
|
||||
initializeTypeChecker();
|
||||
checker = {
|
||||
getProgram: () => program,
|
||||
getDiagnostics: getDiagnostics,
|
||||
getGlobalDiagnostics: getGlobalDiagnostics,
|
||||
getNodeCount: () => sum(program.getSourceFiles(), "nodeCount"),
|
||||
getIdentifierCount: () => sum(program.getSourceFiles(), "identifierCount"),
|
||||
getSymbolCount: () => sum(program.getSourceFiles(), "symbolCount"),
|
||||
getTypeCount: () => typeCount,
|
||||
checkProgram: checkProgram,
|
||||
emitFiles: invokeEmitter,
|
||||
getSymbolOfNode: getSymbolOfNode,
|
||||
getParentOfSymbol: getParentOfSymbol,
|
||||
getTypeOfSymbol: getTypeOfSymbol,
|
||||
getDeclaredTypeOfSymbol: getDeclaredTypeOfSymbol,
|
||||
getPropertiesOfType: getPropertiesOfType,
|
||||
getSignaturesOfType: getSignaturesOfType,
|
||||
getIndexTypeOfType: getIndexTypeOfType,
|
||||
getReturnTypeOfSignature: getReturnTypeOfSignature,
|
||||
resolveEntityName: resolveEntityName,
|
||||
getSymbolsInScope: getSymbolsInScope,
|
||||
getSymbolOfIdentifier: getSymbolOfIdentifier,
|
||||
getTypeOfExpression: checkExpression,
|
||||
typeToString: typeToString,
|
||||
symbolToString: symbolToString,
|
||||
writeTypeToTextWriter: writeTypeToTextWriter
|
||||
};
|
||||
|
||||
return checker;
|
||||
}
|
||||
}
|
||||
|
||||
@ -327,6 +327,14 @@ module ts {
|
||||
return s.parameters.length > 0 && (s.parameters[s.parameters.length - 1].flags & NodeFlags.Rest) !== 0;
|
||||
}
|
||||
|
||||
export function isInAmbientContext(node: Node): boolean {
|
||||
while (node) {
|
||||
if (node.flags & (NodeFlags.Ambient | NodeFlags.DeclarationFile)) return true;
|
||||
node = node.parent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
enum ParsingContext {
|
||||
SourceElements, // Elements in source file
|
||||
ModuleElements, // Elements in module declaration
|
||||
|
||||
@ -603,6 +603,7 @@ module ts {
|
||||
typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
|
||||
symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string;
|
||||
writeTypeToTextWriter(type: Type, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: TextWriter): void;
|
||||
getAugmentedPropertiesOfApparentType(type: Type): Symbol[];
|
||||
}
|
||||
|
||||
export interface TextWriter {
|
||||
|
||||
@ -9,46 +9,46 @@ module TypeScript.Services {
|
||||
return new TextSpan(start(ast), width(ast));
|
||||
}
|
||||
|
||||
private static symbolDeclarationIntersectsPosition(symbol: PullSymbol, fileName: string, position: number) {
|
||||
var decl = symbol.getDeclarations()[0];
|
||||
if (decl.fileName() === fileName && this.getSpan(decl.ast()).intersectsWithPosition(position)) {
|
||||
// This is the symbol declaration from the given position in the file
|
||||
return true;
|
||||
}
|
||||
//private static symbolDeclarationIntersectsPosition(symbol: PullSymbol, fileName: string, position: number) {
|
||||
// var decl = symbol.getDeclarations()[0];
|
||||
// if (decl.fileName() === fileName && this.getSpan(decl.ast()).intersectsWithPosition(position)) {
|
||||
// // This is the symbol declaration from the given position in the file
|
||||
// return true;
|
||||
// }
|
||||
|
||||
return false;
|
||||
}
|
||||
// return false;
|
||||
//}
|
||||
|
||||
public static filterContextualMembersList(contextualMemberSymbols: TypeScript.PullSymbol[], existingMembers: TypeScript.PullVisibleSymbolsInfo, fileName: string, position: number): TypeScript.PullSymbol[] {
|
||||
if (!existingMembers || !existingMembers.symbols || existingMembers.symbols.length === 0) {
|
||||
return contextualMemberSymbols;
|
||||
}
|
||||
//public static filterContextualMembersList(contextualMemberSymbols: TypeScript.PullSymbol[], existingMembers: TypeScript.PullVisibleSymbolsInfo, fileName: string, position: number): TypeScript.PullSymbol[] {
|
||||
// if (!existingMembers || !existingMembers.symbols || existingMembers.symbols.length === 0) {
|
||||
// return contextualMemberSymbols;
|
||||
// }
|
||||
|
||||
var existingMemberSymbols = existingMembers.symbols;
|
||||
var existingMemberNames = TypeScript.createIntrinsicsObject<boolean>();
|
||||
for (var i = 0, n = existingMemberSymbols.length; i < n; i++) {
|
||||
if (this.symbolDeclarationIntersectsPosition(existingMemberSymbols[i], fileName, position)) {
|
||||
// If this is the current item we are editing right now, do not filter it out
|
||||
continue;
|
||||
}
|
||||
// var existingMemberSymbols = existingMembers.symbols;
|
||||
// var existingMemberNames = TypeScript.createIntrinsicsObject<boolean>();
|
||||
// for (var i = 0, n = existingMemberSymbols.length; i < n; i++) {
|
||||
// if (this.symbolDeclarationIntersectsPosition(existingMemberSymbols[i], fileName, position)) {
|
||||
// // If this is the current item we are editing right now, do not filter it out
|
||||
// continue;
|
||||
// }
|
||||
|
||||
existingMemberNames[TypeScript.stripStartAndEndQuotes(existingMemberSymbols[i].getDisplayName())] = true;
|
||||
}
|
||||
// existingMemberNames[TypeScript.stripStartAndEndQuotes(existingMemberSymbols[i].getDisplayName())] = true;
|
||||
// }
|
||||
|
||||
var filteredMembers: TypeScript.PullSymbol[] = [];
|
||||
for (var j = 0, m = contextualMemberSymbols.length; j < m; j++) {
|
||||
var contextualMemberSymbol = contextualMemberSymbols[j];
|
||||
if (!existingMemberNames[TypeScript.stripStartAndEndQuotes(contextualMemberSymbol.getDisplayName())]) {
|
||||
if (this.symbolDeclarationIntersectsPosition(contextualMemberSymbol, fileName, position)) {
|
||||
// If this contextual member symbol was created as part of editing the current position, do not use it
|
||||
continue;
|
||||
}
|
||||
filteredMembers.push(contextualMemberSymbol);
|
||||
}
|
||||
}
|
||||
// var filteredMembers: TypeScript.PullSymbol[] = [];
|
||||
// for (var j = 0, m = contextualMemberSymbols.length; j < m; j++) {
|
||||
// var contextualMemberSymbol = contextualMemberSymbols[j];
|
||||
// if (!existingMemberNames[TypeScript.stripStartAndEndQuotes(contextualMemberSymbol.getDisplayName())]) {
|
||||
// if (this.symbolDeclarationIntersectsPosition(contextualMemberSymbol, fileName, position)) {
|
||||
// // If this contextual member symbol was created as part of editing the current position, do not use it
|
||||
// continue;
|
||||
// }
|
||||
// filteredMembers.push(contextualMemberSymbol);
|
||||
// }
|
||||
// }
|
||||
|
||||
return filteredMembers;
|
||||
}
|
||||
// return filteredMembers;
|
||||
//}
|
||||
|
||||
public static isCompletionListBlocker(sourceUnit: TypeScript.SourceUnitSyntax, position: number): boolean {
|
||||
// We shouldn't be getting a possition that is outside the file because
|
||||
@ -173,7 +173,7 @@ module TypeScript.Services {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static getValidCompletionEntryDisplayName(displayName: string): string {
|
||||
public static getValidCompletionEntryDisplayName(displayName: string, target: ts.ScriptTarget): string {
|
||||
if (displayName && displayName.length > 0) {
|
||||
var firstChar = displayName.charCodeAt(0);
|
||||
if (firstChar === TypeScript.CharacterCodes.singleQuote || firstChar === TypeScript.CharacterCodes.doubleQuote) {
|
||||
@ -182,7 +182,7 @@ module TypeScript.Services {
|
||||
displayName = TypeScript.stripStartAndEndQuotes(displayName);
|
||||
}
|
||||
|
||||
if (TypeScript.Scanner.isValidIdentifier(TypeScript.SimpleText.fromString(displayName), TypeScript.LanguageVersion.EcmaScript5)) {
|
||||
if (TypeScript.Scanner.isValidIdentifier(TypeScript.SimpleText.fromString(displayName), target)) {
|
||||
return displayName;
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,15 +53,18 @@ module TypeScript.Services {
|
||||
"with",
|
||||
];
|
||||
|
||||
private static keywordCompletions: ResolvedCompletionEntry[] = null;
|
||||
private static keywordCompletions: CompletionEntry[] = null;
|
||||
|
||||
public static getKeywordCompltions(): ResolvedCompletionEntry[]{
|
||||
public static getKeywordCompltions(): CompletionEntry[]{
|
||||
if (KeywordCompletions.keywordCompletions === null) {
|
||||
var completions: ResolvedCompletionEntry[] = [];
|
||||
var completions: CompletionEntry[] = [];
|
||||
for (var i = 0, n = KeywordCompletions.keywords.length; i < n; i++) {
|
||||
var keyword = KeywordCompletions.keywords[i];
|
||||
var entry = new ResolvedCompletionEntry(/*name*/ keyword, ScriptElementKind.keyword, ScriptElementKindModifier.none, /*type*/null, /*fullName*/ keyword, /*docComment*/ null);
|
||||
completions.push(entry);
|
||||
completions.push({
|
||||
name: keyword,
|
||||
kind: ScriptElementKind.keyword,
|
||||
kindModifiers: ScriptElementKindModifier.none
|
||||
});
|
||||
}
|
||||
|
||||
KeywordCompletions.keywordCompletions = completions;
|
||||
|
||||
@ -7,6 +7,15 @@
|
||||
/// <reference path="..\compiler\checker.ts"/>
|
||||
|
||||
module TypeScript.Services {
|
||||
interface CompletionSession {
|
||||
filename: string; // the file where the completion was requested
|
||||
position: number; // position in the file where the completion was requested
|
||||
entries: CompletionEntry[]; // entries for this completion
|
||||
symbols: ts.Map<ts.Symbol>; // symbols by entry name map
|
||||
location: ts.Node; // the node where the completion was requested
|
||||
typeChecker: ts.TypeChecker;// the typeChecker used to generate this completion
|
||||
}
|
||||
|
||||
// Information about a specific host file.
|
||||
class HostFileInformation {
|
||||
private _sourceText: TypeScript.IScriptSnapshot;
|
||||
@ -420,6 +429,7 @@ module TypeScript.Services {
|
||||
private documentsByName: ts.Map<Document> = {};
|
||||
private documentRegistry: IDocumentRegistry
|
||||
private cancellationToken: CancellationToken;
|
||||
private activeCompletionSession: CompletionSession;
|
||||
|
||||
constructor(public host: ILanguageServiceHost, documentRegistry: IDocumentRegistry) {
|
||||
this.logger = this.host;
|
||||
@ -558,11 +568,206 @@ module TypeScript.Services {
|
||||
this.synchronizeHostData();
|
||||
return this.program.getGlobalDiagnostics();
|
||||
}
|
||||
|
||||
private getCompletionEntriesFromSymbols(symbols: ts.Symbol[], session:CompletionSession): void {
|
||||
ts.forEach(symbols, (symbol) => {
|
||||
var entry = this.createCompletionEntry(symbol);
|
||||
if (entry) {
|
||||
session.entries.push(entry);
|
||||
session.symbols[entry.name] = symbol;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private createCompletionEntry(symbol: ts.Symbol): CompletionEntry {
|
||||
// Try to get a valid display name for this symbol, if we could not find one, then ignore it.
|
||||
// We would like to only show things that can be added after a dot, so for instance numeric properties can
|
||||
// not be accessed with a dot (a.1 <- invalid)
|
||||
var displayName = CompletionHelpers.getValidCompletionEntryDisplayName(symbol.getName(), this.program.getCompilerOptions().target);
|
||||
if (!displayName) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var declarations = symbol.getDeclarations();
|
||||
var firstDeclaration = [0];
|
||||
return {
|
||||
name: displayName,
|
||||
kind: this.getSymbolKind(symbol),
|
||||
kindModifiers: declarations ? this.getNodeModifiers(declarations[0]) : ScriptElementKindModifier.none
|
||||
};
|
||||
}
|
||||
|
||||
getCompletionsAtPosition(filename: string, position: number, isMemberCompletion: boolean) {
|
||||
return undefined;
|
||||
this.synchronizeHostData();
|
||||
|
||||
filename = TypeScript.switchToForwardSlashes(filename);
|
||||
|
||||
var document = this.documentsByName[filename];
|
||||
var sourceUnit = document.sourceUnit();
|
||||
|
||||
if (CompletionHelpers.isCompletionListBlocker(document.syntaxTree().sourceUnit(), position)) {
|
||||
this.logger.log("Returning an empty list because completion was blocked.");
|
||||
return null;
|
||||
}
|
||||
|
||||
var node = TypeScript.ASTHelpers.getAstAtPosition(sourceUnit, position, /*useTrailingTriviaAsLimChar*/ true, /*forceInclusive*/ true);
|
||||
|
||||
if (node && node.kind() === TypeScript.SyntaxKind.IdentifierName &&
|
||||
start(node) === end(node)) {
|
||||
// Ignore missing name nodes
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
var isRightOfDot = false;
|
||||
if (node &&
|
||||
node.kind() === TypeScript.SyntaxKind.MemberAccessExpression &&
|
||||
end((<TypeScript.MemberAccessExpressionSyntax>node).expression) < position) {
|
||||
|
||||
isRightOfDot = true;
|
||||
node = (<TypeScript.MemberAccessExpressionSyntax>node).expression;
|
||||
}
|
||||
else if (node &&
|
||||
node.kind() === TypeScript.SyntaxKind.QualifiedName &&
|
||||
end((<TypeScript.QualifiedNameSyntax>node).left) < position) {
|
||||
|
||||
isRightOfDot = true;
|
||||
node = (<TypeScript.QualifiedNameSyntax>node).left;
|
||||
}
|
||||
else if (node && node.parent &&
|
||||
node.kind() === TypeScript.SyntaxKind.IdentifierName &&
|
||||
node.parent.kind() === TypeScript.SyntaxKind.MemberAccessExpression &&
|
||||
(<TypeScript.MemberAccessExpressionSyntax>node.parent).name === node) {
|
||||
|
||||
isRightOfDot = true;
|
||||
node = (<TypeScript.MemberAccessExpressionSyntax>node.parent).expression;
|
||||
}
|
||||
else if (node && node.parent &&
|
||||
node.kind() === TypeScript.SyntaxKind.IdentifierName &&
|
||||
node.parent.kind() === TypeScript.SyntaxKind.QualifiedName &&
|
||||
(<TypeScript.QualifiedNameSyntax>node.parent).right === node) {
|
||||
|
||||
isRightOfDot = true;
|
||||
node = (<TypeScript.QualifiedNameSyntax>node.parent).left;
|
||||
}
|
||||
|
||||
// TODO: this is a hack for now, we need a proper walking mechanism to verify that we have the correct node
|
||||
var mappedNode = this.getNodeAtPosition(document.sourceFile(), end(node) - 1);
|
||||
|
||||
Debug.assert(mappedNode, "Could not map a Fidelity node to an AST node");
|
||||
|
||||
// Get the completions
|
||||
this.activeCompletionSession = {
|
||||
filename: filename,
|
||||
position: position,
|
||||
entries: [],
|
||||
symbols: {},
|
||||
location: mappedNode,
|
||||
typeChecker: this.typeChecker
|
||||
};
|
||||
|
||||
// Right of dot member completion list
|
||||
if (isRightOfDot) {
|
||||
var type: ts.Type = this.typeChecker.getTypeOfExpression(mappedNode);
|
||||
if (!type) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var symbols = type.getApparentProperties();
|
||||
isMemberCompletion = true;
|
||||
this.getCompletionEntriesFromSymbols(symbols, this.activeCompletionSession);
|
||||
}
|
||||
else {
|
||||
var containingObjectLiteral = CompletionHelpers.getContainingObjectLiteralApplicableForCompletion(document.syntaxTree().sourceUnit(), position);
|
||||
|
||||
// Object literal expression, look up possible property names from contextual type
|
||||
if (containingObjectLiteral) {
|
||||
var searchPosition = Math.min(position, end(containingObjectLiteral));
|
||||
var path = TypeScript.ASTHelpers.getAstAtPosition(sourceUnit, searchPosition);
|
||||
// Get the object literal node
|
||||
|
||||
while (node && node.kind() !== TypeScript.SyntaxKind.ObjectLiteralExpression) {
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
if (!node || node.kind() !== TypeScript.SyntaxKind.ObjectLiteralExpression) {
|
||||
// AST Path look up did not result in the same node as Fidelity Syntax Tree look up.
|
||||
// Once we remove AST this will no longer be a problem.
|
||||
return null;
|
||||
}
|
||||
|
||||
isMemberCompletion = true;
|
||||
|
||||
//// Try to get the object members form contextual typing
|
||||
//var contextualMembers = this.compiler.getContextualMembersFromAST(node, document);
|
||||
//if (contextualMembers && contextualMembers.symbols && contextualMembers.symbols.length > 0) {
|
||||
// // get existing members
|
||||
// var existingMembers = this.compiler.getVisibleMemberSymbolsFromAST(node, document);
|
||||
|
||||
// // Add filtterd items to the completion list
|
||||
// this.getCompletionEntriesFromSymbols({
|
||||
// symbols: CompletionHelpers.filterContextualMembersList(contextualMembers.symbols, existingMembers, filename, position),
|
||||
// enclosingScopeSymbol: contextualMembers.enclosingScopeSymbol
|
||||
// }, entries);
|
||||
//}
|
||||
}
|
||||
// Get scope memebers
|
||||
else {
|
||||
isMemberCompletion = false;
|
||||
/// TODO filter meaning based on the current context
|
||||
var symbolMeanings = ts.SymbolFlags.Type | ts.SymbolFlags.Value | ts.SymbolFlags.Namespace;
|
||||
var symbols = this.typeChecker.getSymbolsInScope(mappedNode, symbolMeanings);
|
||||
|
||||
this.getCompletionEntriesFromSymbols(symbols, this.activeCompletionSession);
|
||||
}
|
||||
}
|
||||
|
||||
// Add keywords if this is not a member completion list
|
||||
if (!isMemberCompletion) {
|
||||
Array.prototype.push.apply(this.activeCompletionSession.entries, KeywordCompletions.getKeywordCompltions());
|
||||
}
|
||||
|
||||
return {
|
||||
isMemberCompletion: isMemberCompletion,
|
||||
entries: this.activeCompletionSession.entries
|
||||
};
|
||||
}
|
||||
getCompletionEntryDetails(filename: string, position: number, entryName: string) {
|
||||
return undefined;
|
||||
// Note: No need to call synchronizeHostData, as we have captured all the data we need
|
||||
// in the getCompletionsAtPosition erlier
|
||||
filename = TypeScript.switchToForwardSlashes(filename);
|
||||
|
||||
var session = this.activeCompletionSession;
|
||||
|
||||
// Ensure that the current active completion session is still valid for this request
|
||||
if (!session || session.filename !== filename || session.position !== position) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var symbol = this.activeCompletionSession.symbols[entryName];
|
||||
if (symbol) {
|
||||
var type = session.typeChecker.getTypeOfSymbol(symbol);
|
||||
Debug.assert(type, "Could not find type for symbol");
|
||||
var completionEntry = this.createCompletionEntry(symbol);
|
||||
return {
|
||||
name: entryName,
|
||||
kind: completionEntry.kind,
|
||||
kindModifiers: completionEntry.kindModifiers,
|
||||
type: session.typeChecker.typeToString(type, session.location),
|
||||
fullSymbolName: this.typeChecker.symbolToString(symbol, session.location),
|
||||
docComment: ""
|
||||
};
|
||||
}
|
||||
else {
|
||||
// No symbol, it is a keyword
|
||||
return {
|
||||
name: entryName,
|
||||
kind: ScriptElementKind.keyword,
|
||||
kindModifiers: ScriptElementKindModifier.none,
|
||||
type: undefined,
|
||||
fullSymbolName: entryName,
|
||||
docComment: undefined
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private getNodeAtPosition(sourceFile: ts.SourceFile, position: number) {
|
||||
@ -581,7 +786,7 @@ module TypeScript.Services {
|
||||
}
|
||||
}
|
||||
|
||||
getEnclosingDeclaration(node: ts.Node): ts.Node {
|
||||
private getEnclosingDeclaration(node: ts.Node): ts.Node {
|
||||
while (true) {
|
||||
node = node.parent;
|
||||
if (!node) {
|
||||
@ -601,10 +806,10 @@ module TypeScript.Services {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
getSymbolKind(symbol: ts.Symbol): string {
|
||||
var flags = symbol.getFlags();
|
||||
|
||||
if (flags & ts.SymbolFlags.Module) return ScriptElementKind.moduleElement;
|
||||
if (flags & ts.SymbolFlags.Class) return ScriptElementKind.classElement;
|
||||
if (flags & ts.SymbolFlags.Interface) return ScriptElementKind.interfaceElement;
|
||||
@ -621,20 +826,36 @@ module TypeScript.Services {
|
||||
if (flags & ts.SymbolFlags.Constructor) return ScriptElementKind.constructorImplementationElement;
|
||||
if (flags & ts.SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
|
||||
if (flags & ts.SymbolFlags.EnumMember) return ScriptElementKind.variableElement;
|
||||
|
||||
return ScriptElementKind.unknown;
|
||||
}
|
||||
|
||||
getTypeKind(type: ts.Type): string {
|
||||
var flags = type.getFlags();
|
||||
|
||||
if (flags & ts.TypeFlags.Enum) return ScriptElementKind.enumElement;
|
||||
if (flags & ts.TypeFlags.Class) return ScriptElementKind.classElement;
|
||||
if (flags & ts.TypeFlags.Interface) return ScriptElementKind.interfaceElement;
|
||||
if (flags & ts.TypeFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
|
||||
if (flags & ts.TypeFlags.Intrinsic) return ScriptElementKind.primitiveType;
|
||||
if (flags & ts.TypeFlags.StringLiteral) return ScriptElementKind.primitiveType;
|
||||
|
||||
return ScriptElementKind.unknown;
|
||||
}
|
||||
|
||||
getNodeModifiers(node: ts.Node): string {
|
||||
var flags = node.flags;
|
||||
var result: string[] = [];
|
||||
|
||||
if (flags & ts.NodeFlags.Private) result.push(ScriptElementKindModifier.privateMemberModifier);
|
||||
if (flags & ts.NodeFlags.Public) result.push(ScriptElementKindModifier.publicMemberModifier);
|
||||
if (flags & ts.NodeFlags.Static) result.push(ScriptElementKindModifier.staticModifier);
|
||||
if (flags & ts.NodeFlags.Export) result.push(ScriptElementKindModifier.exportedModifier);
|
||||
if (ts.isInAmbientContext(node)) result.push(ScriptElementKindModifier.ambientModifier);
|
||||
|
||||
return result.length > 0 ? result.join(',') : ScriptElementKindModifier.none;
|
||||
}
|
||||
|
||||
getTypeAtPosition(filename: string, position: number): TypeInfo {
|
||||
this.synchronizeHostData();
|
||||
|
||||
|
||||
@ -28,6 +28,7 @@ module ts {
|
||||
getFlags(): TypeFlags;
|
||||
getSymbol(): Symbol;
|
||||
getProperties(): Symbol[];
|
||||
getApparentProperties(): Symbol[];
|
||||
getCallSignatures(): Signature[];
|
||||
getConstructSignatures(): Signature[];
|
||||
getStringIndexType(): Type;
|
||||
@ -213,6 +214,9 @@ module ts {
|
||||
getProperties(): Symbol[] {
|
||||
return this.checker.getPropertiesOfType(this);
|
||||
}
|
||||
getApparentProperties(): Symbol[]{
|
||||
return this.checker.getAugmentedPropertiesOfApparentType(this);
|
||||
}
|
||||
getCallSignatures(): Signature[] {
|
||||
return this.checker.getSignaturesOfType(this, SignatureKind.Call);
|
||||
}
|
||||
|
||||
@ -34,6 +34,8 @@
|
||||
/// <reference path='Breakpoints.ts' />
|
||||
/// <reference path='indentation.ts' />
|
||||
/// <reference path='formatting\formatting.ts' />
|
||||
/// <reference path='completionHelpers.ts' />
|
||||
/// <reference path='keywordCompletions.ts' />
|
||||
|
||||
|
||||
/// <reference path='compiler\document.ts' />
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user