wire quick info
This commit is contained in:
Родитель
05eeba5bc9
Коммит
f8767a5617
|
@ -739,10 +739,10 @@ module ts {
|
|||
};
|
||||
}
|
||||
|
||||
function typeToString(type: Type, flags?: TypeFormatFlags): string {
|
||||
function typeToString(type: Type, enclosingDeclaration?:Node, flags?: TypeFormatFlags): string {
|
||||
var stringWriter = createSingleLineTextWriter();
|
||||
// TODO(shkamat): typeToString should take enclosingDeclaration as input, once we have implemented enclosingDeclaration
|
||||
writeTypeToTextWriter(type, /*enclosingDeclaration*/ null, flags, stringWriter);
|
||||
writeTypeToTextWriter(type, enclosingDeclaration, flags, stringWriter);
|
||||
return stringWriter.getText();
|
||||
}
|
||||
|
||||
|
@ -1379,7 +1379,7 @@ module ts {
|
|||
type.baseTypes.push(baseType);
|
||||
}
|
||||
else {
|
||||
error(declaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, TypeFormatFlags.WriteArrayAsGenericType));
|
||||
error(declaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1420,7 +1420,7 @@ module ts {
|
|||
type.baseTypes.push(baseType);
|
||||
}
|
||||
else {
|
||||
error(declaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, TypeFormatFlags.WriteArrayAsGenericType));
|
||||
error(declaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1987,7 +1987,7 @@ module ts {
|
|||
type = createTypeReference(<GenericType>type, map(node.typeArguments, t => getTypeFromTypeNode(t)));
|
||||
}
|
||||
else {
|
||||
error(node, Diagnostics.Generic_type_0_requires_1_type_argument_s, typeToString(type, TypeFormatFlags.WriteArrayAsGenericType), typeParameters.length);
|
||||
error(node, Diagnostics.Generic_type_0_requires_1_type_argument_s, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType), typeParameters.length);
|
||||
type = undefined;
|
||||
}
|
||||
}
|
||||
|
@ -6194,7 +6194,12 @@ module ts {
|
|||
function getSymbolOfIdentifier(identifier: Identifier) {
|
||||
if (isExpression(identifier)) {
|
||||
if (isRightSideOfQualifiedName()) {
|
||||
// TODO
|
||||
var node = <QualifiedName>identifier.parent;
|
||||
var symbol = getNodeLinks(node).resolvedSymbol;
|
||||
if (!symbol) {
|
||||
checkPropertyAccess(node);
|
||||
}
|
||||
return getNodeLinks(node).resolvedSymbol;
|
||||
}
|
||||
return resolveEntityName(identifier, identifier, SymbolFlags.Value);
|
||||
}
|
||||
|
@ -6425,7 +6430,11 @@ module ts {
|
|||
getReturnTypeOfSignature: getReturnTypeOfSignature,
|
||||
resolveEntityName: resolveEntityName,
|
||||
getSymbolsInScope: getSymbolsInScope,
|
||||
getSymbolOfIdentifier: getSymbolOfIdentifier
|
||||
getSymbolOfIdentifier: getSymbolOfIdentifier,
|
||||
getTypeOfExpression: checkExpression,
|
||||
typeToString: typeToString,
|
||||
symbolToString: symbolToString,
|
||||
writeTypeToTextWriter: writeTypeToTextWriter
|
||||
};
|
||||
return checker;
|
||||
}
|
||||
|
|
|
@ -599,6 +599,10 @@ module ts {
|
|||
resolveEntityName(location: Node, name: EntityName, meaning: SymbolFlags): Symbol;
|
||||
getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];
|
||||
getSymbolOfIdentifier(identifier: Identifier): Symbol;
|
||||
getTypeOfExpression(node: Expression, contextualType?: Type, contextualMapper?: TypeMapper): Type;
|
||||
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;
|
||||
}
|
||||
|
||||
export interface TextWriter {
|
||||
|
|
|
@ -564,8 +564,122 @@ module TypeScript.Services {
|
|||
getCompletionEntryDetails(filename: string, position: number, entryName: string) {
|
||||
return undefined;
|
||||
}
|
||||
getTypeAtPosition(filename: string, position: number) {
|
||||
return undefined;
|
||||
|
||||
private getNodeAtPosition(sourceFile: ts.SourceFile, position: number) {
|
||||
var current: ts.Node = sourceFile;
|
||||
outer: while (true) {
|
||||
// find the child that has this
|
||||
for (var i = 0, n = current.getChildCount(); i < n; i++) {
|
||||
var child = current.getChildAt(i);
|
||||
if (ts.getTokenPosOfNode(child) <= position && position < child.end) {
|
||||
current = child;
|
||||
continue outer;
|
||||
}
|
||||
if (child.end > position) break;
|
||||
}
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
getEnclosingDeclaration(node: ts.Node): ts.Node {
|
||||
while (true) {
|
||||
node = node.parent;
|
||||
if (!node) {
|
||||
return node;
|
||||
}
|
||||
switch (node.kind) {
|
||||
case ts.SyntaxKind.Method:
|
||||
case ts.SyntaxKind.FunctionDeclaration:
|
||||
case ts.SyntaxKind.FunctionExpression:
|
||||
case ts.SyntaxKind.GetAccessor:
|
||||
case ts.SyntaxKind.SetAccessor:
|
||||
case ts.SyntaxKind.ClassDeclaration:
|
||||
case ts.SyntaxKind.InterfaceDeclaration:
|
||||
case ts.SyntaxKind.EnumDeclaration:
|
||||
case ts.SyntaxKind.ModuleDeclaration:
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
if (flags & ts.SymbolFlags.Enum) return ScriptElementKind.enumElement;
|
||||
if (flags & ts.SymbolFlags.Variable) return ScriptElementKind.variableElement;
|
||||
if (flags & ts.SymbolFlags.Function) return ScriptElementKind.functionElement;
|
||||
if (flags & ts.SymbolFlags.GetAccessor) return ScriptElementKind.memberGetAccessorElement;
|
||||
if (flags & ts.SymbolFlags.SetAccessor) return ScriptElementKind.memberSetAccessorElement;
|
||||
if (flags & ts.SymbolFlags.Method) return ScriptElementKind.memberFunctionElement;
|
||||
if (flags & ts.SymbolFlags.Property) return ScriptElementKind.memberVariableElement;
|
||||
if (flags & ts.SymbolFlags.IndexSignature) return ScriptElementKind.indexSignatureElement;
|
||||
if (flags & ts.SymbolFlags.ConstructSignature) return ScriptElementKind.constructSignatureElement;
|
||||
if (flags & ts.SymbolFlags.CallSignature) return ScriptElementKind.callSignatureElement;
|
||||
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;
|
||||
}
|
||||
|
||||
getTypeAtPosition(filename: string, position: number): TypeInfo {
|
||||
this.synchronizeHostData();
|
||||
|
||||
filename = TypeScript.switchToForwardSlashes(filename);
|
||||
var document = this.documentsByName[filename];
|
||||
var node = this.getNodeAtPosition(document.sourceFile(), position);
|
||||
if (!node) return undefined;
|
||||
|
||||
switch (node.kind) {
|
||||
// A declaration
|
||||
case ts.SyntaxKind.Identifier:
|
||||
if (node.parent.kind === ts.SyntaxKind.CallExpression || node.parent.kind === ts.SyntaxKind.NewExpression) {
|
||||
// TODO: handle new and call expressions
|
||||
}
|
||||
|
||||
var symbol = this.typeChecker. getSymbolOfIdentifier(<ts.Identifier>node);
|
||||
Debug.assert(symbol, "getTypeAtPosition: Could not find symbol for node");
|
||||
var type = this.typeChecker.getTypeOfSymbol(symbol);
|
||||
|
||||
return {
|
||||
memberName: new MemberNameString(this.typeChecker.typeToString(type)),
|
||||
docComment: "",
|
||||
fullSymbolName: this.typeChecker.symbolToString(symbol, this.getEnclosingDeclaration(node)),
|
||||
kind: this.getSymbolKind(symbol),
|
||||
minChar: node.pos,
|
||||
limChar: node.end
|
||||
};
|
||||
|
||||
// An Expression
|
||||
case ts.SyntaxKind.ThisKeyword:
|
||||
case ts.SyntaxKind.QualifiedName:
|
||||
case ts.SyntaxKind.SuperKeyword:
|
||||
case ts.SyntaxKind.StringLiteral:
|
||||
var type = this.typeChecker.getTypeOfExpression(node);
|
||||
Debug.assert(type, "getTypeAtPosition: Could not find type for node");
|
||||
return {
|
||||
memberName: new MemberNameString(""),
|
||||
docComment: "",
|
||||
fullSymbolName: this.typeChecker.typeToString(type, this.getEnclosingDeclaration(node)),
|
||||
kind: this.getTypeKind(type),
|
||||
minChar: node.pos,
|
||||
limChar: node.end
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
getSignatureAtPosition(filename: string, position: number) {
|
||||
return undefined;
|
||||
|
@ -589,7 +703,6 @@ module TypeScript.Services {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
private getTypeInfoEligiblePath(filename: string, position: number, isConstructorValidPosition: boolean) {
|
||||
var sourceUnit = this._syntaxTreeCache.getCurrentFileSyntaxTree(filename).sourceUnit();
|
||||
|
||||
|
|
|
@ -41,88 +41,6 @@ module ts {
|
|||
getReturnType(): Type;
|
||||
}
|
||||
|
||||
interface HostFileInformation {
|
||||
version: string;
|
||||
isOpen: boolean;
|
||||
byteOrderMark: ByteOrderMark;
|
||||
sourceText?: IScriptSnapshot;
|
||||
}
|
||||
|
||||
//
|
||||
// Public services of a language service instance associated
|
||||
// with a language service host instance
|
||||
//
|
||||
export interface LanguageService {
|
||||
getSyntacticDiagnostics(filename: string): Diagnostic[];
|
||||
getSemanticDiagnostics(filename: string): Diagnostic[];
|
||||
}
|
||||
|
||||
//
|
||||
// Public interface of the host of a language service instance.
|
||||
//
|
||||
export interface LanguageServiceHost {
|
||||
log(s: string): void;
|
||||
|
||||
getCompilationSettings(): CompilerOptions;
|
||||
|
||||
getScriptFileNames(): string[];
|
||||
getScriptVersion(filename: string): string;
|
||||
getScriptIsOpen(filename: string): boolean;
|
||||
getScriptByteOrderMark(filename: string): ByteOrderMark;
|
||||
getScriptSnapshot(filename: string): IScriptSnapshot;
|
||||
getLocalizedDiagnosticMessages(): any;
|
||||
//getCancellationToken(): CancellationToken;
|
||||
}
|
||||
|
||||
// Represents an immutable snapshot of a script at a specified time. Once acquired, the
|
||||
// snapshot is observably immutable. i.e. the same calls with the same parameters will return
|
||||
// the same values.
|
||||
export interface IScriptSnapshot {
|
||||
// Get's a portion of the script snapshot specified by [start, end).
|
||||
getText(start: number, end: number): string;
|
||||
|
||||
// Get's the length of this script snapshot.
|
||||
getLength(): number;
|
||||
|
||||
// This call returns the array containing the start position of every line.
|
||||
// i.e."[0, 10, 55]". TODO: consider making this optional. The language service could
|
||||
// always determine this (albeit in a more expensive manner).
|
||||
getLineStartPositions(): number[];
|
||||
|
||||
// Gets the TextChangeRange that describe how the text changed between this text and
|
||||
// an older version. This informatoin is used by the incremental parser to determine
|
||||
// what sections of the script need to be reparsed. 'null' can be returned if the
|
||||
// change range cannot be determined. However, in that case, incremental parsing will
|
||||
// not happen and the entire document will be reparsed.
|
||||
getChangeRange(oldSnapshot: IScriptSnapshot): TextChangeRange;
|
||||
}
|
||||
|
||||
export interface Span {
|
||||
start(): number;
|
||||
end(): number;
|
||||
}
|
||||
|
||||
export interface TextChange {
|
||||
span: Span;
|
||||
newText: string;
|
||||
}
|
||||
|
||||
export interface TextChangeRange {
|
||||
span(): Span;
|
||||
newLength(): number;
|
||||
}
|
||||
|
||||
export enum ByteOrderMark {
|
||||
None = 0,
|
||||
Utf8 = 1,
|
||||
Utf16BigEndian = 2,
|
||||
Utf16LittleEndian = 3,
|
||||
}
|
||||
|
||||
export interface CancellationToken {
|
||||
isCancellationRequested(): boolean;
|
||||
}
|
||||
|
||||
var scanner: Scanner = createScanner(ScriptTarget.ES5);
|
||||
|
||||
var emptyArray: any [] = [];
|
||||
|
@ -335,86 +253,6 @@ module ts {
|
|||
}
|
||||
}
|
||||
|
||||
export function createLanguageService(host: LanguageServiceHost): LanguageService {
|
||||
|
||||
var program: Program;
|
||||
var typeChecker: TypeChecker;
|
||||
var filesByName: Map<HostFileInformation>;
|
||||
|
||||
function createCompilerHost(): CompilerHost {
|
||||
return {
|
||||
getSourceFile: (filename, languageVersion) => {
|
||||
var hostFile = filesByName[filename];
|
||||
|
||||
// TODO use the document registry to get or update
|
||||
|
||||
if (!hostFile.sourceText) {
|
||||
hostFile.sourceText = host.getScriptSnapshot(filename);
|
||||
}
|
||||
|
||||
// TODO add support for IScriptSnapshot in the parser
|
||||
return createSourceFile(filename, hostFile.sourceText.getText(0, hostFile.sourceText.getLength()), languageVersion);
|
||||
},
|
||||
// Need something that doesn't depend on sys.ts here
|
||||
getDefaultLibFilename: () => combinePaths(getDirectoryPath(normalizePath(sys.getExecutingFilePath())), "lib.d.ts"),
|
||||
getCancellationToken: (): CancellationToken => undefined,
|
||||
writeFile: (fileName, data) => {
|
||||
throw Error("TODO: write file");
|
||||
},
|
||||
getCurrentDirectory: (): string => {
|
||||
throw Error("TODO: getCurrentDirectory");
|
||||
},
|
||||
getCanonicalFileName: getCanonicalFileName,
|
||||
useCaseSensitiveFileNames: () => sys.useCaseSensitiveFileNames
|
||||
};
|
||||
}
|
||||
|
||||
function synchronizeHostData(): void {
|
||||
// Build the cache
|
||||
filesByName = {};
|
||||
var files = host.getScriptFileNames();
|
||||
forEach(files, (f) => {
|
||||
filesByName[f] = {
|
||||
version: host.getScriptVersion(f),
|
||||
isOpen: host.getScriptIsOpen(f),
|
||||
byteOrderMark: host.getScriptByteOrderMark(f)
|
||||
};
|
||||
});
|
||||
|
||||
var currentProgram = program;
|
||||
|
||||
var options = host.getCompilationSettings();
|
||||
|
||||
// update the program
|
||||
program = createProgram(files, options, createCompilerHost());
|
||||
|
||||
// Update the typeChecker
|
||||
typeChecker = program.getTypeChecker();
|
||||
|
||||
// TODO release old sources from the registry
|
||||
if (currentProgram) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function getSyntacticDiagnostics(filename: string): Diagnostic[] {
|
||||
synchronizeHostData();
|
||||
var sourceFile = program.getSourceFile(filename);
|
||||
return sourceFile ? program.getDiagnostics(sourceFile) : [];
|
||||
}
|
||||
|
||||
function getSemanticDiagnostics(filename: string): Diagnostic[] {
|
||||
synchronizeHostData();
|
||||
var sourceFile = program.getSourceFile(filename);
|
||||
return sourceFile ? typeChecker.getDiagnostics(sourceFile) : [];
|
||||
}
|
||||
|
||||
return {
|
||||
getSyntacticDiagnostics: getSyntacticDiagnostics,
|
||||
getSemanticDiagnostics: getSemanticDiagnostics,
|
||||
};
|
||||
}
|
||||
|
||||
function initializeServices() {
|
||||
objectAllocator = {
|
||||
getNodeConstructor: kind => {
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
// limitations under the License.
|
||||
//
|
||||
|
||||
/// <reference path='services.ts' />
|
||||
|
||||
/// <reference path='core\references.ts' />
|
||||
/// <reference path='resources\references.ts' />
|
||||
|
|
Загрузка…
Ссылка в новой задаче