Index: pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart |
diff --git a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart |
index 0cb00352af79b6af379e9bee3aaac8104a2c9f65..7762e9e9a69306d25fc772aaffe2ce310b43e74f 100644 |
--- a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart |
+++ b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_target.dart |
@@ -91,6 +91,11 @@ class CompletionTarget { |
final CompilationUnit unit; |
/** |
+ * The offset within the source at which the completion is being requested. |
+ */ |
+ final int offset; |
+ |
+ /** |
* The context in which the completion is occurring. This is the AST node |
* which is a direct parent of [entity]. |
*/ |
@@ -162,11 +167,11 @@ class CompletionTarget { |
Token commentToken = _getContainingCommentToken(entity, offset); |
if (commentToken != null) { |
return new CompletionTarget._( |
- compilationUnit, containingNode, commentToken, true); |
+ compilationUnit, offset, containingNode, commentToken, true); |
} |
// Target found. |
return new CompletionTarget._( |
- compilationUnit, containingNode, entity, false); |
+ compilationUnit, offset, containingNode, entity, false); |
} else { |
// Since entity is a token, we don't need to look inside it; just |
// proceed to the next entity. |
@@ -195,12 +200,12 @@ class CompletionTarget { |
if (docComment != null) { |
containingNode = docComment; |
} else { |
- return new CompletionTarget._( |
- compilationUnit, compilationUnit, commentToken, true); |
+ return new CompletionTarget._(compilationUnit, offset, |
+ compilationUnit, commentToken, true); |
} |
} |
return new CompletionTarget._( |
- compilationUnit, containingNode, entity, false); |
+ compilationUnit, offset, containingNode, entity, false); |
} |
// Otherwise, the completion target is somewhere inside the entity, |
@@ -225,7 +230,7 @@ class CompletionTarget { |
// Since no completion target was found, we set the completion target |
// entity to null and use the compilationUnit as the parent. |
return new CompletionTarget._( |
- compilationUnit, compilationUnit, null, false); |
+ compilationUnit, offset, compilationUnit, null, false); |
} |
} |
@@ -233,13 +238,30 @@ class CompletionTarget { |
* Create a [CompletionTarget] holding the given [containingNode] and |
* [entity]. |
*/ |
- CompletionTarget._( |
- this.unit, AstNode containingNode, Object entity, this.isCommentText) |
+ CompletionTarget._(this.unit, this.offset, AstNode containingNode, |
+ Object entity, this.isCommentText) |
: this.containingNode = containingNode, |
this.entity = entity, |
this.argIndex = _computeArgIndex(containingNode, entity); |
/** |
+ * Return `true` if the [containingNode] is a cascade |
+ * and the completion insertion is not between the two dots. |
+ * For example, `..d^` and `..^d` are considered a cascade |
+ * from a completion standpoint, but `.^.d` is not. |
+ */ |
+ bool get isCascade { |
+ AstNode node = containingNode; |
+ if (node is PropertyAccess) { |
+ return node.isCascaded && offset > node.operator.offset + 1; |
+ } |
+ if (node is MethodInvocation) { |
+ return node.isCascaded && offset > node.operator.offset + 1; |
+ } |
+ return false; |
+ } |
+ |
+ /** |
* Return `true` if the target is a functional argument in an argument list. |
* The target [AstNode] hierarchy *must* be resolved for this to work. |
*/ |