mirror of
https://github.com/dart-lang/sdk
synced 2024-10-04 16:54:55 +00:00
Move more of KeywordContributor to the new framework
Change-Id: I2b257545a3af7fa2f803e8f954d14cd3679c35c1 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/319781 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
parent
fc35778ff7
commit
98608662e7
|
@ -102,6 +102,11 @@ class InScopeCompletionPass extends SimpleAstVisitor<void> {
|
|||
_forExpression(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitBooleanLiteral(BooleanLiteral node) {
|
||||
_forExpression(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitClassDeclaration(ClassDeclaration node) {
|
||||
if (offset < node.classKeyword.offset) {
|
||||
|
@ -141,11 +146,99 @@ class InScopeCompletionPass extends SimpleAstVisitor<void> {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitConstructorDeclaration(ConstructorDeclaration node) {
|
||||
var separator = node.separator;
|
||||
if (separator != null) {
|
||||
if (offset >= separator.end && offset <= node.body.offset) {
|
||||
collector.completionLocation = 'ConstructorDeclaration_initializer';
|
||||
keywordHelper.addConstructorInitializerKeywords(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitDoubleLiteral(DoubleLiteral node) {
|
||||
_visitParentIfAtOrBeforeNode(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitEnumDeclaration(EnumDeclaration node) {
|
||||
if (!featureSet.isEnabled(Feature.enhanced_enums)) {
|
||||
return;
|
||||
}
|
||||
if (offset < node.enumKeyword.offset) {
|
||||
// There are no modifiers for enums.
|
||||
return;
|
||||
}
|
||||
if (offset <= node.enumKeyword.end) {
|
||||
keywordHelper.addKeyword(Keyword.ENUM);
|
||||
return;
|
||||
}
|
||||
if (offset <= node.name.end) {
|
||||
// TODO(brianwilkerson) Suggest a name for the mixin.
|
||||
return;
|
||||
}
|
||||
if (offset <= node.leftBracket.offset) {
|
||||
keywordHelper.addEnumDeclarationKeywords(node);
|
||||
return;
|
||||
}
|
||||
var rightBracket = node.rightBracket;
|
||||
if (!rightBracket.isSynthetic && offset >= rightBracket.end) {
|
||||
return;
|
||||
}
|
||||
var semicolon = node.semicolon;
|
||||
if (semicolon != null && offset >= semicolon.end) {
|
||||
collector.completionLocation = 'EnumDeclaration_member';
|
||||
_forEnumMember();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitExtensionDeclaration(ExtensionDeclaration node) {
|
||||
if (offset < node.extensionKeyword.offset) {
|
||||
// There are no modifiers for extensions.
|
||||
return;
|
||||
}
|
||||
if (offset <= node.extensionKeyword.end) {
|
||||
keywordHelper.addKeyword(Keyword.EXTENSION);
|
||||
return;
|
||||
}
|
||||
var name = node.name;
|
||||
if (name != null && offset <= name.end) {
|
||||
// TODO(brianwilkerson) We probably need to suggest `on`.
|
||||
// TODO(brianwilkerson) We probably need to suggest `type` when extension
|
||||
// types are supported.
|
||||
// Don't suggest a name for the extension.
|
||||
return;
|
||||
}
|
||||
if (offset <= node.leftBracket.offset) {
|
||||
if (node.onKeyword.isSynthetic) {
|
||||
keywordHelper.addExtensionDeclarationKeywords(node);
|
||||
} else {
|
||||
collector.completionLocation = 'ExtensionDeclaration_extendedType';
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (offset >= node.leftBracket.end && offset <= node.rightBracket.offset) {
|
||||
collector.completionLocation = 'ExtensionDeclaration_member';
|
||||
_forExtensionMember();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitFunctionDeclaration(FunctionDeclaration node) {
|
||||
// If the cursor is at the beginning of the declaration, include the
|
||||
// compilation unit keywords. See dartbug.com/41039.
|
||||
var returnType = node.returnType;
|
||||
if ((returnType == null || returnType.beginToken == returnType.endToken) &&
|
||||
offset <= node.name.offset) {
|
||||
collector.completionLocation = 'FunctionDeclaration_returnType';
|
||||
keywordHelper.addKeyword(Keyword.DYNAMIC);
|
||||
keywordHelper.addKeyword(Keyword.VOID);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitIntegerLiteral(IntegerLiteral node) {
|
||||
_visitParentIfAtOrBeforeNode(node);
|
||||
|
@ -204,6 +297,42 @@ class InScopeCompletionPass extends SimpleAstVisitor<void> {
|
|||
_forPattern();
|
||||
}
|
||||
|
||||
@override
|
||||
void visitMixinDeclaration(MixinDeclaration node) {
|
||||
if (offset < node.mixinKeyword.offset) {
|
||||
keywordHelper.addMixinModifiers(node);
|
||||
return;
|
||||
}
|
||||
if (offset <= node.mixinKeyword.end) {
|
||||
keywordHelper.addKeyword(Keyword.MIXIN);
|
||||
return;
|
||||
}
|
||||
if (offset <= node.name.end) {
|
||||
// TODO(brianwilkerson) Suggest a name for the mixin.
|
||||
return;
|
||||
}
|
||||
if (offset <= node.leftBracket.offset) {
|
||||
keywordHelper.addMixinDeclarationKeywords(node);
|
||||
return;
|
||||
}
|
||||
if (offset >= node.leftBracket.end && offset <= node.rightBracket.offset) {
|
||||
collector.completionLocation = 'MixinDeclaration_member';
|
||||
_forMixinMember();
|
||||
var element = node.members.elementBefore(offset);
|
||||
if (element is MethodDeclaration) {
|
||||
var body = element.body;
|
||||
if (body.isEmpty) {
|
||||
keywordHelper.addFunctionBodyModifiers(body);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitNullLiteral(NullLiteral node) {
|
||||
_forExpression(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitParenthesizedPattern(ParenthesizedPattern node) {
|
||||
collector.completionLocation = 'ParenthesizedPattern_expression';
|
||||
|
@ -274,6 +403,53 @@ class InScopeCompletionPass extends SimpleAstVisitor<void> {
|
|||
_visitParentIfAtOrBeforeNode(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitSymbolLiteral(SymbolLiteral node) {
|
||||
_forExpression(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitThisExpression(ThisExpression node) {
|
||||
_forExpression(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitThrowExpression(ThrowExpression node) {
|
||||
collector.completionLocation = 'ThrowExpression_expression';
|
||||
_forExpression(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
|
||||
var variableDeclarationList = node.variables;
|
||||
var variables = variableDeclarationList.variables;
|
||||
if (variables.isEmpty || offset > variables.first.beginToken.end) {
|
||||
return;
|
||||
}
|
||||
if (node.externalKeyword == null) {
|
||||
keywordHelper.addKeyword(Keyword.EXTERNAL);
|
||||
}
|
||||
if (variableDeclarationList.lateKeyword == null &&
|
||||
featureSet.isEnabled(Feature.non_nullable)) {
|
||||
keywordHelper.addKeyword(Keyword.LATE);
|
||||
}
|
||||
if (!variables.first.isConst) {
|
||||
keywordHelper.addKeyword(Keyword.CONST);
|
||||
}
|
||||
if (!variables.first.isFinal) {
|
||||
keywordHelper.addKeyword(Keyword.FINAL);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitVariableDeclaration(VariableDeclaration node) {
|
||||
var equals = node.equals;
|
||||
if (equals != null && offset >= equals.end) {
|
||||
collector.completionLocation = 'VariableDeclaration_initializer';
|
||||
_forExpression(node);
|
||||
}
|
||||
}
|
||||
|
||||
/// Add the suggestions that are appropriate when the selection is at the
|
||||
/// beginning of a class member.
|
||||
void _forClassMember() {
|
||||
|
@ -304,6 +480,12 @@ class InScopeCompletionPass extends SimpleAstVisitor<void> {
|
|||
// _addVariablesInScope(node, mustBeConstant: true);
|
||||
}
|
||||
|
||||
/// Add the suggestions that are appropriate when the selection is at the
|
||||
/// beginning of an enum member.
|
||||
void _forEnumMember() {
|
||||
keywordHelper.addEnumMemberKeywords();
|
||||
}
|
||||
|
||||
/// Add the suggestions that are appropriate when the selection is at the
|
||||
/// beginning of an expression. The [node] provides context to determine which
|
||||
/// keywords to include.
|
||||
|
@ -314,6 +496,18 @@ class InScopeCompletionPass extends SimpleAstVisitor<void> {
|
|||
// _addVariablesInScope(node);
|
||||
}
|
||||
|
||||
/// Add the suggestions that are appropriate when the selection is at the
|
||||
/// beginning of an extension member.
|
||||
void _forExtensionMember() {
|
||||
keywordHelper.addExtensionMemberKeywords();
|
||||
}
|
||||
|
||||
/// Add the suggestions that are appropriate when the selection is at the
|
||||
/// beginning of a mixin member.
|
||||
void _forMixinMember() {
|
||||
keywordHelper.addMixinMemberKeywords();
|
||||
}
|
||||
|
||||
/// Add the suggestions that are appropriate when the selection is at the
|
||||
/// beginning of a pattern.
|
||||
void _forPattern() {
|
||||
|
|
|
@ -170,11 +170,6 @@ class _KeywordVisitor extends SimpleAstVisitor<void> {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitBooleanLiteral(BooleanLiteral node) {
|
||||
_addExpressionKeywords(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitCascadeExpression(CascadeExpression node) {
|
||||
_addExpressionKeywords(node);
|
||||
|
@ -251,33 +246,6 @@ class _KeywordVisitor extends SimpleAstVisitor<void> {
|
|||
_addExpressionKeywords(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitConstructorDeclaration(ConstructorDeclaration node) {
|
||||
if (node.initializers.isNotEmpty) {
|
||||
if (entity is ConstructorInitializer) {
|
||||
_addSuggestion(Keyword.ASSERT);
|
||||
}
|
||||
var last = node.initializers.last;
|
||||
if (last == entity) {
|
||||
var previous = node.findPrevious(last.beginToken);
|
||||
if (previous != null && previous.end <= request.offset) {
|
||||
_addSuggestion(Keyword.SUPER);
|
||||
_addSuggestion(Keyword.THIS);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var separator = node.separator;
|
||||
if (separator != null) {
|
||||
var offset = request.offset;
|
||||
if (separator.end <= offset && offset <= separator.next!.offset) {
|
||||
_addSuggestion(Keyword.ASSERT);
|
||||
_addSuggestion(Keyword.SUPER);
|
||||
_addSuggestion(Keyword.THIS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitConstructorReference(ConstructorReference node) {
|
||||
_addExpressionKeywords(node);
|
||||
|
@ -301,29 +269,6 @@ class _KeywordVisitor extends SimpleAstVisitor<void> {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitEnumDeclaration(EnumDeclaration node) {
|
||||
if (!request.featureSet.isEnabled(Feature.enhanced_enums)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity == node.name) {
|
||||
return;
|
||||
}
|
||||
|
||||
var semicolon = node.semicolon;
|
||||
if (request.offset <= node.leftBracket.offset) {
|
||||
if (node.withClause == null) {
|
||||
_addSuggestion(Keyword.WITH);
|
||||
}
|
||||
if (node.implementsClause == null) {
|
||||
_addSuggestion(Keyword.IMPLEMENTS);
|
||||
}
|
||||
} else if (semicolon != null && semicolon.end <= request.offset) {
|
||||
_addEnumBodyKeywords();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitExpressionFunctionBody(ExpressionFunctionBody node) {
|
||||
if (entity == node.expression) {
|
||||
|
@ -331,21 +276,6 @@ class _KeywordVisitor extends SimpleAstVisitor<void> {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitExtensionDeclaration(ExtensionDeclaration node) {
|
||||
// Don't suggest extension name
|
||||
if (entity == node.name) {
|
||||
return;
|
||||
}
|
||||
if (entity == node.rightBracket) {
|
||||
_addExtensionBodyKeywords();
|
||||
} else if (entity is ClassMember) {
|
||||
_addExtensionBodyKeywords();
|
||||
} else {
|
||||
_addExtensionDeclarationKeywords(node);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitExtensionOverride(ExtensionOverride node) {
|
||||
_addExpressionKeywords(node);
|
||||
|
@ -546,16 +476,6 @@ class _KeywordVisitor extends SimpleAstVisitor<void> {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitFunctionDeclaration(FunctionDeclaration node) {
|
||||
// If the cursor is at the beginning of the declaration, include the
|
||||
// compilation unit keywords. See dartbug.com/41039.
|
||||
if (entity == node.returnType || entity == node.name) {
|
||||
_addSuggestion(Keyword.DYNAMIC);
|
||||
_addSuggestion(Keyword.VOID);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitFunctionExpression(FunctionExpression node) {
|
||||
if (entity == node.body) {
|
||||
|
@ -724,29 +644,6 @@ class _KeywordVisitor extends SimpleAstVisitor<void> {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitMixinDeclaration(MixinDeclaration node) {
|
||||
final entity = this.entity;
|
||||
// Don't suggest mixin name
|
||||
if (entity == node.name) {
|
||||
return;
|
||||
}
|
||||
if (entity == node.rightBracket) {
|
||||
_addClassBodyKeywords();
|
||||
} else if (entity is ClassMember) {
|
||||
_addClassBodyKeywords();
|
||||
var index = node.members.indexOf(entity);
|
||||
var previous = index > 0 ? node.members[index - 1] : null;
|
||||
if (previous is MethodDeclaration && previous.body.isEmpty) {
|
||||
_addSuggestion(Keyword.ASYNC);
|
||||
_addSuggestion2(ASYNC_STAR);
|
||||
_addSuggestion2(SYNC_STAR);
|
||||
}
|
||||
} else if (entity != node.mixinKeyword) {
|
||||
_addMixinDeclarationKeywords(node);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitNamedExpression(NamedExpression node) {
|
||||
if (entity is SimpleIdentifier && entity == node.expression) {
|
||||
|
@ -754,11 +651,6 @@ class _KeywordVisitor extends SimpleAstVisitor<void> {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitNullLiteral(NullLiteral node) {
|
||||
_addExpressionKeywords(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitParenthesizedExpression(ParenthesizedExpression node) {
|
||||
var expression = node.expression;
|
||||
|
@ -913,44 +805,6 @@ class _KeywordVisitor extends SimpleAstVisitor<void> {
|
|||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitSymbolLiteral(SymbolLiteral node) {
|
||||
_addExpressionKeywords(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitThisExpression(ThisExpression node) {
|
||||
_addExpressionKeywords(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitThrowExpression(ThrowExpression node) {
|
||||
_addExpressionKeywords(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
|
||||
var variableDeclarationList = node.variables;
|
||||
if (entity != variableDeclarationList) return;
|
||||
var variables = variableDeclarationList.variables;
|
||||
if (variables.isEmpty || request.offset > variables.first.beginToken.end) {
|
||||
return;
|
||||
}
|
||||
if (node.externalKeyword == null) {
|
||||
_addSuggestion(Keyword.EXTERNAL);
|
||||
}
|
||||
if (variableDeclarationList.lateKeyword == null &&
|
||||
request.featureSet.isEnabled(Feature.non_nullable)) {
|
||||
_addSuggestion(Keyword.LATE);
|
||||
}
|
||||
if (!variables.first.isConst) {
|
||||
_addSuggestion(Keyword.CONST);
|
||||
}
|
||||
if (!variables.first.isFinal) {
|
||||
_addSuggestion(Keyword.FINAL);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitTryStatement(TryStatement node) {
|
||||
var obj = entity;
|
||||
|
@ -973,13 +827,6 @@ class _KeywordVisitor extends SimpleAstVisitor<void> {
|
|||
_addExpressionKeywords(node);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitVariableDeclaration(VariableDeclaration node) {
|
||||
if (entity == node.initializer) {
|
||||
_addExpressionKeywords(node);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitVariableDeclarationList(VariableDeclarationList node) {
|
||||
var keyword = node.keyword;
|
||||
|
@ -1086,21 +933,6 @@ class _KeywordVisitor extends SimpleAstVisitor<void> {
|
|||
}
|
||||
}
|
||||
|
||||
void _addEnumBodyKeywords() {
|
||||
_addSuggestions([
|
||||
Keyword.CONST,
|
||||
Keyword.DYNAMIC,
|
||||
Keyword.FINAL,
|
||||
Keyword.GET,
|
||||
Keyword.LATE,
|
||||
Keyword.OPERATOR,
|
||||
Keyword.SET,
|
||||
Keyword.STATIC,
|
||||
Keyword.VAR,
|
||||
Keyword.VOID
|
||||
]);
|
||||
}
|
||||
|
||||
void _addExpressionKeywords(AstNode node) {
|
||||
_addSuggestions([
|
||||
Keyword.FALSE,
|
||||
|
@ -1121,23 +953,6 @@ class _KeywordVisitor extends SimpleAstVisitor<void> {
|
|||
}
|
||||
}
|
||||
|
||||
void _addExtensionBodyKeywords() {
|
||||
_addSuggestions([
|
||||
Keyword.CONST,
|
||||
Keyword.DYNAMIC,
|
||||
Keyword.FINAL,
|
||||
Keyword.GET,
|
||||
Keyword.OPERATOR,
|
||||
Keyword.SET,
|
||||
Keyword.STATIC,
|
||||
Keyword.VAR,
|
||||
Keyword.VOID
|
||||
]);
|
||||
if (request.featureSet.isEnabled(Feature.non_nullable)) {
|
||||
_addSuggestion(Keyword.LATE);
|
||||
}
|
||||
}
|
||||
|
||||
void _addExtensionDeclarationKeywords(ExtensionDeclaration node) {
|
||||
if (node.onKeyword.isSynthetic) {
|
||||
_addSuggestion(Keyword.ON);
|
||||
|
|
|
@ -164,6 +164,32 @@ class KeywordHelper {
|
|||
}
|
||||
}
|
||||
|
||||
/// Add the keywords that are appropriate when the selection is in the
|
||||
/// initializer list of the given [node].
|
||||
void addConstructorInitializerKeywords(ConstructorDeclaration node) {
|
||||
addKeyword(Keyword.ASSERT);
|
||||
var suggestSuper = node.parent is! ExtensionTypeDeclaration;
|
||||
var initializers = node.initializers;
|
||||
if (initializers.isNotEmpty) {
|
||||
var last = initializers.lastNonSynthetic;
|
||||
if (offset >= last.end &&
|
||||
last is! SuperConstructorInvocation &&
|
||||
last is! RedirectingConstructorInvocation) {
|
||||
if (suggestSuper) {
|
||||
addKeyword(Keyword.SUPER);
|
||||
}
|
||||
addKeyword(Keyword.THIS);
|
||||
}
|
||||
} else {
|
||||
// if (separator.end <= offset && offset <= separator.next!.offset) {
|
||||
if (suggestSuper) {
|
||||
addKeyword(Keyword.SUPER);
|
||||
}
|
||||
addKeyword(Keyword.THIS);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
/// Add the keywords that are appropriate when the selection is in an enum
|
||||
/// declaration between the name of the enum and the body. The [node] is the
|
||||
/// enum declaration containing the selection point.
|
||||
|
@ -204,7 +230,12 @@ class KeywordHelper {
|
|||
if (node is CollectionElement && node is! Expression) {
|
||||
node = node.parent;
|
||||
}
|
||||
return node is Expression && !node.inConstantContext;
|
||||
if (node is Expression) {
|
||||
return !node.inConstantContext;
|
||||
} else if (node is VariableDeclaration) {
|
||||
return !node.isConst;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
addKeyword(Keyword.FALSE);
|
||||
|
@ -428,3 +459,13 @@ extension on CollectionElement? {
|
|||
return finalElement is IfElement && finalElement.elseKeyword == null;
|
||||
}
|
||||
}
|
||||
|
||||
extension on NodeList<ConstructorInitializer> {
|
||||
ConstructorInitializer get lastNonSynthetic {
|
||||
final last = this.last;
|
||||
if (last.beginToken.isSynthetic && length > 1) {
|
||||
return this[length - 2];
|
||||
}
|
||||
return last;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -254,8 +254,7 @@ suggestions
|
|||
Keyword.CONST,
|
||||
if (context.isClass || context.isMixin) Keyword.COVARIANT,
|
||||
Keyword.DYNAMIC,
|
||||
// TODO(scheglov) This does not look right, mixin.
|
||||
if (context.isClass || context.isMixin) Keyword.FACTORY,
|
||||
if (context.isClass) Keyword.FACTORY,
|
||||
Keyword.FINAL,
|
||||
Keyword.GET,
|
||||
Keyword.LATE,
|
||||
|
@ -499,8 +498,7 @@ ${keywords.asKeywordSuggestions}
|
|||
Keyword.CONST,
|
||||
if (context.isClass || context.isMixin) Keyword.COVARIANT,
|
||||
Keyword.DYNAMIC,
|
||||
// TODO(scheglov) This does not look right, mixin.
|
||||
if (context.isClass || context.isMixin) Keyword.FACTORY,
|
||||
if (context.isClass) Keyword.FACTORY,
|
||||
Keyword.FINAL,
|
||||
Keyword.GET,
|
||||
Keyword.LATE,
|
||||
|
|
Loading…
Reference in a new issue