Initial work on classified quick info.

This commit is contained in:
Cyrus Najmabadi
2014-09-19 13:07:06 -07:00
parent 80bab05d07
commit f97bb60d6a
3 changed files with 219 additions and 29 deletions
+148 -29
View File
@@ -23,6 +23,20 @@ module ts {
return undefined;
}
interface SymbolWriter {
write(text: string, kind: SymbolDisplayPartKind, symbol: Symbol): void;
displayPartKind(symbol: Symbol): SymbolDisplayPartKind;
clear(): void;
}
interface DisplayPartsSymbolWriter extends SymbolWriter {
displayParts(): SymbolDisplayPart[];
}
interface StringSymbolWriter extends SymbolWriter {
string(): string;
}
/// fullTypeCheck denotes if this instance of the typechecker will be used to get semantic diagnostics.
/// If fullTypeCheck === true, then the typechecker should do every possible check to produce all errors
/// If fullTypeCheck === false, the typechecker can take shortcuts and skip checks that only produce errors.
@@ -62,7 +76,9 @@ module ts {
getTypeOfNode: getTypeOfNode,
getApparentType: getApparentType,
typeToString: typeToString,
typeToDisplayParts: undefined,
symbolToString: symbolToString,
symbolToDisplayParts: symbolToDisplayParts,
getAugmentedPropertiesOfApparentType: getAugmentedPropertiesOfApparentType,
getRootSymbol: getRootSymbol,
getContextualType: getContextualType,
@@ -895,51 +911,154 @@ module ts {
{ accessibility: SymbolAccessibility.NotAccessible, errorSymbolName: firstIdentifierName };
}
var displayPartWriters: DisplayPartsSymbolWriter[] = [];
var stringWriters: StringSymbolWriter[] = [];
function displayPartKind(symbol: Symbol): SymbolDisplayPartKind {
var flags = symbol.flags;
if (flags & SymbolFlags.Variable) {
return symbol.declarations && symbol.declarations.length > 0 && symbol.declarations[0].kind === SyntaxKind.Parameter
? SymbolDisplayPartKind.ParameterName
: SymbolDisplayPartKind.LocalName;
}
else if (flags & SymbolFlags.Property) { return SymbolDisplayPartKind.PropertyName; }
else if (flags & SymbolFlags.EnumMember) { return SymbolDisplayPartKind.EnumMemberName; }
else if (flags & SymbolFlags.Function) { return SymbolDisplayPartKind.FunctionName; }
else if (flags & SymbolFlags.Class) { return SymbolDisplayPartKind.ClassName; }
else if (flags & SymbolFlags.Interface) { return SymbolDisplayPartKind.InterfaceName; }
else if (flags & SymbolFlags.Enum) { return SymbolDisplayPartKind.EnumName; }
else if (flags & SymbolFlags.Module) { return SymbolDisplayPartKind.ModuleName; }
else if (flags & SymbolFlags.Method) { return SymbolDisplayPartKind.MethodName; }
else if (flags & SymbolFlags.TypeParameter) { return SymbolDisplayPartKind.TypeParameterName; }
return SymbolDisplayPartKind.Text;
}
function getDisplayPartWriter(): DisplayPartsSymbolWriter {
if (displayPartWriters.length == 0) {
var displayParts: SymbolDisplayPart[] = [];
return {
displayParts: () => displayParts,
write: (text, kind, symbol) => displayParts.push({ text: text, kind: kind, symbol: symbol }),
clear: () => displayParts = [],
displayPartKind: displayPartKind
};
}
return displayPartWriters.pop();
}
function getStringWriter(): StringSymbolWriter {
if (stringWriters.length == 0) {
var str = "";
return {
string: () => str,
write: text => str += text,
clear: () => str = "",
displayPartKind: (symbol: Symbol): SymbolDisplayPartKind => undefined
};
}
return stringWriters.pop();
}
function releaseDisplayPartWriter(writer: DisplayPartsSymbolWriter) {
writer.clear();
displayPartWriters.push(writer);
}
function releaseStringWriter(writer: StringSymbolWriter) {
writer.clear()
stringWriters.push(writer);
}
function symbolToDisplayParts(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): SymbolDisplayPart[] {
var writer = getDisplayPartWriter();
writeSymbol(symbol, enclosingDeclaration, meaning, writer);
var result = writer.displayParts();
releaseDisplayPartWriter(writer);
return result;
}
function symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string {
var writer = getStringWriter();
writeSymbol(symbol, enclosingDeclaration, meaning, writer);
var result = writer.string();
releaseStringWriter(writer);
return result;
}
// Enclosing declaration is optional when we don't want to get qualified name in the enclosing declaration scope
// Meaning needs to be specified if the enclosing declaration is given
function symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags) {
function getSymbolName(symbol: Symbol) {
function writeSymbol(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, writer: SymbolWriter): void {
function writeSymbolName(symbol: Symbol): void {
if (symbol.declarations && symbol.declarations.length > 0) {
var declaration = symbol.declarations[0];
if (declaration.name) {
return identifierToString(declaration.name);
writer.write(identifierToString(declaration.name), writer.displayPartKind(symbol), symbol);
return;
}
}
writer.write(symbol.name, writer.displayPartKind(symbol), symbol);
}
var needsDot = false;
function walkSymbol(symbol: Symbol, meaning: SymbolFlags): void {
if (symbol) {
var accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning);
if (!accessibleSymbolChain ||
needsQualification(accessibleSymbolChain[0], enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) {
// Go up and add our parent.
walkSymbol(
getParentOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol),
getQualifiedLeftMeaning(meaning));
}
if (accessibleSymbolChain) {
for (var i = 0, n = accessibleSymbolChain.length; i < n; i++) {
if (needsDot) {
writer.write(".", SymbolDisplayPartKind.Punctuation, /*symbol:*/ undefined);
}
writeSymbolName(accessibleSymbolChain[i]);
needsDot = true;
}
}
else {
// If we didn't find accessible symbol chain for this symbol, break if this is external module
if (!needsDot && ts.forEach(symbol.declarations, declaration => hasExternalModuleSymbol(declaration))) {
return;
}
if (needsDot) {
writer.write(".", SymbolDisplayPartKind.Punctuation, /*symbol:*/ undefined);
}
writeSymbolName(symbol);
needsDot = true;
}
}
return symbol.name;
}
// Get qualified name
if (enclosingDeclaration &&
// TypeParameters do not need qualification
!(symbol.flags & SymbolFlags.TypeParameter)) {
var symbolName: string;
while (symbol) {
var isFirstName = !symbolName;
var accessibleSymbolChain = getAccessibleSymbolChain(symbol, enclosingDeclaration, meaning);
var currentSymbolName: string;
if (accessibleSymbolChain) {
currentSymbolName = ts.map(accessibleSymbolChain, accessibleSymbol => getSymbolName(accessibleSymbol)).join(".");
}
else {
// If we didn't find accessible symbol chain for this symbol, break if this is external module
if (!isFirstName && ts.forEach(symbol.declarations, declaration => hasExternalModuleSymbol(declaration))) {
break;
}
currentSymbolName = getSymbolName(symbol);
}
symbolName = currentSymbolName + (isFirstName ? "" : ("." + symbolName));
if (accessibleSymbolChain && !needsQualification(accessibleSymbolChain[0], enclosingDeclaration, accessibleSymbolChain.length === 1 ? meaning : getQualifiedLeftMeaning(meaning))) {
break;
}
symbol = getParentOfSymbol(accessibleSymbolChain ? accessibleSymbolChain[0] : symbol);
meaning = getQualifiedLeftMeaning(meaning);
}
return symbolName;
walkSymbol(symbol, meaning);
return;
}
return getSymbolName(symbol);
return writeSymbolName(symbol);
}
function writeSymbolToTextWriter(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags, writer: TextWriter) {
+38
View File
@@ -638,6 +638,8 @@ module ts {
getApparentType(type: Type): ApparentType;
typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string;
typeToDisplayParts(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[];
symbolToDisplayParts(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): SymbolDisplayPart[];
getFullyQualifiedName(symbol: Symbol): string;
getAugmentedPropertiesOfApparentType(type: Type): Symbol[];
getRootSymbol(symbol: Symbol): Symbol;
@@ -1169,6 +1171,42 @@ module ts {
verticalTab = 0x0B, // \v
}
export class SymbolDisplayPart {
constructor(public text: string,
public kind: SymbolDisplayPartKind,
public symbol: Symbol) {
}
}
export enum SymbolDisplayPartKind {
AliasName,
ClassName,
EnumName,
EventName,
FieldName,
InterfaceName,
Keyword,
LabelName,
LineBreak,
NumericLiteral,
StringLiteral,
LocalName,
MethodName,
ModuleName,
NamespaceName,
Operator,
ParameterName,
PropertyName,
Punctuation,
Space,
AnonymousTypeIndicator,
Text,
TypeParameterName,
EnumMemberName,
FunctionName,
RegularExpressionLiteral,
}
export interface CancellationToken {
isCancellationRequested(): boolean;
}
+33
View File
@@ -495,6 +495,7 @@ module ts {
getCompletionEntryDetails(fileName: string, position: number, entryName: string): CompletionEntryDetails;
getTypeAtPosition(fileName: string, position: number): TypeInfo;
getQuickInfo(fileName: string, position: number): SymbolDisplayPart[];
getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TypeScript.TextSpan;
@@ -652,6 +653,14 @@ module ts {
text: string;
}
export class QuickInfo {
constructor(public kind: string,
public kindModifiers: string,
public textSpan: TypeScript.TextSpan,
public displayParts: SymbolDisplayPart[]) {
}
}
export class TypeInfo {
constructor(
public memberName: TypeScript.MemberName,
@@ -2212,6 +2221,29 @@ module ts {
}
/// QuickInfo
function getQuickInfo(fileName: string, position: number): SymbolDisplayPart[] {
synchronizeHostData();
fileName = TypeScript.switchToForwardSlashes(fileName);
var sourceFile = getSourceFile(fileName);
var node = getNodeAtPosition(sourceFile, position);
if (!node) {
return undefined;
}
var symbol = typeInfoResolver.getSymbolInfo(node);
return symbol ? typeInfoResolver.symbolToDisplayParts(symbol) : [];
//var type = symbol && typeInfoResolver.getTypeOfSymbol(symbol);
//if (type) {
// return new TypeInfo(
// new TypeScript.MemberNameString(typeInfoResolver.typeToString(type)),
// "", typeInfoResolver.symbolToString(symbol, getContainerNode(node)),
// getSymbolKind(symbol), TypeScript.TextSpan.fromBounds(node.pos, node.end));
//}
//return undefined;
}
function getTypeAtPosition(fileName: string, position: number): TypeInfo {
synchronizeHostData();
@@ -4026,6 +4058,7 @@ module ts {
getCompletionsAtPosition: getCompletionsAtPosition,
getCompletionEntryDetails: getCompletionEntryDetails,
getTypeAtPosition: getTypeAtPosition,
getQuickInfo: getQuickInfo,
getSignatureHelpItems: (filename, position): SignatureHelpItems => null,
getSignatureHelpCurrentArgumentState: (fileName, position, applicableSpanStart): SignatureHelpState => null,
getDefinitionAtPosition: getDefinitionAtPosition,