DAS plugins: Bump language version to 3.9
Change-Id: I880e53634c570cc25f4ff22dd01397b088b9bd07 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/447441 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
committed by
Commit Queue
parent
1465c1043a
commit
cbfc0784de
@@ -1,6 +1,7 @@
|
||||
## 0.2.3-dev
|
||||
|
||||
- Require version `8.2.0` of the `analyzer` package.
|
||||
- Require Dart SDK `^3.9.0`.
|
||||
- Add support for automatic re-analysis of files changed on-disk (as opposed to
|
||||
file contents changed in the IDE, which is already supported).
|
||||
|
||||
|
||||
@@ -30,4 +30,5 @@ linter:
|
||||
- unnecessary_library_directive
|
||||
- unnecessary_parenthesis
|
||||
- unreachable_from_main
|
||||
- use_null_aware_elements
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@ final class CorrectionUtils {
|
||||
String? _endOfLine;
|
||||
|
||||
CorrectionUtils(ParsedUnitResult result)
|
||||
: _unit = result.unit,
|
||||
_buffer = result.content;
|
||||
: _unit = result.unit,
|
||||
_buffer = result.content;
|
||||
|
||||
/// The EOL sequence to use for this [CompilationUnit].
|
||||
String get endOfLine {
|
||||
@@ -131,8 +131,10 @@ final class CorrectionUtils {
|
||||
|
||||
/// Returns a [SourceRange] that covers [sourceRange] and extends (if
|
||||
/// possible) to cover whole lines.
|
||||
SourceRange getLinesRange(SourceRange sourceRange,
|
||||
{bool skipLeadingEmptyLines = false}) {
|
||||
SourceRange getLinesRange(
|
||||
SourceRange sourceRange, {
|
||||
bool skipLeadingEmptyLines = false,
|
||||
}) {
|
||||
// Calculate the start:
|
||||
var startOffset = sourceRange.offset;
|
||||
var startLineOffset = getLineContentStart(startOffset);
|
||||
@@ -143,8 +145,9 @@ final class CorrectionUtils {
|
||||
var endOffset = sourceRange.end;
|
||||
var afterEndLineOffset = endOffset;
|
||||
var lineInfo = _unit.lineInfo;
|
||||
var lineStart = lineInfo
|
||||
.getOffsetOfLine(lineInfo.getLocation(startLineOffset).lineNumber - 1);
|
||||
var lineStart = lineInfo.getOffsetOfLine(
|
||||
lineInfo.getLocation(startLineOffset).lineNumber - 1,
|
||||
);
|
||||
if (lineStart == startLineOffset) {
|
||||
// Only consume line endings after the end of the range if there is
|
||||
// nothing else on the line containing the beginning of the range.
|
||||
@@ -184,10 +187,7 @@ final class CorrectionUtils {
|
||||
|
||||
/// Returns the text of the given [AstNode] in the unit, including preceding
|
||||
/// comments.
|
||||
String getNodeText(
|
||||
AstNode node, {
|
||||
bool withLeadingComments = false,
|
||||
}) {
|
||||
String getNodeText(AstNode node, {bool withLeadingComments = false}) {
|
||||
var firstToken = withLeadingComments
|
||||
? node.beginToken.precedingComments ?? node.beginToken
|
||||
: node.beginToken;
|
||||
@@ -252,8 +252,13 @@ final class CorrectionUtils {
|
||||
/// Usually [includeLeading] and [ensureTrailingNewline] are set together,
|
||||
/// when indenting a set of statements to go inside a block (as opposed to
|
||||
/// just wrapping a nested expression that might span multiple lines).
|
||||
String replaceSourceIndent(String source, String oldIndent, String newIndent,
|
||||
{bool includeLeading = false, bool ensureTrailingNewline = false}) {
|
||||
String replaceSourceIndent(
|
||||
String source,
|
||||
String oldIndent,
|
||||
String newIndent, {
|
||||
bool includeLeading = false,
|
||||
bool ensureTrailingNewline = false,
|
||||
}) {
|
||||
// Prepare token ranges.
|
||||
var lineRanges = <SourceRange>[];
|
||||
{
|
||||
@@ -323,12 +328,20 @@ final class CorrectionUtils {
|
||||
/// when indenting a set of statements to go inside a block (as opposed to
|
||||
/// just wrapping a nested expression that might span multiple lines).
|
||||
String replaceSourceRangeIndent(
|
||||
SourceRange range, String oldIndent, String newIndent,
|
||||
{bool includeLeading = false, bool ensureTrailingNewline = false}) {
|
||||
SourceRange range,
|
||||
String oldIndent,
|
||||
String newIndent, {
|
||||
bool includeLeading = false,
|
||||
bool ensureTrailingNewline = false,
|
||||
}) {
|
||||
var oldSource = getRangeText(range);
|
||||
return replaceSourceIndent(oldSource, oldIndent, newIndent,
|
||||
includeLeading: includeLeading,
|
||||
ensureTrailingNewline: ensureTrailingNewline);
|
||||
return replaceSourceIndent(
|
||||
oldSource,
|
||||
oldIndent,
|
||||
newIndent,
|
||||
includeLeading: includeLeading,
|
||||
ensureTrailingNewline: ensureTrailingNewline,
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns the [_InvertedCondition] for the given logical expression.
|
||||
@@ -367,13 +380,21 @@ final class CorrectionUtils {
|
||||
ls = _invertCondition0(le);
|
||||
rs = _invertCondition0(re);
|
||||
return _InvertedCondition._binary(
|
||||
TokenType.BAR_BAR.precedence, ls, ' || ', rs);
|
||||
TokenType.BAR_BAR.precedence,
|
||||
ls,
|
||||
' || ',
|
||||
rs,
|
||||
);
|
||||
}
|
||||
if (operator == TokenType.BAR_BAR) {
|
||||
ls = _invertCondition0(le);
|
||||
rs = _invertCondition0(re);
|
||||
return _InvertedCondition._binary(
|
||||
TokenType.AMPERSAND_AMPERSAND.precedence, ls, ' && ', rs);
|
||||
TokenType.AMPERSAND_AMPERSAND.precedence,
|
||||
ls,
|
||||
' && ',
|
||||
rs,
|
||||
);
|
||||
}
|
||||
} else if (expression is IsExpression) {
|
||||
var expressionSource = getNodeText(expression.expression);
|
||||
@@ -432,14 +453,15 @@ class TokenUtils {
|
||||
static List<Token> getTokens(String s, FeatureSet featureSet) {
|
||||
try {
|
||||
var tokens = <Token>[];
|
||||
var scanner = Scanner(
|
||||
_SourceMock(),
|
||||
CharSequenceReader(s),
|
||||
DiagnosticListener.nullListener,
|
||||
)..configureFeatures(
|
||||
featureSetForOverriding: featureSet,
|
||||
featureSet: featureSet,
|
||||
);
|
||||
var scanner =
|
||||
Scanner(
|
||||
_SourceMock(),
|
||||
CharSequenceReader(s),
|
||||
DiagnosticListener.nullListener,
|
||||
)..configureFeatures(
|
||||
featureSetForOverriding: featureSet,
|
||||
featureSet: featureSet,
|
||||
);
|
||||
var token = scanner.tokenize();
|
||||
while (!token.isEof) {
|
||||
tokens.add(token);
|
||||
@@ -460,25 +482,37 @@ class _InvertedCondition {
|
||||
|
||||
_InvertedCondition(this._precedence, this._source);
|
||||
|
||||
static _InvertedCondition _binary(int precedence, _InvertedCondition left,
|
||||
String operation, _InvertedCondition right) {
|
||||
var src = _parenthesizeIfRequired(left, precedence) +
|
||||
static _InvertedCondition _binary(
|
||||
int precedence,
|
||||
_InvertedCondition left,
|
||||
String operation,
|
||||
_InvertedCondition right,
|
||||
) {
|
||||
var src =
|
||||
_parenthesizeIfRequired(left, precedence) +
|
||||
operation +
|
||||
_parenthesizeIfRequired(right, precedence);
|
||||
return _InvertedCondition(precedence, src);
|
||||
}
|
||||
|
||||
static _InvertedCondition _binary2(
|
||||
_InvertedCondition left, String operation, _InvertedCondition right) {
|
||||
_InvertedCondition left,
|
||||
String operation,
|
||||
_InvertedCondition right,
|
||||
) {
|
||||
// TODO(scheglov): consider merging with "_binary()" after testing
|
||||
return _InvertedCondition(
|
||||
1 << 20, '${left._source}$operation${right._source}');
|
||||
1 << 20,
|
||||
'${left._source}$operation${right._source}',
|
||||
);
|
||||
}
|
||||
|
||||
/// Adds enclosing parenthesis if the precedence of the [_InvertedCondition]
|
||||
/// if less than the precedence of the expression we are going it to use in.
|
||||
static String _parenthesizeIfRequired(
|
||||
_InvertedCondition expr, int newOperatorPrecedence) {
|
||||
_InvertedCondition expr,
|
||||
int newOperatorPrecedence,
|
||||
) {
|
||||
if (expr._precedence < newOperatorPrecedence) {
|
||||
return '(${expr._source})';
|
||||
}
|
||||
|
||||
@@ -168,8 +168,10 @@ sealed class CorrectionProducer<T extends ParsedUnitResult>
|
||||
}
|
||||
var diagnosticOffset = diagnostic.problemMessage.offset;
|
||||
var diagnosticLength = diagnostic.problemMessage.length;
|
||||
return _coveringNode =
|
||||
unit.nodeCovering(offset: diagnosticOffset, length: diagnosticLength);
|
||||
return _coveringNode = unit.nodeCovering(
|
||||
offset: diagnosticOffset,
|
||||
length: diagnosticLength,
|
||||
);
|
||||
}
|
||||
|
||||
/// The length of the source range associated with the diagnostic being
|
||||
@@ -242,15 +244,15 @@ final class CorrectionProducerContext {
|
||||
required Token token,
|
||||
required int selectionOffset,
|
||||
required int selectionLength,
|
||||
}) : _libraryResult = libraryResult,
|
||||
_unitResult = unitResult,
|
||||
_sessionHelper = AnalysisSessionHelper(unitResult.session),
|
||||
_utils = dartFixContext?.correctionUtils ?? CorrectionUtils(unitResult),
|
||||
_applyingBulkFixes = applyingBulkFixes,
|
||||
_diagnostic = diagnostic,
|
||||
_token = token,
|
||||
_selectionOffset = selectionOffset,
|
||||
_selectionLength = selectionLength;
|
||||
}) : _libraryResult = libraryResult,
|
||||
_unitResult = unitResult,
|
||||
_sessionHelper = AnalysisSessionHelper(unitResult.session),
|
||||
_utils = dartFixContext?.correctionUtils ?? CorrectionUtils(unitResult),
|
||||
_applyingBulkFixes = applyingBulkFixes,
|
||||
_diagnostic = diagnostic,
|
||||
_token = token,
|
||||
_selectionOffset = selectionOffset,
|
||||
_selectionLength = selectionLength;
|
||||
|
||||
String get path => _unitResult.path;
|
||||
|
||||
@@ -296,8 +298,10 @@ final class CorrectionProducerContext {
|
||||
int selectionOffset = -1,
|
||||
int selectionLength = 0,
|
||||
}) {
|
||||
var node = unitResult.unit
|
||||
.nodeCovering(offset: selectionOffset, length: selectionLength);
|
||||
var node = unitResult.unit.nodeCovering(
|
||||
offset: selectionOffset,
|
||||
length: selectionLength,
|
||||
);
|
||||
node ??= unitResult.unit;
|
||||
|
||||
var token = _tokenAt(node, selectionOffset) ?? node.beginToken;
|
||||
@@ -445,7 +449,8 @@ abstract class ResolvedCorrectionProducer
|
||||
/// Returns the extension declaration for the given [fragment], or `null` if
|
||||
/// there is no such extension.
|
||||
Future<ExtensionDeclaration?> getExtensionDeclaration(
|
||||
ExtensionFragment fragment) async {
|
||||
ExtensionFragment fragment,
|
||||
) async {
|
||||
var result = await sessionHelper.getFragmentDeclaration(fragment);
|
||||
var node = result?.node;
|
||||
if (node is ExtensionDeclaration) {
|
||||
@@ -457,7 +462,8 @@ abstract class ResolvedCorrectionProducer
|
||||
/// Returns the extension type for the given [fragment], or `null` if there
|
||||
/// is no such extension type.
|
||||
Future<ExtensionTypeDeclaration?> getExtensionTypeDeclaration(
|
||||
ExtensionTypeFragment fragment) async {
|
||||
ExtensionTypeFragment fragment,
|
||||
) async {
|
||||
var result = await sessionHelper.getFragmentDeclaration(fragment);
|
||||
var node = result?.node;
|
||||
if (node is ExtensionTypeDeclaration) {
|
||||
@@ -588,11 +594,10 @@ abstract class ResolvedCorrectionProducer
|
||||
} else if (assignment.writeType case var expectedType?) {
|
||||
// `v += myFunction();`.
|
||||
var method = assignment.element;
|
||||
if (method
|
||||
case MethodElement(
|
||||
:var returnType,
|
||||
formalParameters: List(length: 1, :var first),
|
||||
)) {
|
||||
if (method case MethodElement(
|
||||
:var returnType,
|
||||
formalParameters: List(length: 1, :var first),
|
||||
)) {
|
||||
if (typeSystem.isAssignableTo(returnType, expectedType)) {
|
||||
// The return type is assignable to the expected type, then use
|
||||
// the expected parameter type.
|
||||
@@ -708,10 +713,13 @@ abstract class ResolvedCorrectionProducer
|
||||
/// Looks if the [expression] is directly inside a closure and returns the
|
||||
/// return type of the closure.
|
||||
DartType? _closureReturnType(Expression expression) {
|
||||
if (expression.enclosingClosure
|
||||
case FunctionExpression(:var correspondingParameter, :var staticType)) {
|
||||
if (correspondingParameter?.type ?? staticType
|
||||
case FunctionType(:var returnType)) {
|
||||
if (expression.enclosingClosure case FunctionExpression(
|
||||
:var correspondingParameter,
|
||||
:var staticType,
|
||||
)) {
|
||||
if (correspondingParameter?.type ?? staticType case FunctionType(
|
||||
:var returnType,
|
||||
)) {
|
||||
return returnType;
|
||||
}
|
||||
}
|
||||
@@ -757,7 +765,7 @@ sealed class _AbstractCorrectionProducer<T extends ParsedUnitResult> {
|
||||
final CorrectionProducerContext _context;
|
||||
|
||||
_AbstractCorrectionProducer({required CorrectionProducerContext context})
|
||||
: _context = context;
|
||||
: _context = context;
|
||||
|
||||
/// Whether the fixes are being built for the bulk-fix request.
|
||||
bool get applyingBulkFixes => _context._applyingBulkFixes;
|
||||
@@ -796,10 +804,11 @@ sealed class _AbstractCorrectionProducer<T extends ParsedUnitResult> {
|
||||
|
||||
CorrectionUtils get utils => _context._utils;
|
||||
|
||||
CodeStyleOptions getCodeStyleOptions(File file) =>
|
||||
sessionHelper.session.analysisContext
|
||||
.getAnalysisOptionsForFile(file)
|
||||
.codeStyleOptions;
|
||||
CodeStyleOptions getCodeStyleOptions(File file) => sessionHelper
|
||||
.session
|
||||
.analysisContext
|
||||
.getAnalysisOptionsForFile(file)
|
||||
.codeStyleOptions;
|
||||
|
||||
/// Returns the function body of the most deeply nested method or function
|
||||
/// that encloses the [node], or `null` if the node is not in a method or
|
||||
|
||||
@@ -50,7 +50,7 @@ class DartFixContext implements FixContext {
|
||||
/// least some getFixes requsts. Caching the response can speed up such
|
||||
/// requests.
|
||||
final Map<String, Future<Map<LibraryElement, Element>>>
|
||||
_cachedTopLevelDeclarations = {};
|
||||
_cachedTopLevelDeclarations = {};
|
||||
|
||||
@override
|
||||
final Diagnostic diagnostic;
|
||||
@@ -64,8 +64,8 @@ class DartFixContext implements FixContext {
|
||||
required Diagnostic error,
|
||||
this.autoTriggered = false,
|
||||
CorrectionUtils? correctionUtils,
|
||||
}) : diagnostic = error,
|
||||
correctionUtils = correctionUtils ?? CorrectionUtils(unitResult);
|
||||
}) : diagnostic = error,
|
||||
correctionUtils = correctionUtils ?? CorrectionUtils(unitResult);
|
||||
|
||||
@override
|
||||
Diagnostic get error => diagnostic;
|
||||
@@ -95,9 +95,7 @@ class DartFixContext implements FixContext {
|
||||
await analysisDriver.discoverAvailableFiles();
|
||||
|
||||
var fsState = analysisDriver.fsState;
|
||||
var filter = FileStateFilter(
|
||||
fsState.getFileForPath(unitResult.path),
|
||||
);
|
||||
var filter = FileStateFilter(fsState.getFileForPath(unitResult.path));
|
||||
|
||||
for (var file in fsState.knownFiles.toList()) {
|
||||
if (!filter.shouldInclude(file)) {
|
||||
|
||||
@@ -24,13 +24,13 @@ class _RegisteredAssistGenerators {
|
||||
/// A mapping from registered _assist_ producer generators to the [LintCode]s
|
||||
/// for which they may also act as a _fix_ producer generator.
|
||||
Map<ProducerGenerator, Set<LintCode>> get lintRuleMap => _lintRuleMap ??= {
|
||||
for (var generator in producerGenerators)
|
||||
generator: {
|
||||
for (var MapEntry(key: lintName, value: generators)
|
||||
in registeredFixGenerators.lintProducers.entries)
|
||||
if (generators.contains(generator)) lintName,
|
||||
},
|
||||
};
|
||||
for (var generator in producerGenerators)
|
||||
generator: {
|
||||
for (var MapEntry(key: lintName, value: generators)
|
||||
in registeredFixGenerators.lintProducers.entries)
|
||||
if (generators.contains(generator)) lintName,
|
||||
},
|
||||
};
|
||||
|
||||
void registerGenerator(ProducerGenerator generator) {
|
||||
producerGenerators.add(generator);
|
||||
|
||||
@@ -13,12 +13,10 @@ import 'package:analyzer/src/generated/java_core.dart';
|
||||
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
|
||||
import 'package:analyzer_plugin/utilities/change_builder/conflicting_edit_exception.dart';
|
||||
|
||||
Future<List<Assist>> computeAssists(DartAssistContext context,
|
||||
{AssistPerformance? performance}) =>
|
||||
AssistProcessor(
|
||||
context,
|
||||
performance: performance,
|
||||
).compute();
|
||||
Future<List<Assist>> computeAssists(
|
||||
DartAssistContext context, {
|
||||
AssistPerformance? performance,
|
||||
}) => AssistProcessor(context, performance: performance).compute();
|
||||
|
||||
/// The computer for Dart assists.
|
||||
class AssistProcessor {
|
||||
@@ -29,7 +27,7 @@ class AssistProcessor {
|
||||
final List<Assist> _assists = [];
|
||||
|
||||
AssistProcessor(this._assistContext, {AssistPerformance? performance})
|
||||
: _performance = performance;
|
||||
: _performance = performance;
|
||||
|
||||
Future<List<Assist>> compute() async {
|
||||
_timer.start();
|
||||
@@ -68,10 +66,7 @@ class AssistProcessor {
|
||||
return;
|
||||
}
|
||||
change.id = assistKind.id;
|
||||
change.message = formatList(
|
||||
assistKind.message,
|
||||
producer.assistArguments,
|
||||
);
|
||||
change.message = formatList(assistKind.message, producer.assistArguments);
|
||||
_assists.add(Assist(assistKind, change));
|
||||
} on ConflictingEditException catch (exception, stackTrace) {
|
||||
// Handle the exception by (a) not adding an assist based on the
|
||||
|
||||
@@ -9,12 +9,16 @@ import 'package:analyzer/error/error.dart';
|
||||
final registeredFixGenerators = _RegisteredFixGenerators();
|
||||
|
||||
/// A function that can be executed to create a [MultiCorrectionProducer].
|
||||
typedef MultiProducerGenerator = MultiCorrectionProducer Function(
|
||||
{required CorrectionProducerContext context});
|
||||
typedef MultiProducerGenerator =
|
||||
MultiCorrectionProducer Function({
|
||||
required CorrectionProducerContext context,
|
||||
});
|
||||
|
||||
/// A function that can be executed to create a [CorrectionProducer].
|
||||
typedef ProducerGenerator = CorrectionProducer<ParsedUnitResult> Function(
|
||||
{required CorrectionProducerContext context});
|
||||
typedef ProducerGenerator =
|
||||
CorrectionProducer<ParsedUnitResult> Function({
|
||||
required CorrectionProducerContext context,
|
||||
});
|
||||
|
||||
/// The collection of various registered [ProducerGenerator]s and
|
||||
/// [MultiProducerGenerator]s, accessed through [registeredFixGenerators].
|
||||
@@ -33,7 +37,7 @@ class _RegisteredFixGenerators {
|
||||
///
|
||||
/// The generators used for lint rules are in the [lintMultiProducers].
|
||||
final Map<DiagnosticCode, List<MultiProducerGenerator>>
|
||||
nonLintMultiProducers = {};
|
||||
nonLintMultiProducers = {};
|
||||
|
||||
/// A set of generators that are used to create correction producers that
|
||||
/// produce corrections that ignore diagnostics locally.
|
||||
|
||||
@@ -40,27 +40,35 @@ final class FixInFileProcessor {
|
||||
// like many more errors than generators.
|
||||
if (alreadyCalculated != null) {
|
||||
generators = generators
|
||||
.where((generator) => !alreadyCalculated!
|
||||
.contains(getAlreadyCalculatedValue(generator)))
|
||||
.where(
|
||||
(generator) => !alreadyCalculated!.contains(
|
||||
getAlreadyCalculatedValue(generator),
|
||||
),
|
||||
)
|
||||
.toList(growable: false);
|
||||
}
|
||||
if (generators.isEmpty) {
|
||||
return const <Fix>[];
|
||||
}
|
||||
|
||||
var diagnostics = _fixContext.unitResult.diagnostics
|
||||
.where((e) => diagnostic.diagnosticCode.name == e.diagnosticCode.name);
|
||||
var diagnostics = _fixContext.unitResult.diagnostics.where(
|
||||
(e) => diagnostic.diagnosticCode.name == e.diagnosticCode.name,
|
||||
);
|
||||
if (diagnostics.length < 2) {
|
||||
return const <Fix>[];
|
||||
}
|
||||
|
||||
var fixes = <Fix>[];
|
||||
for (var generator in generators) {
|
||||
if (generator(context: StubCorrectionProducerContext.instance)
|
||||
.canBeAppliedAcrossSingleFile) {
|
||||
_FixState fixState = _EmptyFixState(ChangeBuilder(
|
||||
if (generator(
|
||||
context: StubCorrectionProducerContext.instance,
|
||||
).canBeAppliedAcrossSingleFile) {
|
||||
_FixState fixState = _EmptyFixState(
|
||||
ChangeBuilder(
|
||||
workspace: _fixContext.workspace,
|
||||
defaultEol: CorrectionUtils(_fixContext.unitResult).endOfLine));
|
||||
defaultEol: CorrectionUtils(_fixContext.unitResult).endOfLine,
|
||||
),
|
||||
);
|
||||
|
||||
// First, try to fix the specific error we started from. We should only
|
||||
// include fix-all-in-file when we produce an individual fix at this
|
||||
@@ -73,8 +81,12 @@ final class FixInFileProcessor {
|
||||
error: diagnostic,
|
||||
correctionUtils: _fixContext.correctionUtils,
|
||||
);
|
||||
fixState =
|
||||
await _fixDiagnostic(fixContext, fixState, generator, diagnostic);
|
||||
fixState = await _fixDiagnostic(
|
||||
fixContext,
|
||||
fixState,
|
||||
generator,
|
||||
diagnostic,
|
||||
);
|
||||
|
||||
// The original error was not fixable; continue to next generator.
|
||||
if (!(fixState.builder as ChangeBuilderImpl).hasEdits) {
|
||||
|
||||
@@ -14,17 +14,21 @@ import 'package:analyzer/src/generated/java_core.dart';
|
||||
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
|
||||
import 'package:analyzer_plugin/utilities/change_builder/conflicting_edit_exception.dart';
|
||||
|
||||
Future<List<Fix>> computeFixes(DartFixContext context,
|
||||
{FixPerformance? performance,
|
||||
Set<String>? skipAlreadyCalculatedIfNonNull}) async {
|
||||
Future<List<Fix>> computeFixes(
|
||||
DartFixContext context, {
|
||||
FixPerformance? performance,
|
||||
Set<String>? skipAlreadyCalculatedIfNonNull,
|
||||
}) async {
|
||||
return [
|
||||
...await FixProcessor(context,
|
||||
performance: performance,
|
||||
alreadyCalculated: skipAlreadyCalculatedIfNonNull)
|
||||
.compute(),
|
||||
...await FixInFileProcessor(context,
|
||||
alreadyCalculated: skipAlreadyCalculatedIfNonNull)
|
||||
.compute(),
|
||||
...await FixProcessor(
|
||||
context,
|
||||
performance: performance,
|
||||
alreadyCalculated: skipAlreadyCalculatedIfNonNull,
|
||||
).compute(),
|
||||
...await FixInFileProcessor(
|
||||
context,
|
||||
alreadyCalculated: skipAlreadyCalculatedIfNonNull,
|
||||
).compute(),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -72,7 +76,9 @@ class FixProcessor {
|
||||
}
|
||||
|
||||
var builder = ChangeBuilder(
|
||||
workspace: _fixContext.workspace, defaultEol: producer.defaultEol);
|
||||
workspace: _fixContext.workspace,
|
||||
defaultEol: producer.defaultEol,
|
||||
);
|
||||
try {
|
||||
var fixKind = producer.fixKind;
|
||||
|
||||
@@ -152,9 +158,11 @@ class FixProcessor {
|
||||
for (var generator in registeredFixGenerators.ignoreProducerGenerators) {
|
||||
var producer = generator(context: context);
|
||||
if (producer.fixKind == ignoreErrorAnalysisFileKind) {
|
||||
if (alreadyCalculated?.add('${generator.hashCode}|'
|
||||
'${ignoreErrorAnalysisFileKind.id}|'
|
||||
'${diagnostic.diagnosticCode.name}') ==
|
||||
if (alreadyCalculated?.add(
|
||||
'${generator.hashCode}|'
|
||||
'${ignoreErrorAnalysisFileKind.id}|'
|
||||
'${diagnostic.diagnosticCode.name}',
|
||||
) ==
|
||||
false) {
|
||||
// We did this before and was asked to not do it again. Skip.
|
||||
continue;
|
||||
|
||||
@@ -216,8 +216,9 @@ class IgnoreDiagnosticOnLine extends _DartIgnoreDiagnostic {
|
||||
lineNumber - 1,
|
||||
);
|
||||
var lineStart = unitResult.lineInfo.getOffsetOfLine(lineNumber);
|
||||
var line =
|
||||
unitResult.content.substring(previousLineStart, lineStart).trim();
|
||||
var line = unitResult.content
|
||||
.substring(previousLineStart, lineStart)
|
||||
.trim();
|
||||
|
||||
if (line.startsWith(IgnoreInfo.ignoreMatcher)) {
|
||||
builder.addSimpleInsertion(lineStart - eol.length, ', $_code');
|
||||
|
||||
@@ -63,8 +63,10 @@ class PluginServer {
|
||||
|
||||
final OverlayResourceProvider _resourceProvider;
|
||||
|
||||
late final ByteStore _byteStore =
|
||||
MemoryCachingByteStore(NullByteStore(), 1024 * 1024 * 256);
|
||||
late final ByteStore _byteStore = MemoryCachingByteStore(
|
||||
NullByteStore(),
|
||||
1024 * 1024 * 256,
|
||||
);
|
||||
|
||||
AnalysisContextCollectionImpl? _contextCollection;
|
||||
|
||||
@@ -86,8 +88,8 @@ class PluginServer {
|
||||
PluginServer({
|
||||
required ResourceProvider resourceProvider,
|
||||
required List<Plugin> plugins,
|
||||
}) : _resourceProvider = OverlayResourceProvider(resourceProvider),
|
||||
_plugins = plugins {
|
||||
}) : _resourceProvider = OverlayResourceProvider(resourceProvider),
|
||||
_plugins = plugins {
|
||||
for (var plugin in plugins) {
|
||||
plugin.register(_registry);
|
||||
}
|
||||
@@ -98,8 +100,9 @@ class PluginServer {
|
||||
///
|
||||
/// Throws a [RequestFailure] if the request could not be handled.
|
||||
Future<protocol.AnalysisSetPriorityFilesResult>
|
||||
handleAnalysisSetPriorityFiles(
|
||||
protocol.AnalysisSetPriorityFilesParams parameters) async {
|
||||
handleAnalysisSetPriorityFiles(
|
||||
protocol.AnalysisSetPriorityFilesParams parameters,
|
||||
) async {
|
||||
_priorityPaths = parameters.files.toSet();
|
||||
return protocol.AnalysisSetPriorityFilesResult();
|
||||
}
|
||||
@@ -108,7 +111,8 @@ class PluginServer {
|
||||
///
|
||||
/// Throws a [RequestFailure] if the request could not be handled.
|
||||
Future<protocol.EditGetAssistsResult> handleEditGetAssists(
|
||||
protocol.EditGetAssistsParams parameters) async {
|
||||
protocol.EditGetAssistsParams parameters,
|
||||
) async {
|
||||
var path = parameters.file;
|
||||
|
||||
var recentState = _recentState[path];
|
||||
@@ -117,8 +121,9 @@ class PluginServer {
|
||||
}
|
||||
|
||||
var (:analysisContext, :errors) = recentState;
|
||||
var libraryResult =
|
||||
await analysisContext.currentSession.getResolvedLibrary(path);
|
||||
var libraryResult = await analysisContext.currentSession.getResolvedLibrary(
|
||||
path,
|
||||
);
|
||||
if (libraryResult is! ResolvedLibraryResult) {
|
||||
return protocol.EditGetAssistsResult(const []);
|
||||
}
|
||||
@@ -153,7 +158,7 @@ class PluginServer {
|
||||
|
||||
var corrections = [
|
||||
for (var assist in assists..sort(Assist.compareAssists))
|
||||
protocol.PrioritizedSourceChange(assist.kind.priority, assist.change)
|
||||
protocol.PrioritizedSourceChange(assist.kind.priority, assist.change),
|
||||
];
|
||||
return protocol.EditGetAssistsResult(corrections);
|
||||
}
|
||||
@@ -162,7 +167,8 @@ class PluginServer {
|
||||
///
|
||||
/// Throws a [RequestFailure] if the request could not be handled.
|
||||
Future<protocol.EditGetFixesResult> handleEditGetFixes(
|
||||
protocol.EditGetFixesParams parameters) async {
|
||||
protocol.EditGetFixesParams parameters,
|
||||
) async {
|
||||
var path = parameters.file;
|
||||
var offset = parameters.offset;
|
||||
|
||||
@@ -173,8 +179,9 @@ class PluginServer {
|
||||
|
||||
var (:analysisContext, :errors) = recentState;
|
||||
|
||||
var libraryResult =
|
||||
await analysisContext.currentSession.getResolvedLibrary(path);
|
||||
var libraryResult = await analysisContext.currentSession.getResolvedLibrary(
|
||||
path,
|
||||
);
|
||||
if (libraryResult is! ResolvedLibraryResult) {
|
||||
return protocol.EditGetFixesResult(const []);
|
||||
}
|
||||
@@ -183,8 +190,9 @@ class PluginServer {
|
||||
return protocol.EditGetFixesResult(const []);
|
||||
}
|
||||
|
||||
var lintAtOffset =
|
||||
errors.where((error) => error.diagnostic.offset == offset);
|
||||
var lintAtOffset = errors.where(
|
||||
(error) => error.diagnostic.offset == offset,
|
||||
);
|
||||
if (lintAtOffset.isEmpty) return protocol.EditGetFixesResult(const []);
|
||||
|
||||
var errorFixesList = <protocol.AnalysisErrorFixes>[];
|
||||
@@ -225,26 +233,31 @@ class PluginServer {
|
||||
|
||||
/// Handles a 'plugin.versionCheck' request.
|
||||
Future<protocol.PluginVersionCheckResult> handlePluginVersionCheck(
|
||||
protocol.PluginVersionCheckParams parameters) async {
|
||||
protocol.PluginVersionCheckParams parameters,
|
||||
) async {
|
||||
// TODO(srawlins): It seems improper for _this_ method to be the point where
|
||||
// the SDK path is configured...
|
||||
_sdkPath = parameters.sdkPath;
|
||||
return protocol.PluginVersionCheckResult(
|
||||
true, 'Plugin Server', '0.0.1', ['*.dart']);
|
||||
return protocol.PluginVersionCheckResult(true, 'Plugin Server', '0.0.1', [
|
||||
'*.dart',
|
||||
]);
|
||||
}
|
||||
|
||||
/// Initializes each of the registered plugins.
|
||||
Future<void> initialize() async {
|
||||
await Future.wait(
|
||||
_plugins.map((p) => p.start()).whereType<Future<Object?>>());
|
||||
_plugins.map((p) => p.start()).whereType<Future<Object?>>(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Starts this plugin by listening to the given communication [channel].
|
||||
void start(PluginCommunicationChannel channel) {
|
||||
_channel = channel;
|
||||
_channel.listen(_handleRequestZoned,
|
||||
// TODO(srawlins): Implement.
|
||||
onDone: () {});
|
||||
_channel.listen(
|
||||
_handleRequestZoned,
|
||||
// TODO(srawlins): Implement.
|
||||
onDone: () {},
|
||||
);
|
||||
}
|
||||
|
||||
/// This method is invoked when a new instance of [AnalysisContextCollection]
|
||||
@@ -253,8 +266,10 @@ class PluginServer {
|
||||
required AnalysisContextCollection contextCollection,
|
||||
}) async {
|
||||
_channel.sendNotification(
|
||||
protocol.PluginStatusParams(analysis: protocol.AnalysisStatus(true))
|
||||
.toNotification());
|
||||
protocol.PluginStatusParams(
|
||||
analysis: protocol.AnalysisStatus(true),
|
||||
).toNotification(),
|
||||
);
|
||||
await _forAnalysisContexts(contextCollection, (analysisContext) async {
|
||||
var paths = analysisContext.contextRoot
|
||||
.analyzedFiles()
|
||||
@@ -264,14 +279,13 @@ class PluginServer {
|
||||
.where((p) => file_paths.isDart(_resourceProvider.pathContext, p))
|
||||
.toSet();
|
||||
|
||||
await _analyzeFiles(
|
||||
analysisContext: analysisContext,
|
||||
paths: paths,
|
||||
);
|
||||
await _analyzeFiles(analysisContext: analysisContext, paths: paths);
|
||||
});
|
||||
_channel.sendNotification(
|
||||
protocol.PluginStatusParams(analysis: protocol.AnalysisStatus(false))
|
||||
.toNotification());
|
||||
protocol.PluginStatusParams(
|
||||
analysis: protocol.AnalysisStatus(false),
|
||||
).toNotification(),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _analyzeFile({
|
||||
@@ -286,7 +300,8 @@ class PluginServer {
|
||||
analysisOptions: analysisOptions as AnalysisOptionsImpl,
|
||||
);
|
||||
_channel.sendNotification(
|
||||
protocol.AnalysisErrorsParams(path, diagnostics).toNotification());
|
||||
protocol.AnalysisErrorsParams(path, diagnostics).toNotification(),
|
||||
);
|
||||
}
|
||||
|
||||
/// Analyzes the files at the given [paths].
|
||||
@@ -312,8 +327,9 @@ class PluginServer {
|
||||
String path, {
|
||||
required AnalysisOptionsImpl analysisOptions,
|
||||
}) async {
|
||||
var libraryResult =
|
||||
await analysisContext.currentSession.getResolvedLibrary(path);
|
||||
var libraryResult = await analysisContext.currentSession.getResolvedLibrary(
|
||||
path,
|
||||
);
|
||||
if (libraryResult is! ResolvedLibraryResult) {
|
||||
return const [];
|
||||
}
|
||||
@@ -323,7 +339,9 @@ class PluginServer {
|
||||
}
|
||||
var listener = RecordingDiagnosticListener();
|
||||
var diagnosticReporter = DiagnosticReporter(
|
||||
listener, unitResult.libraryElement.firstFragment.source);
|
||||
listener,
|
||||
unitResult.libraryElement.firstFragment.source,
|
||||
);
|
||||
|
||||
var currentUnit = RuleContextUnit(
|
||||
file: unitResult.file,
|
||||
@@ -363,8 +381,9 @@ class PluginServer {
|
||||
for (var configuration in analysisOptions.pluginConfigurations) {
|
||||
if (!configuration.isEnabled) continue;
|
||||
// TODO(srawlins): Namespace rules by their plugin, to avoid collisions.
|
||||
var rules =
|
||||
Registry.ruleRegistry.enabled(configuration.diagnosticConfigs);
|
||||
var rules = Registry.ruleRegistry.enabled(
|
||||
configuration.diagnosticConfigs,
|
||||
);
|
||||
for (var rule in rules) {
|
||||
rule.reporter = diagnosticReporter;
|
||||
// TODO(srawlins): Enable timing similar to what the linter package's
|
||||
@@ -374,13 +393,16 @@ class PluginServer {
|
||||
for (var code in rules.expand((r) => r.diagnosticCodes)) {
|
||||
pluginCodeMapping.putIfAbsent(code, () => configuration.name);
|
||||
severityMapping.putIfAbsent(
|
||||
code, () => _configuredSeverity(configuration, code));
|
||||
code,
|
||||
() => _configuredSeverity(configuration, code),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
context.currentUnit = currentUnit;
|
||||
currentUnit.unit.accept(
|
||||
AnalysisRuleVisitor(nodeRegistry, shouldPropagateExceptions: true));
|
||||
AnalysisRuleVisitor(nodeRegistry, shouldPropagateExceptions: true),
|
||||
);
|
||||
|
||||
var ignoreInfo = IgnoreInfo.forDart(unitResult.unit, unitResult.content);
|
||||
var diagnostics = listener.diagnostics.where((e) {
|
||||
@@ -409,7 +431,7 @@ class PluginServer {
|
||||
correction: diagnostic.correctionMessage,
|
||||
// TODO(srawlins): Use a valid value here.
|
||||
hasFix: true,
|
||||
)
|
||||
),
|
||||
),
|
||||
];
|
||||
_recentState[path] = (
|
||||
@@ -421,23 +443,27 @@ class PluginServer {
|
||||
|
||||
/// Converts the severity of [code] into a [protocol.AnalysisErrorSeverity].
|
||||
protocol.AnalysisErrorSeverity? _configuredSeverity(
|
||||
PluginConfiguration configuration, DiagnosticCode code) {
|
||||
PluginConfiguration configuration,
|
||||
DiagnosticCode code,
|
||||
) {
|
||||
var configuredSeverity =
|
||||
configuration.diagnosticConfigs[code.name]?.severity;
|
||||
if (configuredSeverity != null &&
|
||||
configuredSeverity != ConfiguredSeverity.enable) {
|
||||
var severityName = configuredSeverity.name.toUpperCase();
|
||||
var severity =
|
||||
protocol.AnalysisErrorSeverity.values.asNameMap()[severityName];
|
||||
assert(severity != null,
|
||||
'Invalid configured severity: ${configuredSeverity.name}');
|
||||
var severity = protocol.AnalysisErrorSeverity.values
|
||||
.asNameMap()[severityName];
|
||||
assert(
|
||||
severity != null,
|
||||
'Invalid configured severity: ${configuredSeverity.name}',
|
||||
);
|
||||
return severity;
|
||||
}
|
||||
|
||||
// Fall back to the declared severity of [code].
|
||||
var severityName = code.severity.name.toUpperCase();
|
||||
var severity =
|
||||
protocol.AnalysisErrorSeverity.values.asNameMap()[code.severity.name];
|
||||
var severity = protocol.AnalysisErrorSeverity.values
|
||||
.asNameMap()[code.severity.name];
|
||||
assert(severity != null, 'Invalid severity: $severityName');
|
||||
return severity;
|
||||
}
|
||||
@@ -467,13 +493,15 @@ class PluginServer {
|
||||
switch (request.method) {
|
||||
case protocol.ANALYSIS_REQUEST_GET_NAVIGATION:
|
||||
case protocol.ANALYSIS_REQUEST_HANDLE_WATCH_EVENTS:
|
||||
var params =
|
||||
protocol.AnalysisHandleWatchEventsParams.fromRequest(request);
|
||||
var params = protocol.AnalysisHandleWatchEventsParams.fromRequest(
|
||||
request,
|
||||
);
|
||||
result = await _handleAnalysisWatchEvents(params);
|
||||
|
||||
case protocol.ANALYSIS_REQUEST_SET_CONTEXT_ROOTS:
|
||||
var params =
|
||||
protocol.AnalysisSetContextRootsParams.fromRequest(request);
|
||||
var params = protocol.AnalysisSetContextRootsParams.fromRequest(
|
||||
request,
|
||||
);
|
||||
result = await _handleAnalysisSetContextRoots(params);
|
||||
|
||||
case protocol.ANALYSIS_REQUEST_SET_PRIORITY_FILES:
|
||||
@@ -500,8 +528,9 @@ class PluginServer {
|
||||
result = null;
|
||||
|
||||
case protocol.PLUGIN_REQUEST_SHUTDOWN:
|
||||
_channel.sendResponse(protocol.PluginShutdownResult()
|
||||
.toResponse(request.id, requestTime));
|
||||
_channel.sendResponse(
|
||||
protocol.PluginShutdownResult().toResponse(request.id, requestTime),
|
||||
);
|
||||
_channel.close();
|
||||
return null;
|
||||
|
||||
@@ -510,8 +539,11 @@ class PluginServer {
|
||||
result = await handlePluginVersionCheck(params);
|
||||
}
|
||||
if (result == null) {
|
||||
return Response(request.id, requestTime,
|
||||
error: RequestErrorFactory.unknownRequest(request.method));
|
||||
return Response(
|
||||
request.id,
|
||||
requestTime,
|
||||
error: RequestErrorFactory.unknownRequest(request.method),
|
||||
);
|
||||
}
|
||||
return result.toResponse(request.id, requestTime);
|
||||
}
|
||||
@@ -526,18 +558,17 @@ class PluginServer {
|
||||
required AnalysisContext analysisContext,
|
||||
required List<String> paths,
|
||||
}) async {
|
||||
var analyzedPaths =
|
||||
paths.where(analysisContext.contextRoot.isAnalyzed).toSet();
|
||||
var analyzedPaths = paths
|
||||
.where(analysisContext.contextRoot.isAnalyzed)
|
||||
.toSet();
|
||||
|
||||
await _analyzeFiles(
|
||||
analysisContext: analysisContext,
|
||||
paths: analyzedPaths,
|
||||
);
|
||||
await _analyzeFiles(analysisContext: analysisContext, paths: analyzedPaths);
|
||||
}
|
||||
|
||||
/// Handles an 'analysis.setContextRoots' request.
|
||||
Future<protocol.AnalysisSetContextRootsResult> _handleAnalysisSetContextRoots(
|
||||
protocol.AnalysisSetContextRootsParams parameters) async {
|
||||
protocol.AnalysisSetContextRootsParams parameters,
|
||||
) async {
|
||||
var currentContextCollection = _contextCollection;
|
||||
if (currentContextCollection != null) {
|
||||
_contextCollection = null;
|
||||
@@ -554,7 +585,8 @@ class PluginServer {
|
||||
);
|
||||
_contextCollection = contextCollection;
|
||||
await _analyzeAllFilesInContextCollection(
|
||||
contextCollection: contextCollection);
|
||||
contextCollection: contextCollection,
|
||||
);
|
||||
return protocol.AnalysisSetContextRootsResult();
|
||||
}
|
||||
|
||||
@@ -562,7 +594,8 @@ class PluginServer {
|
||||
///
|
||||
/// Throws a [RequestFailure] if the request could not be handled.
|
||||
Future<protocol.AnalysisUpdateContentResult> _handleAnalysisUpdateContent(
|
||||
protocol.AnalysisUpdateContentParams parameters) async {
|
||||
protocol.AnalysisUpdateContentParams parameters,
|
||||
) async {
|
||||
var changedPaths = <String>{};
|
||||
var paths = parameters.files;
|
||||
paths.forEach((String path, Object overlay) {
|
||||
@@ -585,14 +618,18 @@ class PluginServer {
|
||||
// The server should only send a ChangeContentOverlay if there is
|
||||
// already an existing overlay for the source.
|
||||
throw RequestFailure(
|
||||
RequestErrorFactory.invalidOverlayChangeNoContent());
|
||||
RequestErrorFactory.invalidOverlayChangeNoContent(),
|
||||
);
|
||||
}
|
||||
try {
|
||||
newContent =
|
||||
protocol.SourceEdit.applySequence(oldContent, overlay.edits);
|
||||
newContent = protocol.SourceEdit.applySequence(
|
||||
oldContent,
|
||||
overlay.edits,
|
||||
);
|
||||
} on RangeError {
|
||||
throw RequestFailure(
|
||||
RequestErrorFactory.invalidOverlayChangeInvalidEdit());
|
||||
RequestErrorFactory.invalidOverlayChangeInvalidEdit(),
|
||||
);
|
||||
}
|
||||
} else if (overlay is protocol.RemoveContentOverlay) {
|
||||
newContent = null;
|
||||
@@ -616,7 +653,8 @@ class PluginServer {
|
||||
|
||||
/// Handles an 'analysis.handleWatchEvents' request.
|
||||
Future<protocol.AnalysisHandleWatchEventsResult> _handleAnalysisWatchEvents(
|
||||
protocol.AnalysisHandleWatchEventsParams parameters) async {
|
||||
protocol.AnalysisHandleWatchEventsParams parameters,
|
||||
) async {
|
||||
final addedPaths = parameters.events
|
||||
.where((e) => e.type == protocol.WatchEventType.ADD)
|
||||
.map((e) => e.path)
|
||||
@@ -640,14 +678,17 @@ class PluginServer {
|
||||
}
|
||||
|
||||
/// Handles added files, modified files, and removed files.
|
||||
Future<void> _handleContentChanged(
|
||||
{List<String> addedPaths = const [],
|
||||
List<String> modifiedPaths = const [],
|
||||
List<String> removedPaths = const []}) async {
|
||||
Future<void> _handleContentChanged({
|
||||
List<String> addedPaths = const [],
|
||||
List<String> modifiedPaths = const [],
|
||||
List<String> removedPaths = const [],
|
||||
}) async {
|
||||
if (_contextCollection case var contextCollection?) {
|
||||
_channel.sendNotification(
|
||||
protocol.PluginStatusParams(analysis: protocol.AnalysisStatus(true))
|
||||
.toNotification());
|
||||
protocol.PluginStatusParams(
|
||||
analysis: protocol.AnalysisStatus(true),
|
||||
).toNotification(),
|
||||
);
|
||||
await _forAnalysisContexts(contextCollection, (analysisContext) async {
|
||||
for (var path in modifiedPaths) {
|
||||
analysisContext.changeFile(path);
|
||||
@@ -660,11 +701,15 @@ class PluginServer {
|
||||
...addedPaths,
|
||||
];
|
||||
await _handleAffectedFiles(
|
||||
analysisContext: analysisContext, paths: affected);
|
||||
analysisContext: analysisContext,
|
||||
paths: affected,
|
||||
);
|
||||
});
|
||||
_channel.sendNotification(
|
||||
protocol.PluginStatusParams(analysis: protocol.AnalysisStatus(false))
|
||||
.toNotification());
|
||||
protocol.PluginStatusParams(
|
||||
analysis: protocol.AnalysisStatus(false),
|
||||
).toNotification(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -677,10 +722,15 @@ class PluginServer {
|
||||
} on RequestFailure catch (exception) {
|
||||
response = Response(id, requestTime, error: exception.error);
|
||||
} catch (exception, stackTrace) {
|
||||
response = Response(id, requestTime,
|
||||
error: protocol.RequestError(
|
||||
protocol.RequestErrorCode.PLUGIN_ERROR, exception.toString(),
|
||||
stackTrace: stackTrace.toString()));
|
||||
response = Response(
|
||||
id,
|
||||
requestTime,
|
||||
error: protocol.RequestError(
|
||||
protocol.RequestErrorCode.PLUGIN_ERROR,
|
||||
exception.toString(),
|
||||
stackTrace: stackTrace.toString(),
|
||||
),
|
||||
);
|
||||
}
|
||||
if (response != null) {
|
||||
_channel.sendResponse(response);
|
||||
@@ -688,25 +738,30 @@ class PluginServer {
|
||||
}
|
||||
|
||||
Future<void> _handleRequestZoned(Request request) async {
|
||||
await runZonedGuarded(
|
||||
() => _handleRequest(request),
|
||||
(error, stackTrace) {
|
||||
_channel.sendNotification(protocol.PluginErrorParams(
|
||||
false /* isFatal */, error.toString(), stackTrace.toString())
|
||||
.toNotification());
|
||||
},
|
||||
);
|
||||
await runZonedGuarded(() => _handleRequest(request), (error, stackTrace) {
|
||||
_channel.sendNotification(
|
||||
protocol.PluginErrorParams(
|
||||
false /* isFatal */,
|
||||
error.toString(),
|
||||
stackTrace.toString(),
|
||||
).toNotification(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
bool _isPriorityAnalysisContext(AnalysisContext analysisContext) =>
|
||||
_priorityPaths.any(analysisContext.contextRoot.isAnalyzed);
|
||||
|
||||
static protocol.Location _locationFor(
|
||||
CompilationUnit unit, String path, Diagnostic diagnostic) {
|
||||
CompilationUnit unit,
|
||||
String path,
|
||||
Diagnostic diagnostic,
|
||||
) {
|
||||
var lineInfo = unit.lineInfo;
|
||||
var startLocation = lineInfo.getLocation(diagnostic.offset);
|
||||
var endLocation =
|
||||
lineInfo.getLocation(diagnostic.offset + diagnostic.length);
|
||||
var endLocation = lineInfo.getLocation(
|
||||
diagnostic.offset + diagnostic.length,
|
||||
);
|
||||
return protocol.Location(
|
||||
path,
|
||||
diagnostic.offset,
|
||||
|
||||
@@ -16,7 +16,7 @@ extension StringExtension on String {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (indexOfNewline > 0 && codeUnitAt(indexOfNewline - 1) == 13 /* \r */) {
|
||||
if (indexOfNewline > 0 && codeUnitAt(indexOfNewline - 1) == 13 /* \r */ ) {
|
||||
return '\r\n';
|
||||
}
|
||||
return '\n';
|
||||
|
||||
@@ -22,8 +22,11 @@ class Selection {
|
||||
/// Initialize a newly created selection to include the characters starting at
|
||||
/// the [offset] and including [length] characters, all of which fall within
|
||||
/// the [coveringNode].
|
||||
Selection(
|
||||
{required this.offset, required this.length, required this.coveringNode});
|
||||
Selection({
|
||||
required this.offset,
|
||||
required this.length,
|
||||
required this.coveringNode,
|
||||
});
|
||||
|
||||
bool isCoveredByNode(AstNode node) {
|
||||
return node.offset <= offset && offset + length <= node.end;
|
||||
@@ -297,19 +300,22 @@ class _ChildrenFinder extends SimpleAstVisitor<void> {
|
||||
|
||||
@override
|
||||
void visitRecordTypeAnnotationNamedField(
|
||||
RecordTypeAnnotationNamedField node) {
|
||||
RecordTypeAnnotationNamedField node,
|
||||
) {
|
||||
_fromList(node.metadata);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitRecordTypeAnnotationNamedFields(
|
||||
RecordTypeAnnotationNamedFields node) {
|
||||
RecordTypeAnnotationNamedFields node,
|
||||
) {
|
||||
_fromList(node.fields);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitRecordTypeAnnotationPositionalField(
|
||||
RecordTypeAnnotationPositionalField node) {
|
||||
RecordTypeAnnotationPositionalField node,
|
||||
) {
|
||||
_fromList(node.metadata);
|
||||
}
|
||||
|
||||
@@ -431,6 +437,9 @@ extension CompilationUnitExtension on CompilationUnit {
|
||||
return null;
|
||||
}
|
||||
return Selection(
|
||||
offset: offset, length: length, coveringNode: coveringNode);
|
||||
offset: offset,
|
||||
length: length,
|
||||
coveringNode: coveringNode,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ version: 0.2.3-dev
|
||||
repository: https://github.com/dart-lang/sdk/tree/main/pkg/analysis_server_plugin
|
||||
|
||||
environment:
|
||||
sdk: ^3.5.0
|
||||
sdk: ^3.9.0
|
||||
|
||||
resolution: workspace
|
||||
|
||||
|
||||
@@ -199,10 +199,7 @@ var j = 1;
|
||||
}
|
||||
|
||||
Future<void> test_replaceSourceIndent_noLeading_nonEmpty_lf() async {
|
||||
await assertReplacedIndentation(
|
||||
' a\n b\n c',
|
||||
' a\n b\n c',
|
||||
);
|
||||
await assertReplacedIndentation(' a\n b\n c', ' a\n b\n c');
|
||||
}
|
||||
|
||||
Future<void> test_replaceSourceIndent_noTrailing_crlf() async {
|
||||
@@ -213,10 +210,7 @@ var j = 1;
|
||||
}
|
||||
|
||||
Future<void> test_replaceSourceIndent_noTrailing_lf() async {
|
||||
await assertReplacedIndentation(
|
||||
' a\n b\n c',
|
||||
' a\n b\n c',
|
||||
);
|
||||
await assertReplacedIndentation(' a\n b\n c', ' a\n b\n c');
|
||||
}
|
||||
|
||||
Future<void> test_replaceSourceIndent_trailing_added_crlf() async {
|
||||
|
||||
@@ -77,15 +77,18 @@ class SingleUnitTest with ResourceProviderMixin {
|
||||
testCode = result.content;
|
||||
var testUnit = result.unit;
|
||||
|
||||
expect(result.diagnostics.where((d) {
|
||||
return d.diagnosticCode != WarningCode.deadCode &&
|
||||
d.diagnosticCode != WarningCode.unusedCatchClause &&
|
||||
d.diagnosticCode != WarningCode.unusedCatchStack &&
|
||||
d.diagnosticCode != WarningCode.unusedElement &&
|
||||
d.diagnosticCode != WarningCode.unusedField &&
|
||||
d.diagnosticCode != WarningCode.unusedImport &&
|
||||
d.diagnosticCode != WarningCode.unusedLocalVariable;
|
||||
}), isEmpty);
|
||||
expect(
|
||||
result.diagnostics.where((d) {
|
||||
return d.diagnosticCode != WarningCode.deadCode &&
|
||||
d.diagnosticCode != WarningCode.unusedCatchClause &&
|
||||
d.diagnosticCode != WarningCode.unusedCatchStack &&
|
||||
d.diagnosticCode != WarningCode.unusedElement &&
|
||||
d.diagnosticCode != WarningCode.unusedField &&
|
||||
d.diagnosticCode != WarningCode.unusedImport &&
|
||||
d.diagnosticCode != WarningCode.unusedLocalVariable;
|
||||
}),
|
||||
isEmpty,
|
||||
);
|
||||
|
||||
findNode = FindNode(testCode, testUnit);
|
||||
return result;
|
||||
|
||||
@@ -19,7 +19,9 @@ class NoBoolsRule extends AnalysisRule {
|
||||
|
||||
@override
|
||||
void registerNodeProcessors(
|
||||
RuleVisitorRegistry registry, RuleContext context) {
|
||||
RuleVisitorRegistry registry,
|
||||
RuleContext context,
|
||||
) {
|
||||
var visitor = _NoBoolsVisitor(this);
|
||||
registry.addBooleanLiteral(this, visitor);
|
||||
}
|
||||
@@ -29,14 +31,16 @@ class NoDoublesRule extends AnalysisRule {
|
||||
static const LintCode code = LintCode('no_doubles', 'No doubles message');
|
||||
|
||||
NoDoublesRule()
|
||||
: super(name: 'no_doubles', description: 'No doubles message');
|
||||
: super(name: 'no_doubles', description: 'No doubles message');
|
||||
|
||||
@override
|
||||
DiagnosticCode get diagnosticCode => code;
|
||||
|
||||
@override
|
||||
void registerNodeProcessors(
|
||||
RuleVisitorRegistry registry, RuleContext context) {
|
||||
RuleVisitorRegistry registry,
|
||||
RuleContext context,
|
||||
) {
|
||||
var visitor = _NoDoublesVisitor(this);
|
||||
registry.addDoubleLiteral(this, visitor);
|
||||
}
|
||||
@@ -50,14 +54,16 @@ class NoDoublesWarningRule extends AnalysisRule {
|
||||
);
|
||||
|
||||
NoDoublesWarningRule()
|
||||
: super(name: 'no_doubles_warning', description: 'No doubles message');
|
||||
: super(name: 'no_doubles_warning', description: 'No doubles message');
|
||||
|
||||
@override
|
||||
DiagnosticCode get diagnosticCode => code;
|
||||
|
||||
@override
|
||||
void registerNodeProcessors(
|
||||
RuleVisitorRegistry registry, RuleContext context) {
|
||||
RuleVisitorRegistry registry,
|
||||
RuleContext context,
|
||||
) {
|
||||
var visitor = _NoDoublesVisitor(this);
|
||||
registry.addDoubleLiteral(this, visitor);
|
||||
}
|
||||
|
||||
@@ -56,22 +56,27 @@ plugins:
|
||||
newFile(filePath, 'bool b = false;');
|
||||
var contextRoot = protocol.ContextRoot(packagePath, []);
|
||||
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
|
||||
// Create a broadcast Stream of notifications, so that we can have multiple
|
||||
// StreamQueues listening.
|
||||
var notifications = channel.notifications.asBroadcastStream();
|
||||
var analysisErrorsParamsQueue = StreamQueue(notifications
|
||||
.where((n) => n.event == protocol.ANALYSIS_NOTIFICATION_ERRORS)
|
||||
.map((n) => protocol.AnalysisErrorsParams.fromNotification(n))
|
||||
.where((p) => p.file == filePath));
|
||||
var analysisErrorsParamsQueue = StreamQueue(
|
||||
notifications
|
||||
.where((n) => n.event == protocol.ANALYSIS_NOTIFICATION_ERRORS)
|
||||
.map((n) => protocol.AnalysisErrorsParams.fromNotification(n))
|
||||
.where((p) => p.file == filePath),
|
||||
);
|
||||
var analysisErrorsParams = await analysisErrorsParamsQueue.next;
|
||||
expect(analysisErrorsParams.errors, isEmpty);
|
||||
|
||||
var pluginErrorParamsQueue = StreamQueue(notifications
|
||||
.where((n) => n.event == protocol.PLUGIN_NOTIFICATION_ERROR)
|
||||
.map((n) => protocol.PluginErrorParams.fromNotification(n)));
|
||||
var pluginErrorParamsQueue = StreamQueue(
|
||||
notifications
|
||||
.where((n) => n.event == protocol.PLUGIN_NOTIFICATION_ERROR)
|
||||
.map((n) => protocol.PluginErrorParams.fromNotification(n)),
|
||||
);
|
||||
var pluginErrorParams = await pluginErrorParamsQueue.next;
|
||||
expect(pluginErrorParams.isFatal, false);
|
||||
expect(pluginErrorParams.message, 'Bad state: A message.');
|
||||
@@ -90,8 +95,9 @@ plugins:
|
||||
newFile(filePath, 'bool b = false;');
|
||||
var contextRoot = protocol.ContextRoot(packagePath, []);
|
||||
|
||||
var response = await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
var response = await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
|
||||
expect(
|
||||
response.error,
|
||||
@@ -112,24 +118,30 @@ plugins:
|
||||
newFile(filePath, 'bool b = false;');
|
||||
var contextRoot = protocol.ContextRoot(packagePath, []);
|
||||
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel
|
||||
.sendRequest(protocol.EditGetFixesParams(filePath, 'bool b = '.length));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
await channel.sendRequest(
|
||||
protocol.EditGetFixesParams(filePath, 'bool b = '.length),
|
||||
);
|
||||
|
||||
// Create a broadcast Stream of notifications, so that we can have multiple
|
||||
// StreamQueues listening.
|
||||
var notifications = channel.notifications.asBroadcastStream();
|
||||
var analysisErrorsParamsQueue = StreamQueue(notifications
|
||||
.where((n) => n.event == protocol.ANALYSIS_NOTIFICATION_ERRORS)
|
||||
.map((n) => protocol.AnalysisErrorsParams.fromNotification(n))
|
||||
.where((p) => p.file == filePath));
|
||||
var analysisErrorsParamsQueue = StreamQueue(
|
||||
notifications
|
||||
.where((n) => n.event == protocol.ANALYSIS_NOTIFICATION_ERRORS)
|
||||
.map((n) => protocol.AnalysisErrorsParams.fromNotification(n))
|
||||
.where((p) => p.file == filePath),
|
||||
);
|
||||
var analysisErrorsParams = await analysisErrorsParamsQueue.next;
|
||||
expect(analysisErrorsParams.errors.single, isNotNull);
|
||||
|
||||
var pluginErrorParamsQueue = StreamQueue(notifications
|
||||
.where((n) => n.event == protocol.PLUGIN_NOTIFICATION_ERROR)
|
||||
.map((n) => protocol.PluginErrorParams.fromNotification(n)));
|
||||
var pluginErrorParamsQueue = StreamQueue(
|
||||
notifications
|
||||
.where((n) => n.event == protocol.PLUGIN_NOTIFICATION_ERROR)
|
||||
.map((n) => protocol.PluginErrorParams.fromNotification(n)),
|
||||
);
|
||||
var pluginErrorParams = await pluginErrorParamsQueue.next;
|
||||
expect(pluginErrorParams.isFatal, false);
|
||||
expect(pluginErrorParams.message, 'Bad state: A message.');
|
||||
@@ -148,11 +160,13 @@ plugins:
|
||||
newFile(filePath, 'bool b = false;');
|
||||
var contextRoot = protocol.ContextRoot(packagePath, []);
|
||||
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
|
||||
var response = await channel
|
||||
.sendRequest(protocol.EditGetFixesParams(filePath, 'bool b = '.length));
|
||||
var response = await channel.sendRequest(
|
||||
protocol.EditGetFixesParams(filePath, 'bool b = '.length),
|
||||
);
|
||||
expect(
|
||||
response.error,
|
||||
isA<protocol.RequestError>()
|
||||
@@ -264,14 +278,16 @@ class _ThrowsAsyncErrorRule extends AnalysisRule {
|
||||
static const LintCode code = LintCode('no_bools', 'No bools message');
|
||||
|
||||
_ThrowsAsyncErrorRule()
|
||||
: super(name: 'no_bools', description: 'No bools desc');
|
||||
: super(name: 'no_bools', description: 'No bools desc');
|
||||
|
||||
@override
|
||||
DiagnosticCode get diagnosticCode => code;
|
||||
|
||||
@override
|
||||
void registerNodeProcessors(
|
||||
RuleVisitorRegistry registry, RuleContext context) {
|
||||
RuleVisitorRegistry registry,
|
||||
RuleContext context,
|
||||
) {
|
||||
var visitor = _ThrowsAsyncErrorVisitor(this);
|
||||
registry.addBooleanLiteral(this, visitor);
|
||||
}
|
||||
@@ -311,14 +327,16 @@ class _ThrowsSyncErrorRule extends AnalysisRule {
|
||||
static const LintCode code = LintCode('no_bools', 'No bools message');
|
||||
|
||||
_ThrowsSyncErrorRule()
|
||||
: super(name: 'no_bools', description: 'No bools desc');
|
||||
: super(name: 'no_bools', description: 'No bools desc');
|
||||
|
||||
@override
|
||||
DiagnosticCode get diagnosticCode => code;
|
||||
|
||||
@override
|
||||
void registerNodeProcessors(
|
||||
RuleVisitorRegistry registry, RuleContext context) {
|
||||
RuleVisitorRegistry registry,
|
||||
RuleContext context,
|
||||
) {
|
||||
var visitor = _ThrowsSyncErrorVisitor(this);
|
||||
registry.addBooleanLiteral(this, visitor);
|
||||
}
|
||||
|
||||
@@ -37,10 +37,12 @@ class PluginServerTest extends PluginServerTestBase {
|
||||
String get packagePath => convertPath('/package1');
|
||||
|
||||
StreamQueue<protocol.AnalysisErrorsParams> get _analysisErrorsParams {
|
||||
return StreamQueue(channel.notifications
|
||||
.where((n) => n.event == protocol.ANALYSIS_NOTIFICATION_ERRORS)
|
||||
.map((n) => protocol.AnalysisErrorsParams.fromNotification(n))
|
||||
.where((p) => p.file == filePath));
|
||||
return StreamQueue(
|
||||
channel.notifications
|
||||
.where((n) => n.event == protocol.ANALYSIS_NOTIFICATION_ERRORS)
|
||||
.map((n) => protocol.AnalysisErrorsParams.fromNotification(n))
|
||||
.where((p) => p.file == filePath),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -48,7 +50,9 @@ class PluginServerTest extends PluginServerTestBase {
|
||||
await super.setUp();
|
||||
|
||||
pluginServer = PluginServer(
|
||||
resourceProvider: resourceProvider, plugins: [_NoLiteralsPlugin()]);
|
||||
resourceProvider: resourceProvider,
|
||||
plugins: [_NoLiteralsPlugin()],
|
||||
);
|
||||
await startPlugin();
|
||||
}
|
||||
|
||||
@@ -58,8 +62,9 @@ class PluginServerTest extends PluginServerTestBase {
|
||||
// ignore: no_literals/no_bools
|
||||
bool b = false;
|
||||
''');
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
var paramsQueue = _analysisErrorsParams;
|
||||
var params = await paramsQueue.next;
|
||||
expect(params.errors, isEmpty);
|
||||
@@ -72,8 +77,9 @@ bool b = false;
|
||||
|
||||
// ignore_for_file: no_literals/no_bools
|
||||
''');
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
var paramsQueue = _analysisErrorsParams;
|
||||
var params = await paramsQueue.next;
|
||||
expect(params.errors, isEmpty);
|
||||
@@ -82,8 +88,9 @@ bool b = false;
|
||||
Future<void> test_handleAnalysisSetContextRoots() async {
|
||||
writeAnalysisOptionsWithPlugin();
|
||||
newFile(filePath, 'bool b = false;');
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
var paramsQueue = _analysisErrorsParams;
|
||||
var params = await paramsQueue.next;
|
||||
expect(params.errors, hasLength(1));
|
||||
@@ -93,12 +100,16 @@ bool b = false;
|
||||
Future<void> test_handleEditGetAssists() async {
|
||||
writeAnalysisOptionsWithPlugin();
|
||||
newFile(filePath, 'bool b = false;');
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
|
||||
var result = await pluginServer.handleEditGetAssists(
|
||||
protocol.EditGetAssistsParams(
|
||||
filePath, 'bool b = f'.length, 3 /* length */),
|
||||
filePath,
|
||||
'bool b = f'.length,
|
||||
3 /* length */,
|
||||
),
|
||||
);
|
||||
var assists = result.assists;
|
||||
expect(assists, hasLength(1));
|
||||
@@ -110,11 +121,13 @@ bool b = false;
|
||||
writeAnalysisOptionsWithPlugin();
|
||||
newFile(filePath, 'bool b = false;');
|
||||
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
|
||||
var response = await channel.sendRequest(
|
||||
protocol.EditGetAssistsParams(filePath, 'bool b = '.length, 1));
|
||||
protocol.EditGetAssistsParams(filePath, 'bool b = '.length, 1),
|
||||
);
|
||||
var result = protocol.EditGetAssistsResult.fromResponse(response);
|
||||
expect(result.assists, hasLength(1));
|
||||
}
|
||||
@@ -122,11 +135,13 @@ bool b = false;
|
||||
Future<void> test_handleEditGetFixes() async {
|
||||
writeAnalysisOptionsWithPlugin();
|
||||
newFile(filePath, 'bool b = false;');
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
|
||||
var result = await pluginServer.handleEditGetFixes(
|
||||
protocol.EditGetFixesParams(filePath, 'bool b = '.length));
|
||||
protocol.EditGetFixesParams(filePath, 'bool b = '.length),
|
||||
);
|
||||
var fixes = result.fixes.single;
|
||||
// The WrapInQuotes fix plus three "ignore diagnostic" fixes.
|
||||
expect(fixes.fixes, hasLength(4));
|
||||
@@ -136,11 +151,13 @@ bool b = false;
|
||||
writeAnalysisOptionsWithPlugin();
|
||||
newFile(filePath, 'bool b = false;');
|
||||
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
|
||||
var response = await channel
|
||||
.sendRequest(protocol.EditGetFixesParams(filePath, 'bool b = '.length));
|
||||
var response = await channel.sendRequest(
|
||||
protocol.EditGetFixesParams(filePath, 'bool b = '.length),
|
||||
);
|
||||
var result = protocol.EditGetFixesResult.fromResponse(response);
|
||||
expect(result.fixes.first.fixes, hasLength(4));
|
||||
}
|
||||
@@ -148,8 +165,9 @@ bool b = false;
|
||||
Future<void> test_lintCodesCanHaveCustomSeverity() async {
|
||||
writeAnalysisOptionsWithPlugin({'no_doubles_warning': 'enable'});
|
||||
newFile(filePath, 'double x = 3.14;');
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
var paramsQueue = _analysisErrorsParams;
|
||||
var params = await paramsQueue.next;
|
||||
expect(params.errors, hasLength(1));
|
||||
@@ -163,8 +181,9 @@ bool b = false;
|
||||
Future<void> test_lintCodesCanHaveConfigurableSeverity() async {
|
||||
writeAnalysisOptionsWithPlugin({'no_doubles_warning': 'error'});
|
||||
newFile(filePath, 'double x = 3.14;');
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
var paramsQueue = _analysisErrorsParams;
|
||||
var params = await paramsQueue.next;
|
||||
expect(params.errors, hasLength(1));
|
||||
@@ -178,8 +197,9 @@ bool b = false;
|
||||
Future<void> test_lintRulesAreDisabledByDefault() async {
|
||||
writeAnalysisOptionsWithPlugin();
|
||||
newFile(filePath, 'double x = 3.14;');
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
var paramsQueue = _analysisErrorsParams;
|
||||
var params = await paramsQueue.next;
|
||||
expect(params.errors, isEmpty);
|
||||
@@ -188,8 +208,9 @@ bool b = false;
|
||||
Future<void> test_lintRulesCanBeEnabled() async {
|
||||
writeAnalysisOptionsWithPlugin({'no_doubles': 'enable'});
|
||||
newFile(filePath, 'double x = 3.14;');
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
var paramsQueue = _analysisErrorsParams;
|
||||
var params = await paramsQueue.next;
|
||||
expect(params.errors, hasLength(1));
|
||||
@@ -200,12 +221,14 @@ bool b = false;
|
||||
writeAnalysisOptionsWithPlugin();
|
||||
newFile(filePath, 'bool b = false;');
|
||||
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
|
||||
// This request is unsupported.
|
||||
var response = await channel.sendRequest(
|
||||
protocol.CompletionGetSuggestionsParams(filePath, 0 /* offset */));
|
||||
protocol.CompletionGetSuggestionsParams(filePath, 0 /* offset */),
|
||||
);
|
||||
|
||||
expect(response.error?.code, RequestErrorCode.UNKNOWN_REQUEST);
|
||||
}
|
||||
@@ -213,15 +236,19 @@ bool b = false;
|
||||
Future<void> test_updateContent_addOverlay() async {
|
||||
writeAnalysisOptionsWithPlugin();
|
||||
newFile(filePath, 'int b = 7;');
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
|
||||
var paramsQueue = _analysisErrorsParams;
|
||||
var params = await paramsQueue.next;
|
||||
expect(params.errors, isEmpty);
|
||||
|
||||
await channel.sendRequest(protocol.AnalysisUpdateContentParams(
|
||||
{filePath: protocol.AddContentOverlay('bool b = false;')}));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisUpdateContentParams({
|
||||
filePath: protocol.AddContentOverlay('bool b = false;'),
|
||||
}),
|
||||
);
|
||||
|
||||
params = await paramsQueue.next;
|
||||
expect(params.errors, hasLength(1));
|
||||
@@ -231,23 +258,30 @@ bool b = false;
|
||||
Future<void> test_updateContent_changeOverlay() async {
|
||||
writeAnalysisOptionsWithPlugin();
|
||||
newFile(filePath, 'int b = 7;');
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
|
||||
var paramsQueue = _analysisErrorsParams;
|
||||
var params = await paramsQueue.next;
|
||||
expect(params.errors, isEmpty);
|
||||
|
||||
await channel.sendRequest(protocol.AnalysisUpdateContentParams(
|
||||
{filePath: protocol.AddContentOverlay('int b = 0;')}));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisUpdateContentParams({
|
||||
filePath: protocol.AddContentOverlay('int b = 0;'),
|
||||
}),
|
||||
);
|
||||
|
||||
params = await paramsQueue.next;
|
||||
expect(params.errors, isEmpty);
|
||||
|
||||
await channel.sendRequest(protocol.AnalysisUpdateContentParams({
|
||||
filePath: protocol.ChangeContentOverlay(
|
||||
[protocol.SourceEdit(0, 9, 'bool b = false')])
|
||||
}));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisUpdateContentParams({
|
||||
filePath: protocol.ChangeContentOverlay([
|
||||
protocol.SourceEdit(0, 9, 'bool b = false'),
|
||||
]),
|
||||
}),
|
||||
);
|
||||
|
||||
params = await paramsQueue.next;
|
||||
expect(params.errors, hasLength(1));
|
||||
@@ -257,22 +291,29 @@ bool b = false;
|
||||
Future<void> test_updateContent_removeOverlay() async {
|
||||
writeAnalysisOptionsWithPlugin();
|
||||
newFile(filePath, 'bool b = false;');
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
|
||||
var paramsQueue = _analysisErrorsParams;
|
||||
var params = await paramsQueue.next;
|
||||
expect(params.errors, hasLength(1));
|
||||
_expectAnalysisError(params.errors.single, message: 'No bools message');
|
||||
|
||||
await channel.sendRequest(protocol.AnalysisUpdateContentParams(
|
||||
{filePath: protocol.AddContentOverlay('int b = 7;')}));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisUpdateContentParams({
|
||||
filePath: protocol.AddContentOverlay('int b = 7;'),
|
||||
}),
|
||||
);
|
||||
|
||||
params = await paramsQueue.next;
|
||||
expect(params.errors, isEmpty);
|
||||
|
||||
await channel.sendRequest(protocol.AnalysisUpdateContentParams(
|
||||
{filePath: protocol.RemoveContentOverlay()}));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisUpdateContentParams({
|
||||
filePath: protocol.RemoveContentOverlay(),
|
||||
}),
|
||||
);
|
||||
|
||||
params = await paramsQueue.next;
|
||||
expect(params.errors, hasLength(1));
|
||||
@@ -282,8 +323,9 @@ bool b = false;
|
||||
Future<void> test_warningRulesAreEnabledByDefault() async {
|
||||
writeAnalysisOptionsWithPlugin();
|
||||
newFile(filePath, 'bool b = false;');
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
var paramsQueue = _analysisErrorsParams;
|
||||
var params = await paramsQueue.next;
|
||||
expect(params.errors, hasLength(1));
|
||||
@@ -293,8 +335,9 @@ bool b = false;
|
||||
Future<void> test_warningRulesCanBeDisabled() async {
|
||||
writeAnalysisOptionsWithPlugin({'no_bools': 'disable'});
|
||||
newFile(filePath, 'bool b = false;');
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
var paramsQueue = _analysisErrorsParams;
|
||||
var params = await paramsQueue.next;
|
||||
expect(params.errors, isEmpty);
|
||||
@@ -302,15 +345,19 @@ bool b = false;
|
||||
|
||||
Future<void> test_watchEvent_add() async {
|
||||
writeAnalysisOptionsWithPlugin();
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
|
||||
var paramsQueue = _analysisErrorsParams;
|
||||
|
||||
newFile(filePath, 'bool b = false;');
|
||||
|
||||
await channel.sendRequest(protocol.AnalysisHandleWatchEventsParams(
|
||||
[WatchEvent(WatchEventType.ADD, filePath)]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisHandleWatchEventsParams([
|
||||
WatchEvent(WatchEventType.ADD, filePath),
|
||||
]),
|
||||
);
|
||||
|
||||
var params = await paramsQueue.next;
|
||||
expect(params.errors, hasLength(1));
|
||||
@@ -320,8 +367,9 @@ bool b = false;
|
||||
Future<void> test_watchEvent_modify() async {
|
||||
writeAnalysisOptionsWithPlugin();
|
||||
newFile(filePath, 'int b = 7;');
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
|
||||
var paramsQueue = _analysisErrorsParams;
|
||||
var params = await paramsQueue.next;
|
||||
@@ -329,8 +377,11 @@ bool b = false;
|
||||
|
||||
newFile(filePath, 'bool b = false;');
|
||||
|
||||
await channel.sendRequest(protocol.AnalysisHandleWatchEventsParams(
|
||||
[WatchEvent(WatchEventType.MODIFY, filePath)]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisHandleWatchEventsParams([
|
||||
WatchEvent(WatchEventType.MODIFY, filePath),
|
||||
]),
|
||||
);
|
||||
|
||||
params = await paramsQueue.next;
|
||||
expect(params.errors, hasLength(1));
|
||||
@@ -340,8 +391,9 @@ bool b = false;
|
||||
Future<void> test_watchEvent_remove() async {
|
||||
writeAnalysisOptionsWithPlugin();
|
||||
newFile(filePath, 'int b = 7;');
|
||||
await channel
|
||||
.sendRequest(protocol.AnalysisSetContextRootsParams([contextRoot]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisSetContextRootsParams([contextRoot]),
|
||||
);
|
||||
|
||||
var paramsQueue = _analysisErrorsParams;
|
||||
var params = await paramsQueue.next;
|
||||
@@ -349,15 +401,19 @@ bool b = false;
|
||||
|
||||
deleteFile(filePath);
|
||||
|
||||
await channel.sendRequest(protocol.AnalysisHandleWatchEventsParams(
|
||||
[WatchEvent(WatchEventType.REMOVE, filePath)]));
|
||||
await channel.sendRequest(
|
||||
protocol.AnalysisHandleWatchEventsParams([
|
||||
WatchEvent(WatchEventType.REMOVE, filePath),
|
||||
]),
|
||||
);
|
||||
|
||||
params = await paramsQueue.next;
|
||||
expect(params.errors, isEmpty);
|
||||
}
|
||||
|
||||
void writeAnalysisOptionsWithPlugin(
|
||||
[Map<String, String> diagnosticConfiguration = const {}]) {
|
||||
void writeAnalysisOptionsWithPlugin([
|
||||
Map<String, String> diagnosticConfiguration = const {},
|
||||
]) {
|
||||
var buffer = StringBuffer('''
|
||||
plugins:
|
||||
no_literals:
|
||||
@@ -382,15 +438,21 @@ plugins:
|
||||
isA<protocol.AnalysisError>()
|
||||
.having((e) => e.severity, 'severity', severity)
|
||||
.having(
|
||||
(e) => e.type, 'type', protocol.AnalysisErrorType.STATIC_WARNING)
|
||||
(e) => e.type,
|
||||
'type',
|
||||
protocol.AnalysisErrorType.STATIC_WARNING,
|
||||
)
|
||||
.having((e) => e.message, 'message', message),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _InvertBoolean extends ResolvedCorrectionProducer {
|
||||
static const _invertBooleanKind =
|
||||
AssistKind('dart.fix.invertBooelan', 50, 'Invert Boolean value');
|
||||
static const _invertBooleanKind = AssistKind(
|
||||
'dart.fix.invertBooelan',
|
||||
50,
|
||||
'Invert Boolean value',
|
||||
);
|
||||
|
||||
_InvertBoolean({required super.context});
|
||||
|
||||
@@ -424,8 +486,11 @@ class _NoLiteralsPlugin extends Plugin {
|
||||
}
|
||||
|
||||
class _WrapInQuotes extends ResolvedCorrectionProducer {
|
||||
static const _wrapInQuotesKind =
|
||||
FixKind('dart.fix.wrapInQuotes', 50, 'Wrap in quotes');
|
||||
static const _wrapInQuotesKind = FixKind(
|
||||
'dart.fix.wrapInQuotes',
|
||||
50,
|
||||
'Wrap in quotes',
|
||||
);
|
||||
|
||||
_WrapInQuotes({required super.context});
|
||||
|
||||
|
||||
@@ -34,8 +34,12 @@ class FakeChannel implements PluginCommunicationChannel {
|
||||
void close() {}
|
||||
|
||||
@override
|
||||
void listen(void Function(protocol.Request request)? onRequest,
|
||||
{void Function()? onDone, Function? onError, Function? onNotification}) {
|
||||
void listen(
|
||||
void Function(protocol.Request request)? onRequest, {
|
||||
void Function()? onDone,
|
||||
Function? onError,
|
||||
Function? onNotification,
|
||||
}) {
|
||||
_onRequest = onRequest;
|
||||
}
|
||||
|
||||
@@ -47,7 +51,8 @@ class FakeChannel implements PluginCommunicationChannel {
|
||||
Future<protocol.Response> sendRequest(protocol.RequestParams params) {
|
||||
if (_onRequest == null) {
|
||||
fail(
|
||||
'_onReuest is null! `listen` has not yet been called on this channel.');
|
||||
'_onReuest is null! `listen` has not yet been called on this channel.',
|
||||
);
|
||||
}
|
||||
var id = (_idCounter++).toString();
|
||||
var request = params.toRequest(id);
|
||||
@@ -84,7 +89,10 @@ class PluginServerTestBase with ResourceProviderMixin {
|
||||
|
||||
await pluginServer.handlePluginVersionCheck(
|
||||
protocol.PluginVersionCheckParams(
|
||||
byteStoreRoot.path, sdkRoot.path, '0.0.1'),
|
||||
byteStoreRoot.path,
|
||||
sdkRoot.path,
|
||||
'0.0.1',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,5 +14,6 @@ Future<void> main() async {
|
||||
}
|
||||
|
||||
/// A list of all targets generated by this code generator.
|
||||
final List<GeneratedContent> allTargets =
|
||||
allTargetsForPackage('analysis_server_plugin');
|
||||
final List<GeneratedContent> allTargets = allTargetsForPackage(
|
||||
'analysis_server_plugin',
|
||||
);
|
||||
|
||||
@@ -14,7 +14,12 @@ import 'generate.dart';
|
||||
Future<void> main() async {
|
||||
await allTargets.check(
|
||||
pkg_root.packageRoot,
|
||||
join(pkg_root.packageRoot, 'analysis_server_plugin', 'tool', 'api',
|
||||
'generate.dart'),
|
||||
join(
|
||||
pkg_root.packageRoot,
|
||||
'analysis_server_plugin',
|
||||
'tool',
|
||||
'api',
|
||||
'generate.dart',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user