mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-20 05:17:43 -05:00
Merge pull request #32266 from fuafa/properties-priorities
Add properties priority for completion
This commit is contained in:
@@ -2,10 +2,12 @@
|
||||
namespace ts.Completions {
|
||||
export enum SortText {
|
||||
LocationPriority = "0",
|
||||
SuggestedClassMembers = "1",
|
||||
GlobalsOrKeywords = "2",
|
||||
AutoImportSuggestions = "3",
|
||||
JavascriptIdentifiers = "4"
|
||||
OptionalMember = "1",
|
||||
MemberDeclaredBySpreadAssignment = "2",
|
||||
SuggestedClassMembers = "3",
|
||||
GlobalsOrKeywords = "4",
|
||||
AutoImportSuggestions = "5",
|
||||
JavascriptIdentifiers = "6"
|
||||
}
|
||||
export type Log = (message: string) => void;
|
||||
|
||||
@@ -1109,6 +1111,7 @@ namespace ts.Completions {
|
||||
const attrsType = jsxContainer && typeChecker.getContextualType(jsxContainer.attributes);
|
||||
if (!attrsType) return GlobalsSearch.Continue;
|
||||
symbols = filterJsxAttributes(getPropertiesForObjectExpression(attrsType, jsxContainer!.attributes, typeChecker), jsxContainer!.attributes.properties);
|
||||
setSortTextToOptionalMember();
|
||||
completionKind = CompletionKind.MemberLike;
|
||||
isNewIdentifierLocation = false;
|
||||
return GlobalsSearch.Success;
|
||||
@@ -1539,6 +1542,8 @@ namespace ts.Completions {
|
||||
// Add filtered items to the completion list
|
||||
symbols = filterObjectMembersList(typeMembers, Debug.assertDefined(existingMembers));
|
||||
}
|
||||
setSortTextToOptionalMember();
|
||||
|
||||
return GlobalsSearch.Success;
|
||||
}
|
||||
|
||||
@@ -1910,6 +1915,7 @@ namespace ts.Completions {
|
||||
return contextualMemberSymbols;
|
||||
}
|
||||
|
||||
const membersDeclaredBySpreadAssignment = createMap<true>();
|
||||
const existingMemberNames = createUnderscoreEscapedMap<boolean>();
|
||||
for (const m of existingMembers) {
|
||||
// Ignore omitted expressions for missing members
|
||||
@@ -1918,7 +1924,8 @@ namespace ts.Completions {
|
||||
m.kind !== SyntaxKind.BindingElement &&
|
||||
m.kind !== SyntaxKind.MethodDeclaration &&
|
||||
m.kind !== SyntaxKind.GetAccessor &&
|
||||
m.kind !== SyntaxKind.SetAccessor) {
|
||||
m.kind !== SyntaxKind.SetAccessor &&
|
||||
m.kind !== SyntaxKind.SpreadAssignment) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1929,7 +1936,10 @@ namespace ts.Completions {
|
||||
|
||||
let existingName: __String | undefined;
|
||||
|
||||
if (isBindingElement(m) && m.propertyName) {
|
||||
if (isSpreadAssignment(m)) {
|
||||
setMembersDeclaredBySpreadAssignment(m, membersDeclaredBySpreadAssignment);
|
||||
}
|
||||
else if (isBindingElement(m) && m.propertyName) {
|
||||
// include only identifiers in completion list
|
||||
if (m.propertyName.kind === SyntaxKind.Identifier) {
|
||||
existingName = m.propertyName.escapedText;
|
||||
@@ -1946,7 +1956,43 @@ namespace ts.Completions {
|
||||
existingMemberNames.set(existingName!, true); // TODO: GH#18217
|
||||
}
|
||||
|
||||
return contextualMemberSymbols.filter(m => !existingMemberNames.get(m.escapedName));
|
||||
const filteredSymbols = contextualMemberSymbols.filter(m => !existingMemberNames.get(m.escapedName));
|
||||
setSortTextToMemberDeclaredBySpreadAssignment(membersDeclaredBySpreadAssignment, filteredSymbols);
|
||||
|
||||
return filteredSymbols;
|
||||
}
|
||||
|
||||
function setMembersDeclaredBySpreadAssignment(declaration: SpreadAssignment | JsxSpreadAttribute, membersDeclaredBySpreadAssignment: Map<true>) {
|
||||
const expression = declaration.expression;
|
||||
const symbol = typeChecker.getSymbolAtLocation(expression);
|
||||
const type = symbol && typeChecker.getTypeOfSymbolAtLocation(symbol, expression);
|
||||
const properties = type && (<ObjectType>type).properties;
|
||||
if (properties) {
|
||||
properties.forEach(property => {
|
||||
membersDeclaredBySpreadAssignment.set(property.name, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Set SortText to OptionalMember if it is an optinoal member
|
||||
function setSortTextToOptionalMember() {
|
||||
symbols.forEach(m => {
|
||||
if (m.flags & SymbolFlags.Optional) {
|
||||
symbolToSortTextMap[getSymbolId(m)] = symbolToSortTextMap[getSymbolId(m)] || SortText.OptionalMember;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Set SortText to MemberDeclaredBySpreadAssignment if it is fulfilled by spread assignment
|
||||
function setSortTextToMemberDeclaredBySpreadAssignment(membersDeclaredBySpreadAssignment: Map<true>, contextualMemberSymbols: Symbol[]): void {
|
||||
if (membersDeclaredBySpreadAssignment.size === 0) {
|
||||
return;
|
||||
}
|
||||
for (const contextualMemberSymbol of contextualMemberSymbols) {
|
||||
if (membersDeclaredBySpreadAssignment.has(contextualMemberSymbol.name)) {
|
||||
symbolToSortTextMap[getSymbolId(contextualMemberSymbol)] = SortText.MemberDeclaredBySpreadAssignment;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2000,6 +2046,7 @@ namespace ts.Completions {
|
||||
*/
|
||||
function filterJsxAttributes(symbols: Symbol[], attributes: NodeArray<JsxAttribute | JsxSpreadAttribute>): Symbol[] {
|
||||
const seenNames = createUnderscoreEscapedMap<boolean>();
|
||||
const membersDeclaredBySpreadAssignment = createMap<true>();
|
||||
for (const attr of attributes) {
|
||||
// If this is the current item we are editing right now, do not filter it out
|
||||
if (isCurrentlyEditingNode(attr)) {
|
||||
@@ -2009,9 +2056,15 @@ namespace ts.Completions {
|
||||
if (attr.kind === SyntaxKind.JsxAttribute) {
|
||||
seenNames.set(attr.name.escapedText, true);
|
||||
}
|
||||
else if (isJsxSpreadAttribute(attr)) {
|
||||
setMembersDeclaredBySpreadAssignment(attr, membersDeclaredBySpreadAssignment);
|
||||
}
|
||||
}
|
||||
const filteredSymbols = symbols.filter(a => !seenNames.get(a.escapedName));
|
||||
|
||||
return symbols.filter(a => !seenNames.get(a.escapedName));
|
||||
setSortTextToMemberDeclaredBySpreadAssignment(membersDeclaredBySpreadAssignment, filteredSymbols);
|
||||
|
||||
return filteredSymbols;
|
||||
}
|
||||
|
||||
function isCurrentlyEditingNode(node: Node): boolean {
|
||||
|
||||
Reference in New Issue
Block a user