Skip to content

Commit

Permalink
base processor migration; fix to add type annotations
Browse files Browse the repository at this point in the history
Change-Id: Ia35084f29ac54e666b98f1400eeef598512b4f20
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/115761
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Phil Quitslund <pquitslund@google.com>
  • Loading branch information
pq authored and commit-bot@chromium.org committed Sep 5, 2019
1 parent d9a9346 commit 698d120
Show file tree
Hide file tree
Showing 8 changed files with 291 additions and 196 deletions.
208 changes: 23 additions & 185 deletions pkg/analysis_server/lib/src/services/correction/assist_internal.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,15 @@ import 'package:analysis_server/src/services/correction/statement_analyzer.dart'
import 'package:analysis_server/src/services/correction/util.dart';
import 'package:analysis_server/src/services/linter/lint_names.dart';
import 'package:analysis_server/src/services/search/hierarchy.dart';
import 'package:analysis_server/src/utilities/flutter.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/precedence.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/analysis/session_helper.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/utilities.dart';
import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element;
import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_dart.dart';
Expand All @@ -47,41 +41,26 @@ typedef _SimpleIdentifierVisitor(SimpleIdentifier node);
*/
class AssistProcessor extends BaseProcessor {
final DartAssistContext context;

final AnalysisSession session;
final AnalysisSessionHelper sessionHelper;
final TypeProvider typeProvider;
final Flutter flutter;

final List<Assist> assists = <Assist>[];

AssistProcessor(this.context)
: session = context.resolveResult.session,
sessionHelper = AnalysisSessionHelper(context.resolveResult.session),
typeProvider = context.resolveResult.typeProvider,
flutter = Flutter.of(context.resolveResult),
super(
: super(
selectionOffset: context.selectionOffset,
selectionLength: context.selectionLength,
resolvedResult: context.resolveResult,
workspace: context.workspace,
);

/**
* Return the status of the known experiments.
*/
ExperimentStatus get experimentStatus =>
(session.analysisContext.analysisOptions as AnalysisOptionsImpl)
.experimentStatus;

Future<List<Assist>> compute() async {
if (!setupCompute()) {
return assists;
}
if (!_containsErrorCode(
{LintNames.always_specify_types, LintNames.type_annotate_public_apis},
)) {
await _addProposals_addTypeAnnotation();
}

await _addProposal_addTypeAnnotation_DeclaredIdentifier();
await _addProposal_addTypeAnnotation_SimpleFormalParameter();
await _addProposal_addTypeAnnotation_VariableDeclaration();
await _addProposal_assignToLocalVariable();
await _addProposal_convertClassToMixin();
await _addProposal_convertDocumentationIntoBlock();
Expand Down Expand Up @@ -138,8 +117,8 @@ class AssistProcessor extends BaseProcessor {
await _addProposal_splitAndCondition();
await _addProposal_splitVariableDeclaration();
await _addProposal_surroundWith();
if (!_containsDiagnostic(
LintNames.curly_braces_in_flow_control_structures,
if (!_containsErrorCode(
{LintNames.curly_braces_in_flow_control_structures},
)) {
await _addProposal_useCurlyBraces();
}
Expand Down Expand Up @@ -229,160 +208,6 @@ class AssistProcessor extends BaseProcessor {
assists.add(new Assist(kind, change));
}

Future<void> _addProposal_addTypeAnnotation_DeclaredIdentifier() async {
DeclaredIdentifier declaredIdentifier =
node.thisOrAncestorOfType<DeclaredIdentifier>();
if (declaredIdentifier == null) {
ForStatement forEach = node.thisOrAncestorMatching(
(node) => node is ForStatement && node.forLoopParts is ForEachParts);
ForEachParts forEachParts = forEach?.forLoopParts;
int offset = node.offset;
if (forEach != null &&
forEachParts.iterable != null &&
offset < forEachParts.iterable.offset) {
declaredIdentifier = forEachParts is ForEachPartsWithDeclaration
? forEachParts.loopVariable
: null;
}
}
if (declaredIdentifier == null) {
_coverageMarker();
return;
}
// Ensure that there isn't already a type annotation.
if (declaredIdentifier.type != null) {
_coverageMarker();
return;
}
DartType type = declaredIdentifier.identifier.staticType;
if (type is! InterfaceType && type is! FunctionType) {
_coverageMarker();
return;
}
_configureTargetLocation(node);

var changeBuilder = _newDartChangeBuilder();
bool validChange = true;
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
Token keyword = declaredIdentifier.keyword;
if (keyword.keyword == Keyword.VAR) {
builder.addReplacement(range.token(keyword), (DartEditBuilder builder) {
validChange = builder.writeType(type);
});
} else {
builder.addInsertion(declaredIdentifier.identifier.offset,
(DartEditBuilder builder) {
validChange = builder.writeType(type);
builder.write(' ');
});
}
});
if (validChange) {
_addAssistFromBuilder(changeBuilder, DartAssistKind.ADD_TYPE_ANNOTATION);
}
}

Future<void> _addProposal_addTypeAnnotation_SimpleFormalParameter() async {
AstNode node = this.node;
// should be the name of a simple parameter
if (node is! SimpleIdentifier || node.parent is! SimpleFormalParameter) {
_coverageMarker();
return;
}
SimpleIdentifier name = node;
SimpleFormalParameter parameter = node.parent;
// the parameter should not have a type
if (parameter.type != null) {
_coverageMarker();
return;
}
// prepare the type
DartType type = parameter.declaredElement.type;
// TODO(scheglov) If the parameter is in a method declaration, and if the
// method overrides a method that has a type for the corresponding
// parameter, it would be nice to copy down the type from the overridden
// method.
if (type is! InterfaceType) {
_coverageMarker();
return;
}
// prepare type source
_configureTargetLocation(node);

var changeBuilder = _newDartChangeBuilder();
bool validChange = true;
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
builder.addInsertion(name.offset, (DartEditBuilder builder) {
validChange = builder.writeType(type);
builder.write(' ');
});
});
if (validChange) {
_addAssistFromBuilder(changeBuilder, DartAssistKind.ADD_TYPE_ANNOTATION);
}
}

Future<void> _addProposal_addTypeAnnotation_VariableDeclaration() async {
AstNode node = this.node;
// prepare VariableDeclarationList
VariableDeclarationList declarationList =
node.thisOrAncestorOfType<VariableDeclarationList>();
if (declarationList == null) {
_coverageMarker();
return;
}
// may be has type annotation already
if (declarationList.type != null) {
_coverageMarker();
return;
}
// prepare single VariableDeclaration
List<VariableDeclaration> variables = declarationList.variables;
if (variables.length != 1) {
_coverageMarker();
return;
}
VariableDeclaration variable = variables[0];
// must be not after the name of the variable
if (selectionOffset > variable.name.end) {
_coverageMarker();
return;
}
// we need an initializer to get the type from
Expression initializer = variable.initializer;
if (initializer == null) {
_coverageMarker();
return;
}
DartType type = initializer.staticType;
// prepare type source
if ((type is! InterfaceType || type.isDartCoreNull) &&
type is! FunctionType) {
_coverageMarker();
return;
}
_configureTargetLocation(node);

var changeBuilder = _newDartChangeBuilder();
bool validChange = true;
await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
Token keyword = declarationList.keyword;
if (keyword?.keyword == Keyword.VAR) {
builder.addReplacement(range.token(keyword), (DartEditBuilder builder) {
validChange = builder.writeType(type);
});
} else {
builder.addInsertion(variable.offset, (DartEditBuilder builder) {
validChange = builder.writeType(type);
builder.write(' ');
});
}
});
if (validChange) {
_addAssistFromBuilder(changeBuilder, DartAssistKind.ADD_TYPE_ANNOTATION);
}
}

