Files
sdk/pkg/analyzer/lib/src/generated/parser.dart
T
Sam Rawlins ee69f45a1f analyzer: rework AnalysisErrorListener deprecation
Work towards #60635

In this change, we rework the AnalysisErrorListener deprecation to
better support users who have their own class that implements
AnalysisErrorListener. This change introduces a sealed supertype,
DiagnosticOrErrorListener, with the old implementation,
AnalysisErrorListener, and the new implementation, DiagnosticListener,
as its sole direct subclasses. Users who have implemented
AnalysisErrorListener should be able to instead implement
DiagnosticListener, and their class is an acceptable instance of
DiagnosticOrErrorListener, wherever that is needed.

In a breaking change we can drop AnalysisErrorListener and deprecate
DiagnosticOrErrorListener, and in the next breaking change, we can drop
DiagnosticOrErrorListener.

For reference, see the first API difference when deprecating AnalysisErrorListener and introducing DiagnosticListener: https://github.com/dart-lang/sdk/commit/903d77cc8229972a424941dcb7b7b79741e833eb#diff-dec15868961d7eadcd009f49d129bebcdb747aaa8dbfde5f5a08884e0cf11e32

Change-Id: I3ccf11d54b41fbca98d020d89978d250c16b4c04
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/436480
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Samuel Rawlins <srawlins@google.com>
2025-06-25 06:54:20 -07:00

303 lines
9.3 KiB
Dart

// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:_fe_analyzer_shared/src/parser/parser.dart' as fasta;
import 'package:_fe_analyzer_shared/src/parser/type_info.dart' as fasta;
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/source/source.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:analyzer/src/fasta/ast_builder.dart';
export 'package:analyzer/src/dart/error/syntactic_errors.dart';
/// A parser used to parse tokens into an AST structure.
class Parser {
late Token currentToken;
/// The fasta parser being wrapped.
late final fasta.Parser fastaParser;
/// The builder which creates the analyzer AST data structures
/// based on the Fasta parser.
final AstBuilder astBuilder;
Parser(
Source source,
DiagnosticOrErrorListener diagnosticListener, {
required FeatureSet featureSet,
bool allowNativeClause = true,
required LibraryLanguageVersion languageVersion,
required LineInfo lineInfo,
}) : astBuilder = AstBuilder(
DiagnosticReporter(diagnosticListener, source),
source.uri,
true,
featureSet,
languageVersion,
lineInfo,
) {
fastaParser = fasta.Parser(
astBuilder,
allowPatterns: featureSet.isEnabled(Feature.patterns),
enableFeatureEnhancedParts: featureSet.isEnabled(Feature.enhanced_parts),
);
astBuilder.parser = fastaParser;
astBuilder.allowNativeClause = allowNativeClause;
}
set allowNativeClause(bool value) {
astBuilder.allowNativeClause = value;
}
set parseFunctionBodies(bool parseFunctionBodies) {
astBuilder.parseFunctionBodies = parseFunctionBodies;
}
/// Append the given token to the end of the token stream,
/// and update the token's offset.
void appendToken(Token token, Token newToken) {
while (!token.next!.isEof) {
token = token.next!;
}
newToken
..offset = token.end
..setNext(token.next!);
token.setNext(newToken);
}
Expression parseAdditiveExpression() => parseExpression2();
Expression parseArgument() {
currentToken = SimpleToken(TokenType.OPEN_PAREN, 0)..setNext(currentToken);
appendToken(currentToken, SimpleToken(TokenType.CLOSE_PAREN, 0));
currentToken =
fastaParser
.parseArguments(fastaParser.syntheticPreviousToken(currentToken))
.next!;
var invocation = astBuilder.pop() as MethodInvocation;
return invocation.argumentList.arguments[0];
}
Expression parseAssignableExpression(bool primaryAllowed) =>
parseExpression2();
Expression parseBitwiseAndExpression() => parseExpression2();
Expression parseBitwiseOrExpression() => parseExpression2();
Expression parseBitwiseXorExpression() => parseExpression2();
CompilationUnitImpl parseCompilationUnit(Token token) {
currentToken = token;
return parseCompilationUnit2();
}
CompilationUnitImpl parseCompilationUnit2() {
currentToken = fastaParser.parseUnit(currentToken);
return astBuilder.pop() as CompilationUnitImpl;
}
Expression parseConditionalExpression() => parseExpression2();
Configuration parseConfiguration() {
currentToken =
fastaParser
.parseConditionalUri(
fastaParser.syntheticPreviousToken(currentToken),
)
.next!;
return astBuilder.pop() as Configuration;
}
Expression parseConstExpression() => parseExpression2();
CompilationUnit parseDirectives(Token token) {
currentToken = token;
return parseDirectives2();
}
CompilationUnit parseDirectives2() {
currentToken = fastaParser.parseDirectives(currentToken);
return astBuilder.pop() as CompilationUnit;
}
DottedName parseDottedName() {
currentToken =
fastaParser
.parseDottedName(fastaParser.syntheticPreviousToken(currentToken))
.next!;
return astBuilder.pop() as DottedName;
}
Expression parseEqualityExpression() => parseExpression2();
Expression parseExpression(Token token) {
currentToken = token;
return parseExpression2();
}
Expression parseExpression2() {
currentToken =
fastaParser
.parseExpression(fastaParser.syntheticPreviousToken(currentToken))
.next!;
return astBuilder.pop() as Expression;
}
Expression parseExpressionWithoutCascade() => parseExpression2();
FormalParameterList parseFormalParameterList({bool inFunctionType = false}) {
currentToken =
fastaParser
.parseFormalParametersRequiredOpt(
fastaParser.syntheticPreviousToken(currentToken),
inFunctionType
? fasta.MemberKind.GeneralizedFunctionType
: fasta.MemberKind.NonStaticMethod,
)
.next!;
return astBuilder.pop() as FormalParameterList;
}
FunctionBody parseFunctionBody(
bool mayBeEmpty,
ParserErrorCode emptyErrorCode,
bool inExpression,
) {
currentToken = fastaParser.parseAsyncModifierOpt(
fastaParser.syntheticPreviousToken(currentToken),
);
currentToken = fastaParser.parseFunctionBody(
currentToken,
inExpression,
mayBeEmpty,
);
return astBuilder.pop() as FunctionBody;
}
FunctionExpression parseFunctionExpression() =>
parseExpression2() as FunctionExpression;
Expression parseLogicalAndExpression() => parseExpression2();
Expression parseLogicalOrExpression() => parseExpression2();
Expression parseMultiplicativeExpression() => parseExpression2();
InstanceCreationExpression parseNewExpression() =>
parseExpression2() as InstanceCreationExpression;
Expression parsePostfixExpression() => parseExpression2();
Identifier parsePrefixedIdentifier() => parseExpression2() as Identifier;
Expression parsePrimaryExpression() {
currentToken =
fastaParser
.parsePrimary(
fastaParser.syntheticPreviousToken(currentToken),
fasta.IdentifierContext.expression,
fasta.ConstantPatternContext.none,
)
.next!;
return astBuilder.pop() as Expression;
}
Expression parseRelationalExpression() => parseExpression2();
Expression parseRethrowExpression() => parseExpression2();
Expression parseShiftExpression() => parseExpression2();
SimpleIdentifier parseSimpleIdentifier({
bool allowKeyword = false,
bool isDeclaration = false,
}) => parseExpression2() as SimpleIdentifier;
Statement parseStatement(Token token) {
currentToken = token;
return parseStatement2();
}
Statement parseStatement2() {
currentToken =
fastaParser
.parseStatement(fastaParser.syntheticPreviousToken(currentToken))
.next!;
return astBuilder.pop() as Statement;
}
StringLiteral parseStringLiteral() => parseExpression2() as StringLiteral;
SymbolLiteral parseSymbolLiteral() => parseExpression2() as SymbolLiteral;
Expression parseThrowExpression() => parseExpression2();
Expression parseThrowExpressionWithoutCascade() => parseExpression2();
AnnotatedNode parseTopLevelDeclaration(bool isDirective) {
currentToken = fastaParser.parseTopLevelDeclaration(currentToken);
return (isDirective ? astBuilder.directives : astBuilder.declarations)
.removeLast();
}
TypeAnnotation parseTypeAnnotation(bool inExpression) {
Token previous = fastaParser.syntheticPreviousToken(currentToken);
currentToken =
fasta
.computeType(previous, true, !inExpression)
.parseType(previous, fastaParser)
.next!;
return astBuilder.pop() as TypeAnnotation;
}
TypeArgumentList parseTypeArgumentList() {
Token previous = fastaParser.syntheticPreviousToken(currentToken);
currentToken =
fasta
.computeTypeParamOrArg(previous)
.parseArguments(previous, fastaParser)
.next!;
return astBuilder.pop() as TypeArgumentList;
}
NamedType parseTypeName(bool inExpression) {
Token previous = fastaParser.syntheticPreviousToken(currentToken);
currentToken =
fasta
.computeType(previous, true, !inExpression)
.parseType(previous, fastaParser)
.next!;
return astBuilder.pop() as NamedType;
}
TypeParameter parseTypeParameter() {
currentToken =
SyntheticBeginToken(TokenType.LT, 0)
..endGroup = SyntheticToken(TokenType.GT, 0)
..setNext(currentToken);
appendToken(currentToken, currentToken.endGroup!);
TypeParameterList typeParams = parseTypeParameterList()!;
return typeParams.typeParameters[0];
}
TypeParameterList? parseTypeParameterList() {
Token token = fastaParser.syntheticPreviousToken(currentToken);
currentToken =
fasta
.computeTypeParamOrArg(token, true)
.parseVariables(token, fastaParser)
.next!;
return astBuilder.pop() as TypeParameterList?;
}
Expression parseUnaryExpression() => parseExpression2();
}