blob: d5a5bab1da40bccf4ba554eb8da8f2e5b20156d3 [file] [log] [blame]
// Copyright (c) 2016, 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/messages/codes.dart'
show
Code,
Message,
codeAssertAsExpression,
codeSetOrMapLiteralTooManyTypeArguments;
import 'package:analyzer/dart/ast/token.dart' show Token;
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
import 'package:analyzer/src/error/codes.dart';
/// An error reporter that knows how to convert a Fasta error into an analyzer
/// error.
class FastaErrorReporter {
/// The underlying error reporter to which errors are reported.
final ErrorReporter? errorReporter;
/// Initialize a newly created error reporter to report errors to the given
/// [errorReporter].
FastaErrorReporter(this.errorReporter);
void reportByCode(
String? analyzerCode,
int offset,
int length,
Message message,
) {
Map<String, dynamic> arguments = message.arguments;
String lexeme() => (arguments['lexeme'] as Token).lexeme;
switch (analyzerCode) {
case "ASYNC_FOR_IN_WRONG_CONTEXT":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.ASYNC_FOR_IN_WRONG_CONTEXT,
);
return;
case "ASYNC_KEYWORD_USED_AS_IDENTIFIER":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER,
);
return;
case "AWAIT_IN_WRONG_CONTEXT":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.AWAIT_IN_WRONG_CONTEXT,
);
return;
case "BUILT_IN_IDENTIFIER_AS_TYPE":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE,
arguments: [lexeme()],
);
return;
case "CONCRETE_CLASS_WITH_ABSTRACT_MEMBER":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode:
CompileTimeErrorCode.CONCRETE_CLASS_WITH_ABSTRACT_MEMBER,
);
return;
case "CONST_CONSTRUCTOR_WITH_BODY":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.CONST_CONSTRUCTOR_WITH_BODY,
);
return;
case "CONST_NOT_INITIALIZED":
var name = arguments['name'] as String;
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.CONST_NOT_INITIALIZED,
arguments: [name],
);
return;
case "DEFAULT_VALUE_IN_FUNCTION_TYPE":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.DEFAULT_VALUE_IN_FUNCTION_TYPE,
);
return;
case "LABEL_UNDEFINED":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.LABEL_UNDEFINED,
arguments: [arguments['name'] as Object],
);
return;
case "EMPTY_ENUM_BODY":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.EMPTY_ENUM_BODY,
);
return;
case "EXPECTED_CLASS_MEMBER":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.EXPECTED_CLASS_MEMBER,
);
return;
case "EXPECTED_EXECUTABLE":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.EXPECTED_EXECUTABLE,
);
return;
case "EXPECTED_STRING_LITERAL":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.EXPECTED_STRING_LITERAL,
);
return;
case "EXPECTED_TOKEN":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.EXPECTED_TOKEN,
arguments: [arguments['string'] as Object],
);
return;
case "EXPECTED_TYPE_NAME":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.EXPECTED_TYPE_NAME,
);
return;
case "EXTENSION_DECLARES_INSTANCE_FIELD":
// Reported by
// [ErrorVerifier._checkForExtensionDeclaresInstanceField]
return;
case "FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode:
CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR,
);
return;
case "FINAL_NOT_INITIALIZED":
var name = arguments['name'] as String;
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.FINAL_NOT_INITIALIZED,
arguments: [name],
);
return;
case "FINAL_NOT_INITIALIZED_CONSTRUCTOR_1":
var name = arguments['name'] as String;
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode:
CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1,
arguments: [name],
);
return;
case "GETTER_WITH_PARAMETERS":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.GETTER_WITH_PARAMETERS,
);
return;
case "ILLEGAL_CHARACTER":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ScannerErrorCode.ILLEGAL_CHARACTER,
);
return;
case "INVALID_ASSIGNMENT":
var type1 = arguments['type'] as Object;
var type2 = arguments['type2'] as Object;
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.INVALID_ASSIGNMENT,
arguments: [type1, type2],
);
return;
case "INVALID_INLINE_FUNCTION_TYPE":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.INVALID_INLINE_FUNCTION_TYPE,
);
return;
case "INVALID_LITERAL_IN_CONFIGURATION":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.INVALID_LITERAL_IN_CONFIGURATION,
);
return;
case "IMPORT_OF_NON_LIBRARY":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.IMPORT_OF_NON_LIBRARY,
);
return;
case "INVALID_CAST_FUNCTION":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.INVALID_CAST_FUNCTION,
);
return;
case "INVALID_CAST_FUNCTION_EXPR":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.INVALID_CAST_FUNCTION_EXPR,
);
return;
case "INVALID_CAST_LITERAL_LIST":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.INVALID_CAST_LITERAL_LIST,
);
return;
case "INVALID_CAST_LITERAL_MAP":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.INVALID_CAST_LITERAL_MAP,
);
return;
case "INVALID_CAST_LITERAL_SET":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.INVALID_CAST_LITERAL_SET,
);
return;
case "INVALID_CAST_METHOD":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.INVALID_CAST_METHOD,
);
return;
case "INVALID_CAST_NEW_EXPR":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.INVALID_CAST_NEW_EXPR,
);
return;
case "INVALID_CODE_POINT":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.INVALID_CODE_POINT,
arguments: ['\\u{...}'],
);
return;
case "INVALID_GENERIC_FUNCTION_TYPE":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.INVALID_GENERIC_FUNCTION_TYPE,
);
return;
case "INVALID_METHOD_OVERRIDE":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.INVALID_OVERRIDE,
);
return;
case "INVALID_MODIFIER_ON_SETTER":
_reportByCode(
offset: offset,
length: length,
code: CompileTimeErrorCode.INVALID_MODIFIER_ON_SETTER,
message: message,
);
return;
case "INVALID_OPERATOR_FOR_SUPER":
_reportByCode(
offset: offset,
length: length,
code: ParserErrorCode.INVALID_OPERATOR_FOR_SUPER,
message: message,
);
return;
case "MISSING_DIGIT":
errorReporter?.atOffset(
diagnosticCode: ScannerErrorCode.MISSING_DIGIT,
offset: offset,
length: length,
);
return;
case "MISSING_ENUM_BODY":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.MISSING_ENUM_BODY,
);
return;
case "MISSING_FUNCTION_BODY":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.MISSING_FUNCTION_BODY,
);
return;
case "MISSING_FUNCTION_PARAMETERS":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.MISSING_FUNCTION_PARAMETERS,
);
return;
case "MISSING_HEX_DIGIT":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ScannerErrorCode.MISSING_HEX_DIGIT,
);
return;
case "MISSING_IDENTIFIER":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.MISSING_IDENTIFIER,
);
return;
case "MISSING_METHOD_PARAMETERS":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.MISSING_METHOD_PARAMETERS,
);
return;
case "MISSING_STAR_AFTER_SYNC":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.MISSING_STAR_AFTER_SYNC,
);
return;
case "MISSING_TYPEDEF_PARAMETERS":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.MISSING_TYPEDEF_PARAMETERS,
);
return;
case "MULTIPLE_IMPLEMENTS_CLAUSES":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES,
);
return;
case "NAMED_FUNCTION_EXPRESSION":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.NAMED_FUNCTION_EXPRESSION,
);
return;
case "NAMED_PARAMETER_OUTSIDE_GROUP":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP,
);
return;
case "NON_PART_OF_DIRECTIVE_IN_PART":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.NON_PART_OF_DIRECTIVE_IN_PART,
);
return;
case "NON_SYNC_FACTORY":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.NON_SYNC_FACTORY,
);
return;
case "POSITIONAL_AFTER_NAMED_ARGUMENT":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT,
);
return;
case "RECURSIVE_CONSTRUCTOR_REDIRECT":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT,
);
return;
case "RETURN_IN_GENERATOR":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.RETURN_IN_GENERATOR,
);
return;
case "SUPER_INVOCATION_NOT_LAST":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.SUPER_INVOCATION_NOT_LAST,
);
return;
case "SUPER_IN_REDIRECTING_CONSTRUCTOR":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.SUPER_IN_REDIRECTING_CONSTRUCTOR,
);
return;
case "UNDEFINED_CLASS":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.UNDEFINED_CLASS,
);
return;
case "UNDEFINED_GETTER":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.UNDEFINED_GETTER,
);
return;
case "UNDEFINED_METHOD":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.UNDEFINED_METHOD,
);
return;
case "UNDEFINED_SETTER":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: CompileTimeErrorCode.UNDEFINED_SETTER,
);
return;
case "UNEXPECTED_DOLLAR_IN_STRING":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ScannerErrorCode.UNEXPECTED_DOLLAR_IN_STRING,
);
return;
case "UNEXPECTED_TOKEN":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ParserErrorCode.UNEXPECTED_TOKEN,
arguments: [lexeme()],
);
return;
case "UNTERMINATED_MULTI_LINE_COMMENT":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ScannerErrorCode.UNTERMINATED_MULTI_LINE_COMMENT,
);
return;
case "UNTERMINATED_STRING_LITERAL":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode: ScannerErrorCode.UNTERMINATED_STRING_LITERAL,
);
return;
case "WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode:
CompileTimeErrorCode.WRONG_NUMBER_OF_PARAMETERS_FOR_SETTER,
);
return;
case "WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER":
errorReporter?.atOffset(
offset: offset,
length: length,
diagnosticCode:
ParserErrorCode.WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER,
);
return;
case "YIELD_IN_NON_GENERATOR":
// Reported by [YieldStatementResolver._resolve_notGenerator]
return;
case "BUILT_IN_IDENTIFIER_IN_DECLARATION":
// Reported by [ErrorVerifier._checkForBuiltInIdentifierAsName].
return;
case "PRIVATE_OPTIONAL_PARAMETER":
// Reported by [ErrorVerifier._checkForPrivateOptionalParameter].
return;
case "NON_SYNC_ABSTRACT_METHOD":
// Not reported but followed by a MISSING_FUNCTION_BODY error.
return;
case "ABSTRACT_EXTENSION_FIELD":
// Not reported but followed by a
// CompileTimeErrorCode.EXTENSION_DECLARES_INSTANCE_FIELD.
return;
case "EXTENSION_TYPE_WITH_ABSTRACT_MEMBER":
// Reported by [ErrorVerifier._checkForExtensionTypeWithAbstractMember].
return;
case "EXTENSION_TYPE_DECLARES_INSTANCE_FIELD":
// Reported by
// [ErrorVerifier._checkForExtensionTypeDeclaresInstanceField]
return;
case null:
switch (message.code) {
case codeAssertAsExpression:
// Reported as UNDEFINED_IDENTIFIER in
// [SimpleIdentifierResolver._resolve1],
// followed by an EXPECTED_IDENTIFIER_BUT_GOT_KEYWORD error,
// or followed by an EXPECTED_TOKEN error as seen in
// `language/constructor/explicit_instantiation_syntax_test`
// TODO(srawlins): See below
// TODO(johnniwinther): How can we be sure that no other
// cases exists?
return;
case codeSetOrMapLiteralTooManyTypeArguments:
// Reported as EXPECTED_TWO_MAP_TYPE_ARGUMENTS in
// [TypeArgumentsVerifier.checkMapLiteral].
return;
default:
}
}
assert(false, "Unreported message $analyzerCode.");
}
/// Report an error based on the given [message] whose range is described by
/// the given [offset] and [length].
void reportMessage(Message message, int offset, int length) {
Code code = message.code;
int index = code.index;
if (index > 0 && index < fastaAnalyzerErrorCodes.length) {
var errorCode = fastaAnalyzerErrorCodes[index];
if (errorCode != null) {
errorReporter!.reportError(
Diagnostic.tmp(
source: errorReporter!.source,
offset: offset,
length: length,
errorCode: errorCode,
arguments: message.arguments.values.toList(),
),
);
return;
}
}
reportByCode(code.analyzerCodes?.first, offset, length, message);
}
void reportScannerError(
ScannerErrorCode errorCode,
int offset,
List<Object>? arguments,
) {
// TODO(danrubel): update client to pass length in addition to offset.
int length = 1;
errorReporter?.atOffset(
diagnosticCode: errorCode,
offset: offset,
length: length,
arguments: arguments ?? const [],
);
}
void _reportByCode({
required int offset,
required int length,
required DiagnosticCode code,
required Message message,
}) {
if (errorReporter != null) {
errorReporter!.reportError(
Diagnostic.tmp(
source: errorReporter!.source,
offset: offset,
length: length,
errorCode: code,
arguments: message.arguments.values.toList(),
),
);
}
}
}