Don't include completion in opening tag, include name of opening in closing tag

This commit is contained in:
Yui T
2015-12-08 18:54:29 -08:00
parent 06badd0e0d
commit 48894e5023
3 changed files with 40 additions and 11 deletions
+6 -2
View File
@@ -61,6 +61,7 @@ namespace ts {
getTypeCount: () => typeCount,
isUndefinedSymbol: symbol => symbol === undefinedSymbol,
isArgumentsSymbol: symbol => symbol === argumentsSymbol,
isUnknownSymbol: symbol => symbol === unknownSymbol,
getDiagnostics,
getGlobalDiagnostics,
@@ -7979,6 +7980,7 @@ namespace ts {
if (compilerOptions.noImplicitAny) {
error(node, Diagnostics.JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists, JsxNames.IntrinsicElements);
}
return unknownSymbol;
}
}
@@ -14574,7 +14576,7 @@ namespace ts {
return false;
}
function getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[] {
function getSymbolsInScope(location: Node, meaning: SymbolFlags, includeAllGlobalSymbols: boolean): Symbol[] {
const symbols: SymbolTable = {};
let memberFlags: NodeFlags = 0;
@@ -14637,7 +14639,9 @@ namespace ts {
location = location.parent;
}
copySymbols(globals, meaning);
if (includeAllGlobalSymbols) {
copySymbols(globals, meaning);
}
}
/**
+2 -1
View File
@@ -1717,7 +1717,7 @@ namespace ts {
getBaseTypes(type: InterfaceType): ObjectType[];
getReturnTypeOfSignature(signature: Signature): Type;
getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];
getSymbolsInScope(location: Node, meaning: SymbolFlags, includeAllGlobalSymbols: boolean): Symbol[];
getSymbolAtLocation(node: Node): Symbol;
getShorthandAssignmentValueSymbol(location: Node): Symbol;
getTypeAtLocation(node: Node): Type;
@@ -1733,6 +1733,7 @@ namespace ts {
isImplementationOfOverload(node: FunctionLikeDeclaration): boolean;
isUndefinedSymbol(symbol: Symbol): boolean;
isArgumentsSymbol(symbol: Symbol): boolean;
isUnknownSymbol(symbol: Symbol): boolean;
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean;
+32 -8
View File
@@ -3099,6 +3099,7 @@ namespace ts {
}
else if (kind === SyntaxKind.SlashToken && contextToken.parent.kind === SyntaxKind.JsxClosingElement) {
isStartingCloseTag = true;
location = contextToken;
}
}
}
@@ -3113,7 +3114,9 @@ namespace ts {
}
else if (isRightOfOpenTag) {
let tagSymbols = typeChecker.getJsxIntrinsicTagNames();
if (tryGetGlobalSymbols()) {
// If the currect cursor is inside JSX opening tag, the only meaningful completions are those of JSX.IntrinsicElements or users defined React.Component
// If the services can't find those symbols, then show nothing instead of including all the global symbols in the completion list.
if (tryGetGlobalSymbols(/*includeAllGlobalSymbols*/false)) {
symbols = tagSymbols.concat(symbols.filter(s => !!(s.flags & SymbolFlags.Value)));
}
else {
@@ -3123,8 +3126,12 @@ namespace ts {
isNewIdentifierLocation = false;
}
else if (isStartingCloseTag) {
let tagName = (<JsxElement>contextToken.parent.parent).openingElement.tagName;
symbols = [typeChecker.getSymbolAtLocation(tagName)];
const tagName = (<JsxElement>contextToken.parent.parent).openingElement.tagName;
const tagSymbol = typeChecker.getSymbolAtLocation(tagName);
if (!typeChecker.isUnknownSymbol(tagSymbol)) {
symbols = [tagSymbol];
}
isMemberCompletion = true;
isNewIdentifierLocation = false;
@@ -3133,7 +3140,7 @@ namespace ts {
// For JavaScript or TypeScript, if we're not after a dot, then just try to get the
// global symbols in scope. These results should be valid for either language as
// the set of symbols that can be referenced from this location.
if (!tryGetGlobalSymbols()) {
if (!tryGetGlobalSymbols(/*includeAllGlobalSymbols*/true)) {
return undefined;
}
}
@@ -3193,7 +3200,7 @@ namespace ts {
}
}
function tryGetGlobalSymbols(): boolean {
function tryGetGlobalSymbols(includeAllGlobalSymbols: boolean): boolean {
let objectLikeContainer: ObjectLiteralExpression | BindingPattern;
let namedImportsOrExports: NamedImportsOrExports;
let jsxContainer: JsxOpeningLikeElement;
@@ -3264,7 +3271,7 @@ namespace ts {
/// TODO filter meaning based on the current context
let symbolMeanings = SymbolFlags.Type | SymbolFlags.Value | SymbolFlags.Namespace | SymbolFlags.Alias;
symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings);
symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings, includeAllGlobalSymbols);
return true;
}
@@ -3831,7 +3838,23 @@ namespace ts {
}
else {
if (!symbols || symbols.length === 0) {
return undefined;
if (sourceFile.languageVariant === LanguageVariant.JSX &&
location.parent && location.parent.kind === SyntaxKind.JsxClosingElement) {
// In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag,
// instead of simply giving unknown value, the completion will return the tag-name of an associated opening-element.
// For example:
// var x = <div> </ /*1*/> completion list at "1" will contain "div" with type any
const tagName = (<JsxElement>location.parent.parent).openingElement.tagName;
entries.push({
name: (<Identifier>tagName).text,
kind: undefined,
kindModifiers: undefined,
sortText: "0",
});
}
else {
return undefined;
}
}
getCompletionEntriesFromSymbols(symbols, entries);
@@ -3907,6 +3930,7 @@ namespace ts {
function getCompletionEntriesFromSymbols(symbols: Symbol[], entries: CompletionEntry[]): Map<string> {
let start = new Date().getTime();
let uniqueNames: Map<string> = {};
if (symbols) {
for (let symbol of symbols) {
let entry = createCompletionEntry(symbol, location);
@@ -4439,7 +4463,7 @@ namespace ts {
let typeChecker = program.getTypeChecker();
let symbol = typeChecker.getSymbolAtLocation(node);
if (!symbol) {
if (!symbol || typeChecker.isUnknownSymbol(symbol)) {
// Try getting just type at this position and show
switch (node.kind) {
case SyntaxKind.Identifier: