diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0a40d881433..6c9a943b951 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -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__"); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 68ef296e263..c0571bdfb60 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -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. @@ -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, diff --git a/src/services/services.ts b/src/services/services.ts index 05aeb47f7c6..0e8b00f2faf 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -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) @@ -2261,7 +2261,7 @@ module ts { return { name: displayName, - kind: getSymbolKind(symbol), + kind: getSymbolKind(symbol, typeChecker), kindModifiers: getSymbolModifiers(symbol) }; } @@ -2269,7 +2269,7 @@ module ts { 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; @@ -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. @@ -2657,7 +2657,7 @@ 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; @@ -2665,7 +2665,7 @@ module ts { 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; @@ -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; @@ -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) { @@ -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 @@ -2978,7 +2983,7 @@ module ts { } } else { - symbolKind = getSymbolKind(symbol); + symbolKind = getSymbolKind(symbol, typeResolver); } } @@ -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) : ""; @@ -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), diff --git a/tests/cases/fourslash/quickInfoOnArgumentsInsideFunction.ts b/tests/cases/fourslash/quickInfoOnArgumentsInsideFunction.ts new file mode 100644 index 00000000000..7ac1502ed8c --- /dev/null +++ b/tests/cases/fourslash/quickInfoOnArgumentsInsideFunction.ts @@ -0,0 +1,9 @@ +/// + +////function foo(x: string) { +//// return /*1*/arguments; +////} + +goTo.marker('1'); +debugger; +verify.quickInfoIs('(local var) arguments: IArguments'); \ No newline at end of file