Future<void> _addProposal_assignToLocalVariable() async {
// prepare enclosing ExpressionStatement
ExpressionStatement expressionStatement;
Expand Down Expand Up @@ -3857,6 +3682,19 @@ class AssistProcessor extends BaseProcessor {
_addAssistFromBuilder(changeBuilder, DartAssistKind.USE_CURLY_BRACES);
}

Future<void> _addProposals_addTypeAnnotation() async {
var changeBuilder =
await createBuilder_addTypeAnnotation_DeclaredIdentifier();
_addAssistFromBuilder(changeBuilder, DartAssistKind.ADD_TYPE_ANNOTATION);

changeBuilder =
await createBuilder_addTypeAnnotation_SimpleFormalParameter();
_addAssistFromBuilder(changeBuilder, DartAssistKind.ADD_TYPE_ANNOTATION);

changeBuilder = await createBuilder_addTypeAnnotation_VariableDeclaration();
_addAssistFromBuilder(changeBuilder, DartAssistKind.ADD_TYPE_ANNOTATION);
}

/**
* Return `true` if all of the parameters in the given list of [parameters]
* have an explicit type annotation.
Expand Down Expand Up @@ -3891,14 +3729,14 @@ class AssistProcessor extends BaseProcessor {
}
}

bool _containsDiagnostic(String diagnosticCode) {
bool _containsErrorCode(Set<String> errorCodes) {
final fileOffset = node.offset;
for (var error in context.resolveResult.errors) {
final errorSource = error.source;
if (file == errorSource.fullName) {
if (fileOffset >= error.offset &&
fileOffset <= error.offset + error.length) {
if (error.errorCode.name == diagnosticCode) {
if (errorCodes.contains(error.errorCode.name)) {
return true;
}
}
Expand Down
Loading

0 comments on commit 698d120

Please sign in to comment.