Skip to content

Commit

Permalink
Version 3.5.0-178.0.dev
Browse files Browse the repository at this point in the history
Merge c888e76 into dev
  • Loading branch information
Dart CI committed May 21, 2024
2 parents f0ac30b + c888e76 commit fca7dd7
Show file tree
Hide file tree
Showing 56 changed files with 1,811 additions and 294 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer_plugin/utilities/assist/assist.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
import 'package:analyzer_plugin/utilities/range_factory.dart';
import 'package:meta/meta.dart';

/// How broadly a [CorrectionProducer] can be applied.
Expand Down Expand Up @@ -117,17 +115,12 @@ abstract class CorrectionProducer<T extends ParsedUnitResult>
bool get canBeAppliedAutomatically =>
applicability == CorrectionApplicability.automatically;

/// The length of the error message being fixed, or `null` if there is no
/// diagnostic.
/// The length of the source range associated with the error message being
/// fixed, or `null` if there is no diagnostic.
int? get errorLength => diagnostic?.problemMessage.length;

/// The text of the error message being fixed, or `null` if there is no
/// diagnostic.
String? get errorMessage =>
diagnostic?.problemMessage.messageText(includeUrl: true);

/// The offset of the error message being fixed, or `null` if there is no
/// diagnostic.
/// The offset of the source range associated with the error message being
/// fixed, or `null` if there is no diagnostic.
int? get errorOffset => diagnostic?.problemMessage.offset;

/// The arguments that should be used when composing the message for a fix, or
Expand Down Expand Up @@ -162,9 +155,7 @@ abstract class CorrectionProducer<T extends ParsedUnitResult>
///
/// If the fix needs to dynamically set [fixKind], it should be done here.
@override
void configure(CorrectionProducerContext<T> context) {
super.configure(context);
}
void configure(CorrectionProducerContext<T> context);
}

