Skip to content

Fix how arguments and undefined are shown in the quickInfo #885

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 13, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,12 @@ module ts {
writeTypeParameter: writeTypeParameter,
writeTypeParametersOfSymbol: writeTypeParametersOfSymbol,
isImplementationOfOverload: isImplementationOfOverload,
getAliasedSymbol: resolveImport
getAliasedSymbol: resolveImport,
isUndefinedSymbol: symbol => symbol === undefinedSymbol,
isArgumentsSymbol: symbol => symbol === argumentsSymbol
};

var undefinedSymbol = createSymbol(SymbolFlags.Undefined | SymbolFlags.Property | SymbolFlags.Transient, "undefined");
var undefinedSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "undefined");
var argumentsSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "arguments");
var unknownSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "unknown");
var resolvingSymbol = createSymbol(SymbolFlags.Transient, "__resolving__");
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,8 @@ module ts {
writeTypeParameter(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
writeTypeParametersOfSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags): void;
isImplementationOfOverload(node: FunctionDeclaration): boolean;
isUndefinedSymbol(symbol: Symbol): boolean;
isArgumentsSymbol(symbol: Symbol): boolean;

// Returns the constant value of this enum member, or 'undefined' if the enum member has a
// computed value.
Expand Down Expand Up @@ -767,8 +769,6 @@ module ts {
Transient = 0x02000000, // Transient symbol (created during type check)
Prototype = 0x04000000, // Symbol for the prototype property (without source code representation)

Undefined = 0x08000000, // Symbol for the undefined

Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor,
Type = Class | Interface | Enum | TypeLiteral | ObjectLiteral | TypeParameter,
Namespace = ValueModule | NamespaceModule,
Expand Down
35 changes: 20 additions & 15 deletions src/services/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2250,7 +2250,7 @@ module ts {
return undefined;
}

function createCompletionEntry(symbol: Symbol): CompletionEntry {
function createCompletionEntry(symbol: Symbol, typeChecker: TypeChecker): 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)
Expand All @@ -2261,15 +2261,15 @@ module ts {

return {
name: displayName,
kind: getSymbolKind(symbol),
kind: getSymbolKind(symbol, typeChecker),
kindModifiers: getSymbolModifiers(symbol)
};
}

function getCompletionsAtPosition(filename: string, position: number, isMemberCompletion: boolean) {
function getCompletionEntriesFromSymbols(symbols: Symbol[], session: CompletionSession): void {
forEach(symbols, symbol => {
var entry = createCompletionEntry(symbol);
var entry = createCompletionEntry(symbol, session.typeChecker);
if (entry && !lookUp(session.symbols, entry.name)) {
session.entries.push(entry);
session.symbols[entry.name] = symbol;
Expand Down Expand Up @@ -2608,7 +2608,7 @@ module ts {
if (symbol) {
var type = session.typeChecker.getTypeOfSymbol(symbol);
Debug.assert(type, "Could not find type for symbol");
var completionEntry = createCompletionEntry(symbol);
var completionEntry = createCompletionEntry(symbol, session.typeChecker);
// TODO(drosen): Right now we just permit *all* semantic meanings when calling 'getSymbolKind'
// which is permissible given that it is backwards compatible; but really we should consider
// passing the meaning for the node so that we don't report that a suggestion for a value is an interface.
Expand Down Expand Up @@ -2657,15 +2657,15 @@ module ts {
}

// TODO(drosen): use contextual SemanticMeaning.
function getSymbolKind(symbol: Symbol): string {
function getSymbolKind(symbol: Symbol, typeResolver: TypeChecker): string {
var flags = typeInfoResolver.getRootSymbol(symbol).getFlags();

if (flags & SymbolFlags.Class) return ScriptElementKind.classElement;
if (flags & SymbolFlags.Enum) return ScriptElementKind.enumElement;
if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement;
if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;

var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags);
var result = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, flags, typeResolver);
if (result === ScriptElementKind.unknown) {
if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
if (flags & SymbolFlags.EnumMember) return ScriptElementKind.variableElement;
Expand All @@ -2675,16 +2675,19 @@ module ts {
return result;
}

function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol: Symbol, flags: SymbolFlags) {
function getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol: Symbol, flags: SymbolFlags, typeResolver: TypeChecker) {
if (typeResolver.isUndefinedSymbol(symbol)) {
return ScriptElementKind.variableElement;
}
if (typeResolver.isArgumentsSymbol(symbol)) {
return ScriptElementKind.localVariableElement;
}
if (flags & SymbolFlags.Variable) {
if (isFirstDeclarationOfSymbolParameter(symbol)) {
return ScriptElementKind.parameterElement;
}
return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localVariableElement : ScriptElementKind.variableElement;
}
if (flags & SymbolFlags.Undefined) {
return ScriptElementKind.variableElement;
}
if (flags & SymbolFlags.Function) return isLocalVariableOrFunction(symbol) ? ScriptElementKind.localFunctionElement : ScriptElementKind.functionElement;
if (flags & SymbolFlags.GetAccessor) return ScriptElementKind.memberGetAccessorElement;
if (flags & SymbolFlags.SetAccessor) return ScriptElementKind.memberSetAccessorElement;
Expand Down Expand Up @@ -2746,7 +2749,7 @@ module ts {
var displayParts: SymbolDisplayPart[] = [];
var documentation: SymbolDisplayPart[];
var symbolFlags = typeResolver.getRootSymbol(symbol).flags;
var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags);
var symbolKind = getSymbolKindOfConstructorPropertyMethodAccessorFunctionOrVar(symbol, symbolFlags, typeResolver);
var hasAddedSymbolInfo: boolean;
// Class at constructor site need to be shown as constructor apart from property,method, vars
if (symbolKind !== ScriptElementKind.unknown || symbolFlags & SymbolFlags.Class || symbolFlags & SymbolFlags.Import) {
Expand Down Expand Up @@ -2952,8 +2955,10 @@ module ts {
if (symbolKind !== ScriptElementKind.unknown) {
if (type) {
addPrefixForAnyFunctionOrVar(symbol, symbolKind);
// For properties, variables and local vars: show the type
if (symbolKind === ScriptElementKind.memberVariableElement ||
symbolFlags & SymbolFlags.Variable) {
symbolFlags & SymbolFlags.Variable ||
symbolKind === ScriptElementKind.localVariableElement) {
displayParts.push(punctuationPart(SyntaxKind.ColonToken));
displayParts.push(spacePart());
// If the type is type parameter, format it specially
Expand All @@ -2978,7 +2983,7 @@ module ts {
}
}
else {
symbolKind = getSymbolKind(symbol);
symbolKind = getSymbolKind(symbol, typeResolver);
}
}

Expand Down Expand Up @@ -3184,7 +3189,7 @@ module ts {

var declarations = symbol.getDeclarations();
var symbolName = typeInfoResolver.symbolToString(symbol); // Do not get scoped name, just the name of the symbol
var symbolKind = getSymbolKind(symbol);
var symbolKind = getSymbolKind(symbol, typeInfoResolver);
var containerSymbol = symbol.parent;
var containerName = containerSymbol ? typeInfoResolver.symbolToString(containerSymbol, node) : "";

Expand Down Expand Up @@ -5175,7 +5180,7 @@ module ts {

// Only allow a symbol to be renamed if it actually has at least one declaration.
if (symbol && symbol.getDeclarations() && symbol.getDeclarations().length > 0) {
var kind = getSymbolKind(symbol);
var kind = getSymbolKind(symbol, typeInfoResolver);
if (kind) {
return getRenameInfo(symbol.name, typeInfoResolver.getFullyQualifiedName(symbol), kind,
getSymbolModifiers(symbol),
Expand Down
8 changes: 8 additions & 0 deletions tests/cases/fourslash/quickInfoOnArgumentsInsideFunction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// <reference path='fourslash.ts'/>

////function foo(x: string) {
//// return /*1*/arguments;
////}

goTo.marker('1');
verify.quickInfoIs('(local var) arguments: IArguments');