General TypeInfo and IdentifierContext cleanup

* Assert computeType and TypeInfo.skipType do not modify the token stream
* Rename TokenInfoTest to TypeInfoTest
* Move skipMetadata to util.dart
* Address comments in https://dart-review.googlesource.com/c/sdk/+/53300

Change-Id: Id2dbe54c5bc688db268e18b0a491367115f7b091
Reviewed-on: https://dart-review.googlesource.com/53640
Commit-Queue: Dan Rubel <danrubel@google.com>
Reviewed-by: Peter von der Ahé <ahe@google.com>
This commit is contained in:
Dan Rubel 2018-05-03 16:38:24 +00:00 committed by commit-bot@chromium.org
parent e93b2ee250
commit 73768a5342
3 changed files with 54 additions and 33 deletions

View file

@ -15,9 +15,9 @@ import 'parser.dart' show Parser;
import 'type_info.dart'
show insertSyntheticIdentifierAfter, isValidTypeReference;
import 'util.dart' show optional;
import 'util.dart' show optional, skipMetadata;
/// See [IdentifierContext].classOrNamedMixin
/// See [IdentifierContext.classOrNamedMixinDeclaration].
class ClassOrNamedMixinIdentifierContext extends IdentifierContext {
const ClassOrNamedMixinIdentifierContext()
: super('classOrNamedMixinDeclaration',
@ -53,7 +53,7 @@ class ClassOrNamedMixinIdentifierContext extends IdentifierContext {
}
}
/// See [IdentifierContext].dottedName
/// See [IdentifierContext.dottedName].
class DottedNameIdentifierContext extends IdentifierContext {
const DottedNameIdentifierContext() : super('dottedName');
@ -95,7 +95,7 @@ class DottedNameIdentifierContext extends IdentifierContext {
}
}
/// See [IdentifierContext].expression
/// See [IdentifierContext.expression].
class ExpressionIdentifierContext extends IdentifierContext {
const ExpressionIdentifierContext()
: super('expression', isScopeReference: true);
@ -145,6 +145,7 @@ class ExpressionIdentifierContext extends IdentifierContext {
}
}
/// See [IdentifierContext.fieldDeclaration].
class FieldDeclarationIdentifierContext extends IdentifierContext {
const FieldDeclarationIdentifierContext()
: super('fieldDeclaration', inDeclaration: true);
@ -175,7 +176,7 @@ class FieldDeclarationIdentifierContext extends IdentifierContext {
}
}
/// See [IdentifierContext].fieldInitializer
/// See [IdentifierContext.fieldInitializer].
class FieldInitializerIdentifierContext extends IdentifierContext {
const FieldInitializerIdentifierContext()
: super('fieldInitializer', isContinuation: true);
@ -234,7 +235,7 @@ class ImportPrefixIdentifierContext extends IdentifierContext {
}
}
/// See [IdentifierContext].libraryName
/// See [IdentifierContext.libraryName].
class LibraryIdentifierContext extends IdentifierContext {
const LibraryIdentifierContext()
: super('libraryName', inLibraryOrPartOfDeclaration: true);
@ -276,7 +277,7 @@ class LibraryIdentifierContext extends IdentifierContext {
}
}
/// See [IdentifierContext].localVariableDeclaration
/// See [IdentifierContext.localVariableDeclaration].
class LocalVariableDeclarationIdentifierContext extends IdentifierContext {
const LocalVariableDeclarationIdentifierContext()
: super('localVariableDeclaration', inDeclaration: true);
@ -308,6 +309,7 @@ class LocalVariableDeclarationIdentifierContext extends IdentifierContext {
}
}
/// See [IdentifierContext.methodDeclaration].
class MethodDeclarationIdentifierContext extends IdentifierContext {
const MethodDeclarationIdentifierContext()
: super('methodDeclaration', inDeclaration: true);
@ -383,7 +385,7 @@ class TypedefDeclarationIdentifierContext extends IdentifierContext {
}
}
/// See [IdentifierContext].typeReference
/// See [IdentifierContext.typeReference].
class TypeReferenceIdentifierContext extends IdentifierContext {
const TypeReferenceIdentifierContext()
: super('typeReference',
@ -415,7 +417,7 @@ class TypeReferenceIdentifierContext extends IdentifierContext {
// annotation is not allowed before type arguments.
parser.reportRecoverableErrorWithToken(
next, fasta.templateUnexpectedToken);
token = skipMetadata(next);
token = skipMetadata(token);
next = token.next;
}
@ -490,25 +492,3 @@ bool looksLikeStartOfNextStatement(Token token) => isOneOfOrEof(token, const [
bool looksLikeStartOfNextTopLevelDeclaration(Token token) =>
token.isTopLevelKeyword ||
isOneOfOrEof(token, const ['const', 'get', 'final', 'set', 'var', 'void']);
Token skipMetadata(Token token) {
assert(optional('@', token));
Token next = token.next;
if (next.isIdentifier) {
token = next;
next = token.next;
while (optional('.', next)) {
token = next;
next = token.next;
if (next.isIdentifier) {
token = next;
next = token.next;
}
}
if (optional('(', next)) {
token = next.endGroup;
next = token.next;
}
}
return token;
}

View file

@ -53,3 +53,26 @@ int lengthOfSpan(Token begin, Token end) {
if (end == null) return lengthForToken(begin);
return end.offset + end.length - begin.offset;
}
Token skipMetadata(Token token) {
token = token.next;
assert(optional('@', token));
Token next = token.next;
if (next.isIdentifier) {
token = next;
next = token.next;
while (optional('.', next)) {
token = next;
next = token.next;
if (next.isIdentifier) {
token = next;
next = token.next;
}
}
if (optional('(', next)) {
token = next.endGroup;
next = token.next;
}
}
return token;
}

View file

@ -13,12 +13,12 @@ import 'package:test_reflective_loader/test_reflective_loader.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(TokenInfoTest);
defineReflectiveTests(TypeInfoTest);
});
}
@reflectiveTest
class TokenInfoTest {
class TypeInfoTest {
void test_noType() {
final Token start = scanString('before ;').tokens;
@ -790,12 +790,18 @@ void compute(
String expectedAfter,
List<String> expectedCalls,
List<ExpectedError> expectedErrors) {
int expectedGtGtAndNullEndCount = countGtGtAndNullEnd(start);
TypeInfo typeInfo = computeType(start, required);
expect(typeInfo, expectedInfo, reason: source);
expect(countGtGtAndNullEnd(start), expectedGtGtAndNullEndCount,
reason: 'computeType should not modify the token stream');
if (typeInfo is ComplexTypeInfo) {
expect(typeInfo.start, start.next, reason: source);
expect(typeInfo.couldBeExpression, isFalse);
expectEnd(expectedAfter, typeInfo.skipType(start));
expect(countGtGtAndNullEnd(start), expectedGtGtAndNullEndCount,
reason: 'TypeInfo.skipType should not modify the token stream');
TypeInfoListener listener;
assertResult(Token actualEnd) {
@ -838,6 +844,18 @@ Token scan(String source) {
return new SyntheticToken(TokenType.EOF, 0)..setNext(start);
}
int countGtGtAndNullEnd(Token token) {
int count = 0;
while (!token.isEof) {
if ((optional('<', token) && token.endGroup == null) ||
optional('>>', token)) {
++count;
}
token = token.next;
}
return count;
}
class TypeInfoListener implements Listener {
List<String> calls = <String>[];
List<ExpectedError> errors;