This commit is contained in:
Mohamed Hegazy 2014-07-22 14:36:29 -07:00
Родитель 05eeba5bc9
Коммит f8767a5617
5 изменённых файлов: 137 добавлений и 172 удалений

Просмотреть файл

@ -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' />