class CorrectionProducerContext<UnitResult extends ParsedUnitResult> {
Expand All @@ -176,11 +167,10 @@ class CorrectionProducerContext<UnitResult extends ParsedUnitResult> {
final AnalysisSessionHelper _sessionHelper;
final UnitResult _unitResult;

// TODO(migration): Make it non-nullable, specialize "fix" context?
final DartFixContext? dartFixContext;

/// A flag indicating whether the correction producers will be run in the
/// context of applying bulk fixes.
/// Whether the correction producers are run in the context of applying bulk
/// fixes.
final bool _applyingBulkFixes;

final Diagnostic? _diagnostic;
Expand All @@ -191,13 +181,13 @@ class CorrectionProducerContext<UnitResult extends ParsedUnitResult> {

CorrectionProducerContext._({
required UnitResult unitResult,
bool applyingBulkFixes = false,
this.dartFixContext,
Diagnostic? diagnostic,
required bool applyingBulkFixes,
required this.dartFixContext,
required Diagnostic? diagnostic,
required AstNode node,
required Token token,
int selectionOffset = -1,
int selectionLength = 0,
required int selectionOffset,
required int selectionLength,
}) : _unitResult = unitResult,
_sessionHelper = AnalysisSessionHelper(unitResult.session),
_utils = CorrectionUtils(unitResult),
Expand Down Expand Up @@ -301,12 +291,6 @@ abstract class MultiCorrectionProducer

/// The individual producers generated by this producer.
Future<List<ResolvedCorrectionProducer>> get producers;

TypeProvider get typeProvider => unitResult.typeProvider;

/// The type system appropriate to the library in which the correction is
/// requested.
TypeSystem get typeSystem => unitResult.typeSystem;
}

/// An object that can compute a correction (fix or assist) in a Dart file using
Expand All @@ -322,9 +306,6 @@ abstract class ResolvedCorrectionProducer
sessionHelper.session.analysisContext
.getAnalysisOptionsForFile(unitResult.file) as AnalysisOptionsImpl;

/// The type for the class `bool` from `dart:core`.
DartType get coreTypeBool => unitResult.typeProvider.boolType;

/// Whether [node] is in a static context.
bool get inStaticContext {
// Constructor initializers cannot reference `this`.
Expand All @@ -351,6 +332,9 @@ abstract class ResolvedCorrectionProducer
/// requested.
TypeSystem get typeSystem => unitResult.typeSystem;

/// The type for the class `bool` from `dart:core`.
DartType get _coreTypeBool => typeProvider.boolType;

/// Returns the class declaration for the given [element], or `null` if there
/// is no such class.
Future<ClassDeclaration?> getClassDeclaration(ClassElement element) async {
Expand Down Expand Up @@ -486,35 +470,35 @@ abstract class ResolvedCorrectionProducer
if (parent is AssertStatement) {
var statement = parent;
if (statement.condition == expression) {
return coreTypeBool;
return _coreTypeBool;
}
}
// `if ( myFunction() ) {}`.
if (parent is IfStatement) {
var statement = parent;
if (statement.expression == expression) {
return coreTypeBool;
return _coreTypeBool;
}
}
// `while ( myFunction() ) {}`.
if (parent is WhileStatement) {
var statement = parent;
if (statement.condition == expression) {
return coreTypeBool;
return _coreTypeBool;
}
}
// `do {} while ( myFunction() );`.
if (parent is DoStatement) {
var statement = parent;
if (statement.condition == expression) {
return coreTypeBool;
return _coreTypeBool;
}
}
// `!myFunction()`.
if (parent is PrefixExpression) {
var prefixExpression = parent;
if (prefixExpression.operator.type == TokenType.BANG) {
return coreTypeBool;
return _coreTypeBool;
}
}
// Binary expression `&&` or `||`.
Expand All @@ -523,7 +507,7 @@ abstract class ResolvedCorrectionProducer
var operatorType = binaryExpression.operator.type;
if (operatorType == TokenType.AMPERSAND_AMPERSAND ||
operatorType == TokenType.BAR_BAR) {
return coreTypeBool;
return _coreTypeBool;
}
}
}
Expand Down Expand Up @@ -577,11 +561,6 @@ abstract class _AbstractCorrectionProducer<T extends ParsedUnitResult> {

String get file => _context.path;

/// See [CompilationUnitImpl.invalidNodes].
List<AstNode> get invalidNodes {
return (unit as CompilationUnitImpl).invalidNodes;
}

AstNode get node => _context._node;

ResourceProvider get resourceProvider => unitResult.session.resourceProvider;
Expand All @@ -594,15 +573,6 @@ abstract class _AbstractCorrectionProducer<T extends ParsedUnitResult> {

AnalysisSessionHelper get sessionHelper => _context._sessionHelper;

bool get strictCasts {
var file = _context.dartFixContext?.resolvedResult.file;
// TODO(pq): can this ever happen?
if (file == null) return false;
var analysisOptions = _context._unitResult.session.analysisContext
.getAnalysisOptionsForFile(file) as AnalysisOptionsImpl;
return analysisOptions.strictCasts;
}

Token get token => _context._token;

CompilationUnit get unit => _context._unitResult.unit;
Expand All @@ -611,16 +581,12 @@ abstract class _AbstractCorrectionProducer<T extends ParsedUnitResult> {

CorrectionUtils get utils => _context._utils;

/// Configure this producer based on the [context].
/// Configures this producer based on the [context].
@mustCallSuper
void configure(CorrectionProducerContext<T> context) {
_context = context;
}

/// Returns the text that should be displayed to users when referring to the
/// given [type].
String displayStringForType(DartType type) => type.getDisplayString();

CodeStyleOptions getCodeStyleOptions(File file) =>
sessionHelper.session.analysisContext
.getAnalysisOptionsForFile(file)
Expand Down Expand Up @@ -650,19 +616,17 @@ abstract class _AbstractCorrectionProducer<T extends ParsedUnitResult> {
}

/// Returns the text of the given [range] in the unit.
String getRangeText(SourceRange range) {
return utils.getRangeText(range);
}
String getRangeText(SourceRange range) => utils.getRangeText(range);

/// Returns the mapping from a library (that is available to this context) to
/// a top-level declaration that is exported (not necessary declared) by this
/// library, and has the requested base name. For getters and setters the
/// corresponding top-level variable is returned.
/// library, and has the requested base name.
///
/// For getters and setters the corresponding top-level variable is returned.
Future<Map<LibraryElement, Element>> getTopLevelDeclarations(
String baseName,
) {
return _context.dartFixContext!.getTopLevelDeclarations(baseName);
}
) =>
_context.dartFixContext!.getTopLevelDeclarations(baseName);

/// Returns whether the selection covers an operator of the given
/// [binaryExpression].
Expand All @@ -686,73 +650,9 @@ abstract class _AbstractCorrectionProducer<T extends ParsedUnitResult> {
return false;
}

/// Return libraries with extensions that declare non-static public
/// Returns libraries with extensions that declare non-static public
/// extension members with the [memberName].
Stream<LibraryElement> librariesWithExtensions(String memberName) {
return _context.dartFixContext!.librariesWithExtensions(memberName);
}

/// Return `true` if the given [node] is in a location where an implicit
/// constructor invocation would be allowed.
bool mightBeImplicitConstructor(AstNode node) {
if (node is SimpleIdentifier) {
var parent = node.parent;
if (parent is MethodInvocation) {
return parent.realTarget == null;
}
}
return false;
}

/// If the [node] might be a type name, return its name.
String? nameOfType(AstNode node) {
if (node is SimpleIdentifier) {
var name = node.name;
if (node.parent is NamedType || _isNameOfType(name)) {
return name;
}
}
return null;
}

/// Return `true` if the given [expression] should be wrapped with parenthesis
/// when we want to use it as operand of a logical `and` expression.
bool shouldWrapParenthesisBeforeAnd(Expression expression) {
if (expression is BinaryExpression) {
var binary = expression;
var precedence = binary.operator.type.precedence;
return precedence < TokenClass.LOGICAL_AND_OPERATOR.precedence;
}
return false;
}

/// Return `true` if the [name] is capitalized.
bool _isNameOfType(String name) {
if (name.isEmpty) {
return false;
}
var firstLetter = name.substring(0, 1);
if (firstLetter.toUpperCase() != firstLetter) {
return false;
}
return true;
}
}

extension DartFileEditBuilderExtension on DartFileEditBuilder {
/// Add edits to the [builder] to remove any parentheses enclosing the
/// [expression].
// TODO(brianwilkerson): Consider moving this to DartFileEditBuilder.
void removeEnclosingParentheses(Expression expression) {
var precedence = getExpressionPrecedence(expression);
while (expression.parent is ParenthesizedExpression) {
var parenthesized = expression.parent as ParenthesizedExpression;
if (getExpressionParentPrecedence(parenthesized) > precedence) {
break;
}
addDeletion(range.token(parenthesized.leftParenthesis));
addDeletion(range.token(parenthesized.rightParenthesis));
expression = parenthesized;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ class ChangeTypeAnnotation extends ResolvedCorrectionProducer {
if (newType is InterfaceType ||
newType is FunctionType ||
newType is RecordType) {
_oldAnnotation = displayStringForType(typeNode.typeOrThrow);
_newAnnotation = displayStringForType(newType);
_oldAnnotation = typeNode.typeOrThrow.getDisplayString();
_newAnnotation = newType.getDisplayString();
await builder.addDartFileEdit(file, (builder) {
if (builder.canWriteType(newType)) {
builder.addReplacement(range.node(typeNode), (builder) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,14 @@ class CreateClass extends ResolvedCorrectionProducer {
className = targetNode.name2.lexeme;
requiresConstConstructor |= _requiresConstConstructor(targetNode);
} else if (targetNode is SimpleIdentifier) {
className = nameOfType(targetNode);
className = targetNode.nameOfType;
requiresConstConstructor |= _requiresConstConstructor(targetNode);
} else if (targetNode is PrefixedIdentifier) {
prefixElement = targetNode.prefix.staticElement;
if (prefixElement == null) {
return;
}
className = nameOfType(targetNode.identifier);
className = targetNode.identifier.nameOfType;
} else {
return;
}
Expand Down Expand Up @@ -159,3 +159,29 @@ class CreateClass extends ResolvedCorrectionProducer {
return false;
}
}

extension on AstNode {
/// If this might be a type name, return its name.
String? get nameOfType {
var self = this;
if (self is SimpleIdentifier) {
var name = self.name;
if (self.parent is NamedType || _isNameOfType(name)) {
return name;
}
}
return null;
}

/// Return `true` if the [name] is capitalized.
static bool _isNameOfType(String name) {
if (name.isEmpty) {
return false;
}
var firstLetter = name.substring(0, 1);
if (firstLetter.toUpperCase() != firstLetter) {
return false;
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ class ImportLibrary extends MultiCorrectionProducer {
ElementKind.MIXIN,
ElementKind.TYPE_ALIAS,
]);
} else if (mightBeImplicitConstructor(targetNode)) {
} else if (targetNode.mightBeImplicitConstructor) {
var typeName = (targetNode as SimpleIdentifier).name;
await _importLibraryForElement(producers, typeName, const [
ElementKind.CLASS,
Expand All @@ -147,7 +147,6 @@ class ImportLibrary extends MultiCorrectionProducer {
return producers;
}

@override
String? nameOfType(AstNode node) {
var parent = node.parent;
switch (node) {
Expand Down Expand Up @@ -584,3 +583,17 @@ class _ImportRelativeLibrary extends ResolvedCorrectionProducer {
});
}
}

extension on AstNode {
/// Whether this [AstNode] is in a location where an implicit constructor
/// invocation would be allowed.
bool get mightBeImplicitConstructor {
if (this is SimpleIdentifier) {
var parent = this.parent;
if (parent is MethodInvocation) {
return parent.realTarget == null;
}
}
return false;
}
}
Loading

0 comments on commit fca7dd7

Please sign in to comment.