mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 14:32:24 +00:00
Fix (+test) dangling expression autocompletion for angular
Change-Id: If35f998eb7fe38f21e30bfba3d87c507c07ebc7c Reviewed-on: https://dart-review.googlesource.com/52522 Commit-Queue: Mike Fairhurst <mfairhurst@google.com> Reviewed-by: Paul Berry <paulberry@google.com>
This commit is contained in:
parent
34a1ba7307
commit
4bf738606b
3 changed files with 58 additions and 1 deletions
|
@ -543,7 +543,10 @@ class CompletionTarget {
|
|||
// If the current token is synthetic, then check the previous token
|
||||
// because it may have been dropped from the parse tree
|
||||
Token previous = node.findPrevious(token);
|
||||
if (offset < previous.end) {
|
||||
if (previous == null) {
|
||||
// support dangling expression completion, where previous may be null.
|
||||
return false;
|
||||
} else if (offset < previous.end) {
|
||||
return true;
|
||||
} else if (offset == previous.end) {
|
||||
return token.type.isKeyword || previous.type == TokenType.IDENTIFIER;
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
|
||||
import 'package:analyzer/dart/ast/token.dart';
|
||||
import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
import 'package:front_end/src/scanner/token.dart'
|
||||
show SyntheticBeginToken, TokenType, SyntheticToken;
|
||||
import 'package:analyzer/src/generated/parser.dart';
|
||||
import 'package:analyzer/src/dart/scanner/reader.dart';
|
||||
import 'package:analyzer/src/dart/scanner/scanner.dart';
|
||||
|
||||
void main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(CompletionTargetTest);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class CompletionTargetTest {
|
||||
test_danglingExpressionCompletionIsValid() {
|
||||
// Test that users can parse dangling expressions of dart and autocomplete
|
||||
// them without crash/with the correct offset information.
|
||||
final snippet = wrapForCompliance(parseDanglingDart('identifier'));
|
||||
final completionTarget =
|
||||
new CompletionTarget.forOffset(null, 1, entryPoint: snippet);
|
||||
expect(completionTarget.offset, 1);
|
||||
final replacementRange = completionTarget.computeReplacementRange(1);
|
||||
expect(replacementRange.offset, 0);
|
||||
expect(replacementRange.length, 'identifier'.length);
|
||||
}
|
||||
|
||||
/// Parse a dangling expression (no parent node). The angular plugin, for
|
||||
/// instance, does this.
|
||||
Expression parseDanglingDart(String code) {
|
||||
final reader = new CharSequenceReader(code);
|
||||
final scanner = new Scanner(null, reader, null);
|
||||
return new Parser(null, null).parseExpression(scanner.tokenize());
|
||||
}
|
||||
|
||||
Expression wrapForCompliance(Expression expression) {
|
||||
// TODO(mfairhurst) This should be performed for clients or the need should
|
||||
// be dropped. It's a fairly valid invariant that all autocompletion target
|
||||
// expressions should have parents, and one we can enforce via synthetics.
|
||||
// But clients should not be doing this ideally.
|
||||
return astFactory.parenthesizedExpression(
|
||||
new SyntheticBeginToken(TokenType.OPEN_PAREN, expression.offset)
|
||||
..next = expression.beginToken,
|
||||
expression,
|
||||
new SyntheticToken(TokenType.CLOSE_PAREN, expression.end));
|
||||
}
|
||||
}
|
|
@ -7,10 +7,12 @@ import 'package:test_reflective_loader/test_reflective_loader.dart';
|
|||
import 'inherited_reference_contributor_test.dart'
|
||||
as inherited_reference_contributor_test;
|
||||
import 'type_member_contributor_test.dart' as type_member_contributor_test;
|
||||
import 'completion_target_test.dart' as completion_target_test;
|
||||
|
||||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
inherited_reference_contributor_test.main();
|
||||
type_member_contributor_test.main();
|
||||
completion_target_test.main();
|
||||
}, name: 'subscriptions');
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue