Version 2.18.0-264.0.dev
Merge commit '7b7a4665783f8857024cd6e80850ed8931973d9c' into 'dev'
diff --git a/DEPS b/DEPS
index 74fde4b..e9818b9 100644
--- a/DEPS
+++ b/DEPS
@@ -81,7 +81,7 @@
"args_rev": "73e8d3b55cbedc9765f8e266f3422d8914f8e62a",
"async_rev": "f3ed5f690e2ec9dbe1bfc5184705575b4f6480e5",
"bazel_worker_rev": "9710de6c9c70b1b583183db9d9721ba64e5a16fe",
- "benchmark_harness_rev": "f4ed0fcac4c284580263f0c548664dd548c9cca3",
+ "benchmark_harness_rev": "4183c76739ed7a27c260ca9ebaab6e0f210d1a37",
"boolean_selector_rev": "1d3565e2651d16566bb556955b96ea75018cbd0c",
"boringssl_gen_rev": "ced85ef0a00bbca77ce5a91261a5f2ae61b1e62f",
"boringssl_rev": "87f316d7748268eb56f2dc147bd593254ae93198",
@@ -108,7 +108,7 @@
# For more details, see https://github.com/dart-lang/sdk/issues/30164.
"dart_style_rev": "d7b73536a8079331c888b7da539b80e6825270ea", # manually rev'd
- "dartdoc_rev": "61dea6b8307392ee6dfe8fd952716b07f5243b1d",
+ "dartdoc_rev": "bf7cf5112bf2742a8fe05a5ec61377dc07f27cf7",
"devtools_rev": "95d292626da26505b02417735f77e8922783b477",
"ffi_rev": "18b2b549d55009ff594600b04705ff6161681e07",
"file_rev": "0132eeedea2933513bf230513a766a8baeab0c4f",
@@ -135,7 +135,7 @@
"path_rev": "7a0ed40280345b1c11df4c700c71e590738f4257",
"ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
"pool_rev": "fa84ddd0e39f45bf3f09dcc5d6b9fbdda7820fef",
- "protobuf_rev": "585878516d90b973ba47e2ffa295814ccaa19d3d",
+ "protobuf_rev": "7b20134b5609a4d25a57c7396e91b93ba60888d5",
"pub_rev": "9bf4289d6fd5d6872a8929d6312bbd7098f3ea9c", # manually rev'd
"pub_semver_rev": "5c0b4bfd5ca57fe16f1319c581dc8c882e9b8cb2",
"root_certificates_rev": "692f6d6488af68e0121317a9c2c9eb393eb0ee50",
diff --git a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
index 1c684d6..ac255c9 100644
--- a/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
+++ b/pkg/analysis_server/lib/lsp_protocol/protocol_custom_generated.dart
@@ -143,6 +143,10 @@
);
static CompletionItemResolutionInfo fromJson(Map<String, Object?> json) {
+ if (DartNotImportedCompletionResolutionInfo.canParse(
+ json, nullLspJsonReporter)) {
+ return DartNotImportedCompletionResolutionInfo.fromJson(json);
+ }
if (DartSuggestionSetCompletionItemResolutionInfo.canParse(
json, nullLspJsonReporter)) {
return DartSuggestionSetCompletionItemResolutionInfo.fromJson(json);
@@ -229,6 +233,78 @@
String toString() => jsonEncoder.convert(toJson());
}
+class DartNotImportedCompletionResolutionInfo
+ implements CompletionItemResolutionInfo, ToJsonable {
+ static const jsonHandler = LspJsonHandler(
+ DartNotImportedCompletionResolutionInfo.canParse,
+ DartNotImportedCompletionResolutionInfo.fromJson,
+ );
+
+ DartNotImportedCompletionResolutionInfo({
+ required this.file,
+ required this.libraryUri,
+ });
+ static DartNotImportedCompletionResolutionInfo fromJson(
+ Map<String, Object?> json) {
+ final fileJson = json['file'];
+ final file = fileJson as String;
+ final libraryUriJson = json['libraryUri'];
+ final libraryUri = libraryUriJson as String;
+ return DartNotImportedCompletionResolutionInfo(
+ file: file,
+ libraryUri: libraryUri,
+ );
+ }
+
+ /// The file where the completion is being inserted.
+ ///
+ /// This is used to compute where to add the import.
+ final String file;
+
+ /// The URI to be imported if this completion is selected.
+ final String libraryUri;
+
+ @override
+ Map<String, Object?> toJson() {
+ var result = <String, Object?>{};
+ result['file'] = file;
+ result['libraryUri'] = libraryUri;
+ return result;
+ }
+
+ static bool canParse(Object? obj, LspJsonReporter reporter) {
+ if (obj is Map<String, Object?>) {
+ if (!_canParseString(obj, reporter, 'file',
+ allowsUndefined: false, allowsNull: false)) {
+ return false;
+ }
+ return _canParseString(obj, reporter, 'libraryUri',
+ allowsUndefined: false, allowsNull: false);
+ } else {
+ reporter.reportError(
+ 'must be of type DartNotImportedCompletionResolutionInfo');
+ return false;
+ }
+ }
+
+ @override
+ bool operator ==(Object other) {
+ return other is DartNotImportedCompletionResolutionInfo &&
+ other.runtimeType == DartNotImportedCompletionResolutionInfo &&
+ file == other.file &&
+ libraryUri == other.libraryUri;
+ }
+
+ @override
+ int get hashCode => Object.hash(
+ file,
+ libraryUri,
+ );
+
+ @override
+ String toString() => jsonEncoder.convert(toJson());
+}
+
class DartSuggestionSetCompletionItemResolutionInfo
implements CompletionItemResolutionInfo, ToJsonable {
static const jsonHandler = LspJsonHandler(
@@ -237,89 +313,39 @@
);
DartSuggestionSetCompletionItemResolutionInfo({
- required this.displayUri,
required this.file,
- required this.iLength,
required this.libId,
- required this.offset,
- required this.rLength,
- required this.rOffset,
});
static DartSuggestionSetCompletionItemResolutionInfo fromJson(
Map<String, Object?> json) {
- final displayUriJson = json['displayUri'];
- final displayUri = displayUriJson as String;
final fileJson = json['file'];
final file = fileJson as String;
- final iLengthJson = json['iLength'];
- final iLength = iLengthJson as int;
final libIdJson = json['libId'];
final libId = libIdJson as int;
- final offsetJson = json['offset'];
- final offset = offsetJson as int;
- final rLengthJson = json['rLength'];
- final rLength = rLengthJson as int;
- final rOffsetJson = json['rOffset'];
- final rOffset = rOffsetJson as int;
return DartSuggestionSetCompletionItemResolutionInfo(
- displayUri: displayUri,
file: file,
- iLength: iLength,
libId: libId,
- offset: offset,
- rLength: rLength,
- rOffset: rOffset,
);
}
- final String displayUri;
final String file;
- final int iLength;
final int libId;
- final int offset;
- final int rLength;
- final int rOffset;
@override
Map<String, Object?> toJson() {
var result = <String, Object?>{};
- result['displayUri'] = displayUri;
result['file'] = file;
- result['iLength'] = iLength;
result['libId'] = libId;
- result['offset'] = offset;
- result['rLength'] = rLength;
- result['rOffset'] = rOffset;
return result;
}
static bool canParse(Object? obj, LspJsonReporter reporter) {
if (obj is Map<String, Object?>) {
- if (!_canParseString(obj, reporter, 'displayUri',
- allowsUndefined: false, allowsNull: false)) {
- return false;
- }
if (!_canParseString(obj, reporter, 'file',
allowsUndefined: false, allowsNull: false)) {
return false;
}
- if (!_canParseInt(obj, reporter, 'iLength',
- allowsUndefined: false, allowsNull: false)) {
- return false;
- }
- if (!_canParseInt(obj, reporter, 'libId',
- allowsUndefined: false, allowsNull: false)) {
- return false;
- }
- if (!_canParseInt(obj, reporter, 'offset',
- allowsUndefined: false, allowsNull: false)) {
- return false;
- }
- if (!_canParseInt(obj, reporter, 'rLength',
- allowsUndefined: false, allowsNull: false)) {
- return false;
- }
- return _canParseInt(obj, reporter, 'rOffset',
+ return _canParseInt(obj, reporter, 'libId',
allowsUndefined: false, allowsNull: false);
} else {
reporter.reportError(
@@ -332,24 +358,14 @@
bool operator ==(Object other) {
return other is DartSuggestionSetCompletionItemResolutionInfo &&
other.runtimeType == DartSuggestionSetCompletionItemResolutionInfo &&
- displayUri == other.displayUri &&
file == other.file &&
- iLength == other.iLength &&
- libId == other.libId &&
- offset == other.offset &&
- rLength == other.rLength &&
- rOffset == other.rOffset;
+ libId == other.libId;
}
@override
int get hashCode => Object.hash(
- displayUri,
file,
- iLength,
libId,
- offset,
- rLength,
- rOffset,
);
@override
diff --git a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
index 3f7c863..c97b898 100644
--- a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
+++ b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
@@ -91,6 +91,9 @@
if (kind == engine.ElementKind.PARAMETER) {
return ElementKind.PARAMETER;
}
+ if (kind == engine.ElementKind.PART) {
+ return ElementKind.COMPILATION_UNIT;
+ }
if (kind == engine.ElementKind.PREFIX) {
return ElementKind.PREFIX;
}
diff --git a/pkg/analysis_server/lib/src/computer/computer_folding.dart b/pkg/analysis_server/lib/src/computer/computer_folding.dart
index 816e3cd..f5feba2 100644
--- a/pkg/analysis_server/lib/src/computer/computer_folding.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_folding.dart
@@ -13,7 +13,7 @@
final LineInfo _lineInfo;
final CompilationUnit _unit;
- Directive? _firstDirective, _lastDirective;
+ _Directive? _firstDirective, _lastDirective;
final List<FoldingRegion> _foldingRegions = [];
DartUnitFoldingComputer(this._lineInfo, this._unit);
@@ -59,10 +59,13 @@
if (firstDirective != null &&
lastDirective != null &&
firstDirective != lastDirective) {
- _foldingRegions.add(FoldingRegion(
+ _foldingRegions.add(
+ FoldingRegion(
FoldingKind.DIRECTIVES,
firstDirective.keyword.end,
- lastDirective.end - firstDirective.keyword.end));
+ lastDirective.directive.end - firstDirective.keyword.end,
+ ),
+ );
}
_addCommentRegions();
@@ -146,7 +149,7 @@
isFirstToken = false;
// Only exit the loop when hitting EOF *after* processing the token as
// the EOF token may have preceding comments.
- if (token.type == TokenType.EOF) {
+ if (token.isEof) {
break;
}
token = token.next;
@@ -176,7 +179,7 @@
return secondLoc.lineNumber - firstLoc.lineNumber > 1;
}
- void _recordDirective(Directive node) {
+ void _recordDirective(_Directive node) {
_firstDirective ??= node;
_lastDirective = node;
}
@@ -242,7 +245,7 @@
@override
void visitExportDirective(ExportDirective node) {
- _computer._recordDirective(node);
+ _computer._recordDirective(_Directive(node, node.exportKeyword));
super.visitExportDirective(node);
}
@@ -295,7 +298,7 @@
@override
void visitImportDirective(ImportDirective node) {
- _computer._recordDirective(node);
+ _computer._recordDirective(_Directive(node, node.importKeyword));
super.visitImportDirective(node);
}
@@ -308,7 +311,7 @@
@override
void visitLibraryDirective(LibraryDirective node) {
- _computer._recordDirective(node);
+ _computer._recordDirective(_Directive(node, node.libraryKeyword));
super.visitLibraryDirective(node);
}
@@ -343,13 +346,13 @@
@override
void visitPartDirective(PartDirective node) {
- _computer._recordDirective(node);
+ _computer._recordDirective(_Directive(node, node.partKeyword));
super.visitPartDirective(node);
}
@override
void visitPartOfDirective(PartOfDirective node) {
- _computer._recordDirective(node);
+ _computer._recordDirective(_Directive(node, node.partKeyword));
super.visitPartOfDirective(node);
}
@@ -370,6 +373,13 @@
}
}
+class _Directive {
+ final Directive directive;
+ final Token keyword;
+
+ _Directive(this.directive, this.keyword);
+}
+
extension _CommentTokenExtensions on Token {
static final _newlinePattern = RegExp(r'[\r\n]');
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights.dart b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
index 503a8ec..4e25d41 100644
--- a/pkg/analysis_server/lib/src/computer/computer_highlights.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
@@ -84,7 +84,7 @@
}
commentToken = commentToken.next;
}
- if (token.type == TokenType.EOF) {
+ if (token.isEof) {
// Only exit the loop *after* processing the EOF token as it may
// have preceding comments.
break;
@@ -759,7 +759,7 @@
@override
void visitExportDirective(ExportDirective node) {
computer._addRegion_node(node, HighlightRegionType.DIRECTIVE);
- computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN);
+ computer._addRegion_token(node.exportKeyword, HighlightRegionType.BUILT_IN);
_addRegions_configurations(node.configurations);
super.visitExportDirective(node);
}
@@ -916,7 +916,7 @@
@override
void visitImportDirective(ImportDirective node) {
computer._addRegion_node(node, HighlightRegionType.DIRECTIVE);
- computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN);
+ computer._addRegion_token(node.importKeyword, HighlightRegionType.BUILT_IN);
computer._addRegion_token(
node.deferredKeyword, HighlightRegionType.BUILT_IN);
computer._addRegion_token(node.asKeyword, HighlightRegionType.BUILT_IN);
@@ -978,7 +978,8 @@
@override
void visitLibraryDirective(LibraryDirective node) {
computer._addRegion_node(node, HighlightRegionType.DIRECTIVE);
- computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN);
+ computer._addRegion_token(
+ node.libraryKeyword, HighlightRegionType.BUILT_IN);
super.visitLibraryDirective(node);
}
@@ -1053,7 +1054,7 @@
@override
void visitPartDirective(PartDirective node) {
computer._addRegion_node(node, HighlightRegionType.DIRECTIVE);
- computer._addRegion_token(node.keyword, HighlightRegionType.BUILT_IN);
+ computer._addRegion_token(node.partKeyword, HighlightRegionType.BUILT_IN);
super.visitPartDirective(node);
}
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
index 1e44d82..cad822d 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart
@@ -37,8 +37,25 @@
/// Whether to include symbols from libraries that have not been imported.
final bool suggestFromUnimportedLibraries;
+ /// Whether to use [NotImportedContributor] instead of SuggestionSets to
+ /// build completions for not-yet-imported libraries.
+ final bool previewNotImportedCompletions;
+
+ /// The budget to use for [NotImportedContributor] computation.
+ ///
+ /// This is usually the default value, but can be overridden via
+ /// initializationOptions (used for tests, but may also be useful for
+ /// debugging).
+ late final CompletionBudget completionBudget;
+
CompletionHandler(super.server, LspInitializationOptions options)
- : suggestFromUnimportedLibraries = options.suggestFromUnimportedLibraries;
+ : suggestFromUnimportedLibraries = options.suggestFromUnimportedLibraries,
+ previewNotImportedCompletions = options.previewNotImportedCompletions {
+ final budgetMs = options.notImportedCompletionBudgetMilliseconds;
+ completionBudget = CompletionBudget(budgetMs != null
+ ? Duration(milliseconds: budgetMs)
+ : CompletionBudget.defaultDuration);
+ }
@override
Method get handlesMessage => Method.textDocument_completion;
@@ -299,8 +316,12 @@
String? triggerCharacter,
CancellationToken token,
) async {
- final useSuggestionSets =
- suggestFromUnimportedLibraries && capabilities.applyEdit;
+ final useSuggestionSets = suggestFromUnimportedLibraries &&
+ capabilities.applyEdit &&
+ !previewNotImportedCompletions;
+ final useNotImportedCompletions = suggestFromUnimportedLibraries &&
+ capabilities.applyEdit &&
+ previewNotImportedCompletions;
final completionRequest = DartCompletionRequest.forResolvedUnit(
resolvedUnit: unit,
@@ -321,20 +342,24 @@
Set<ElementKind>? includedElementKinds;
Set<String>? includedElementNames;
List<IncludedSuggestionRelevanceTag>? includedSuggestionRelevanceTags;
+ NotImportedSuggestions? notImportedSuggestions;
if (useSuggestionSets) {
includedElementKinds = <ElementKind>{};
includedElementNames = <String>{};
includedSuggestionRelevanceTags = <IncludedSuggestionRelevanceTag>[];
+ } else if (useNotImportedCompletions) {
+ notImportedSuggestions = NotImportedSuggestions();
}
try {
final serverSuggestions2 =
await performance.runAsync('computeSuggestions', (performance) async {
var contributor = DartCompletionManager(
- budget: CompletionBudget(CompletionBudget.defaultDuration),
+ budget: completionBudget,
includedElementKinds: includedElementKinds,
includedElementNames: includedElementNames,
includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
+ notImportedSuggestions: notImportedSuggestions,
);
// `await` required for `performance.runAsync` to count time.
@@ -383,11 +408,25 @@
}
// Convert to LSP ranges using the LineInfo.
- Range? replacementRange = toRange(
+ var replacementRange = toRange(
unit.lineInfo, itemReplacementOffset, itemReplacementLength);
- Range? insertionRange =
+ var insertionRange =
toRange(unit.lineInfo, itemReplacementOffset, itemInsertLength);
+ // For not-imported items, we need to include the file+uri to be able
+ // to compute the import-inserting edits in the `completionItem/resolve`
+ // call later.
+ CompletionItemResolutionInfo? resolutionInfo;
+ final libraryUri = item.libraryUri;
+ if (useNotImportedCompletions &&
+ libraryUri != null &&
+ (item.isNotImported ?? false)) {
+ resolutionInfo = DartNotImportedCompletionResolutionInfo(
+ file: unit.path,
+ libraryUri: libraryUri,
+ );
+ }
+
return toCompletionItem(
capabilities,
unit.lineInfo,
@@ -402,6 +441,10 @@
includeCommitCharacters:
server.clientConfiguration.global.previewCommitCharacters,
completeFunctionCalls: completeFunctionCalls,
+ resolutionData: resolutionInfo,
+ // Exclude docs if we will be providing them via
+ // `completionItem/resolve`.
+ includeDocs: resolutionInfo == null,
);
}
@@ -504,7 +547,6 @@
.map((item) => declarationToCompletionItem(
capabilities,
unit.path,
- offset,
includedSet,
library,
tagBoosts,
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
index 07ab252..93b22ad 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/lsp_protocol/protocol.dart' hide Element;
+import 'package:analysis_server/src/computer/computer_hover.dart';
import 'package:analysis_server/src/lsp/client_capabilities.dart';
import 'package:analysis_server/src/lsp/constants.dart';
import 'package:analysis_server/src/lsp/handlers/handlers.dart';
@@ -10,8 +11,6 @@
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/session.dart';
import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/source/line_info.dart';
-import 'package:analyzer/src/util/comment.dart' as analyzer;
import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
class CompletionResolveHandler
@@ -41,6 +40,8 @@
if (resolutionInfo is DartSuggestionSetCompletionItemResolutionInfo) {
return resolveDartSuggestionSetCompletion(params, resolutionInfo, token);
+ } else if (resolutionInfo is DartNotImportedCompletionResolutionInfo) {
+ return resolveDartNotImportedCompletion(params, resolutionInfo, token);
} else if (resolutionInfo is PubPackageCompletionItemResolutionInfo) {
return resolvePubPackageCompletion(params, resolutionInfo, token);
} else {
@@ -51,12 +52,9 @@
Future<ErrorOr<CompletionItem>> resolveDartCompletion(
CompletionItem item,
LspClientCapabilities clientCapabilities,
- LineInfo lineInfo,
CancellationToken token, {
required String file,
required Uri libraryUri,
- required Range insertionRange,
- required Range replacementRange,
}) async {
const timeout = Duration(milliseconds: 1000);
var timer = Stopwatch()..start();
@@ -72,6 +70,11 @@
return cancelled();
}
+ final result = await session.getResolvedUnit(file);
+ if (result is! ResolvedUnitResult) {
+ return cancelled();
+ }
+
final element = await _getElement(session, libraryUri, item);
if (element == null) {
return error(
@@ -85,15 +88,9 @@
return cancelled();
}
- var newInsertText = item.textEdit
- ?.map((edit) => edit.newText, (edit) => edit.newText) ??
- item.label;
final builder = ChangeBuilder(session: session);
await builder.addDartFileEdit(file, (builder) {
- final result = builder.importLibraryElement(libraryUri);
- if (result.prefix != null) {
- newInsertText = '${result.prefix}.$newInsertText';
- }
+ builder.importLibraryElement(libraryUri);
});
if (token.isCancellationRequested) {
@@ -121,12 +118,14 @@
}
final formats = clientCapabilities.completionDocumentationFormats;
- final dartDoc =
- analyzer.getDartDocPlainText(element.documentationComment);
- final documentation =
- dartDoc != null ? asMarkupContentOrString(formats, dartDoc) : null;
- final supportsInsertReplace =
- clientCapabilities.insertReplaceCompletionRanges;
+ final dartDocInfo = server.getDartdocDirectiveInfoForSession(session);
+ final dartDocData =
+ DartUnitHoverComputer.computeDocumentation(dartDocInfo, element);
+ final dartDoc = dartDocData?.full;
+ // `dartDoc` can be both null or empty.
+ final documentation = dartDoc != null && dartDoc.isNotEmpty
+ ? asMarkupContentOrString(formats, dartDoc)
+ : null;
// If the only URI we have is a file:// URI, display it as relative to
// the file we're importing into, rather than the full URI.
@@ -144,7 +143,7 @@
label: item.label,
kind: item.kind,
tags: item.tags,
- detail: thisFilesChanges.isNotEmpty
+ detail: changes.edits.isNotEmpty
? "Auto import from '$autoImportDisplayUri'\n\n${item.detail ?? ''}"
.trim()
: item.detail,
@@ -155,23 +154,10 @@
filterText: item.filterText,
insertTextFormat: item.insertTextFormat,
insertTextMode: item.insertTextMode,
- textEdit: supportsInsertReplace && insertionRange != replacementRange
- ? Either2<InsertReplaceEdit, TextEdit>.t1(
- InsertReplaceEdit(
- insert: insertionRange,
- replace: replacementRange,
- newText: newInsertText,
- ),
- )
- : Either2<InsertReplaceEdit, TextEdit>.t2(
- TextEdit(
- range: replacementRange,
- newText: newInsertText,
- ),
- ),
+ textEdit: item.textEdit,
additionalTextEdits: thisFilesChanges
.expand((change) =>
- change.edits.map((edit) => toTextEdit(lineInfo, edit)))
+ change.edits.map((edit) => toTextEdit(result.lineInfo, edit)))
.toList(),
commitCharacters: item.commitCharacters,
command: command ?? item.command,
@@ -191,6 +177,27 @@
);
}
+ Future<ErrorOr<CompletionItem>> resolveDartNotImportedCompletion(
+ CompletionItem item,
+ DartNotImportedCompletionResolutionInfo data,
+ CancellationToken token,
+ ) async {
+ final clientCapabilities = server.clientCapabilities;
+ if (clientCapabilities == null) {
+ // This should not happen unless a client misbehaves.
+ return error(ErrorCodes.ServerNotInitialized,
+ 'Requests not before server is initilized');
+ }
+
+ return resolveDartCompletion(
+ item,
+ clientCapabilities,
+ token,
+ file: data.file,
+ libraryUri: Uri.parse(data.libraryUri),
+ );
+ }
+
Future<ErrorOr<CompletionItem>> resolveDartSuggestionSetCompletion(
CompletionItem item,
DartSuggestionSetCompletionItemResolutionInfo data,
@@ -202,16 +209,6 @@
return serverNotInitializedError;
}
- final file = data.file;
- final lineInfo = server.getLineInfo(file);
- if (lineInfo == null) {
- return error(
- ErrorCodes.InternalError,
- 'Line info not available for $file',
- null,
- );
- }
-
var library = server.declarationsTracker?.getLibrary(data.libId);
if (library == null) {
return error(
@@ -221,18 +218,12 @@
);
}
- final insertionRange = toRange(lineInfo, data.rOffset, data.iLength);
- final replacementRange = toRange(lineInfo, data.rOffset, data.rLength);
-
return resolveDartCompletion(
item,
clientCapabilities,
- lineInfo,
token,
- file: file,
+ file: data.file,
libraryUri: library.uri,
- insertionRange: insertionRange,
- replacementRange: replacementRange,
);
}
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
index 49cc0b8..6a1cc96 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -887,21 +887,30 @@
class LspInitializationOptions {
final bool onlyAnalyzeProjectsWithOpenFiles;
+ final bool previewNotImportedCompletions;
final bool suggestFromUnimportedLibraries;
final bool closingLabels;
final bool outline;
final bool flutterOutline;
+ final int? notImportedCompletionBudgetMilliseconds;
LspInitializationOptions(dynamic options)
: onlyAnalyzeProjectsWithOpenFiles = options != null &&
options['onlyAnalyzeProjectsWithOpenFiles'] == true,
+ // Undocumented preview flag to allow easy testing of not imported
+ // completion contributor.
+ previewNotImportedCompletions =
+ options != null && options['previewNotImportedCompletions'] == true,
// suggestFromUnimportedLibraries defaults to true, so must be
// explicitly passed as false to disable.
suggestFromUnimportedLibraries = options == null ||
options['suggestFromUnimportedLibraries'] != false,
closingLabels = options != null && options['closingLabels'] == true,
outline = options != null && options['outline'] == true,
- flutterOutline = options != null && options['flutterOutline'] == true;
+ flutterOutline = options != null && options['flutterOutline'] == true,
+ notImportedCompletionBudgetMilliseconds = options != null
+ ? options['notImportedCompletionBudgetMilliseconds'] as int?
+ : null;
}
class LspServerContextManagerCallbacks extends ContextManagerCallbacks {
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index 77a4353..a3c3c99 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -269,7 +269,6 @@
lsp.CompletionItem declarationToCompletionItem(
LspClientCapabilities capabilities,
String file,
- int offset,
server.IncludedSuggestionSet includedSuggestionSet,
Library library,
Map<String, int> tagBoosts,
@@ -382,13 +381,9 @@
),
// data, used for completionItem/resolve.
data: lsp.DartSuggestionSetCompletionItemResolutionInfo(
- file: file,
- offset: offset,
- libId: includedSuggestionSet.id,
- displayUri: includedSuggestionSet.displayUri ?? library.uri.toString(),
- rOffset: replacementOffset,
- iLength: insertLength,
- rLength: replacementLength),
+ file: file,
+ libId: includedSuggestionSet.id,
+ ),
);
}
@@ -1123,6 +1118,7 @@
server.CompletionSuggestion suggestion, {
required Range replacementRange,
required Range insertionRange,
+ bool includeDocs = true,
required bool includeCommitCharacters,
required bool completeFunctionCalls,
CompletionItemResolutionInfo? resolutionData,
@@ -1221,7 +1217,7 @@
includeCommitCharacters ? dartCompletionCommitCharacters : null,
data: resolutionData,
detail: detail,
- documentation: cleanedDoc != null
+ documentation: cleanedDoc != null && includeDocs
? asMarkupContentOrString(formats, cleanedDoc)
: null,
deprecated: supportsCompletionDeprecatedFlag && suggestion.isDeprecated
diff --git a/pkg/analysis_server/lib/src/lsp/source_edits.dart b/pkg/analysis_server/lib/src/lsp/source_edits.dart
index ac2a8b8..cea729e 100644
--- a/pkg/analysis_server/lib/src/lsp/source_edits.dart
+++ b/pkg/analysis_server/lib/src/lsp/source_edits.dart
@@ -309,7 +309,7 @@
/// Iterates over a token stream returning all tokens including comments.
Iterable<Token> _iterateAllTokens(Token token) sync* {
- while (token.type != TokenType.EOF) {
+ while (!token.isEof) {
Token? commentToken = token.precedingComments;
while (commentToken != null) {
yield commentToken;
diff --git a/pkg/analysis_server/lib/src/services/correction/assist.dart b/pkg/analysis_server/lib/src/services/correction/assist.dart
index 2dbdf85..43a169f 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -228,6 +228,11 @@
30,
'Convert to StatefulWidget',
);
+ static const FLUTTER_CONVERT_TO_STATELESS_WIDGET = AssistKind(
+ 'dart.assist.flutter.convert.toStatelessWidget',
+ 30,
+ 'Convert to StatelessWidget',
+ );
// Flutter wrap specific assists
static const FLUTTER_WRAP_GENERIC = AssistKind(
diff --git a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
index 00f542e..41f866b 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -44,6 +44,7 @@
import 'package:analysis_server/src/services/correction/dart/exchange_operands.dart';
import 'package:analysis_server/src/services/correction/dart/flutter_convert_to_children.dart';
import 'package:analysis_server/src/services/correction/dart/flutter_convert_to_stateful_widget.dart';
+import 'package:analysis_server/src/services/correction/dart/flutter_convert_to_stateless_widget.dart';
import 'package:analysis_server/src/services/correction/dart/flutter_move_down.dart';
import 'package:analysis_server/src/services/correction/dart/flutter_move_up.dart';
import 'package:analysis_server/src/services/correction/dart/flutter_remove_widget.dart';
@@ -125,6 +126,7 @@
ExchangeOperands.new,
FlutterConvertToChildren.new,
FlutterConvertToStatefulWidget.new,
+ FlutterConvertToStatelessWidget.new,
FlutterMoveDown.new,
FlutterMoveUp.new,
FlutterRemoveWidget.new,
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateful_widget.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateful_widget.dart
index 4e73f85..c646e6f 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateful_widget.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateful_widget.dart
@@ -34,28 +34,18 @@
return;
}
- // Find the build() method.
- MethodDeclaration? buildMethod;
- for (var member in widgetClass.members) {
- if (member is MethodDeclaration && member.name.name == 'build') {
- var parameters = member.parameters;
- if (parameters != null && parameters.parameters.length == 1) {
- buildMethod = member;
- break;
- }
- }
- }
- if (buildMethod == null) {
- return;
- }
-
- // Must be a StatelessWidget subclasses.
+ // Must be a StatelessWidget subclass.
var widgetClassElement = widgetClass.declaredElement!;
var superType = widgetClassElement.supertype;
if (superType == null || !flutter.isExactlyStatelessWidgetType(superType)) {
return;
}
+ var buildMethod = _findBuildMethod(widgetClass);
+ if (buildMethod == null) {
+ return;
+ }
+
var widgetName = widgetClassElement.displayName;
var stateName = widgetClassElement.isPrivate
? '${widgetName}State'
@@ -254,6 +244,18 @@
});
});
}
+
+ MethodDeclaration? _findBuildMethod(ClassDeclaration widgetClass) {
+ for (var member in widgetClass.members) {
+ if (member is MethodDeclaration && member.name.name == 'build') {
+ var parameters = member.parameters;
+ if (parameters != null && parameters.parameters.length == 1) {
+ return member;
+ }
+ }
+ }
+ return null;
+ }
}
class _FieldFinder extends RecursiveAstVisitor<void> {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateless_widget.dart b/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateless_widget.dart
new file mode 100644
index 0000000..c061f38
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/flutter_convert_to_stateless_widget.dart
@@ -0,0 +1,406 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:_fe_analyzer_shared/src/scanner/token.dart';
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/utilities/flutter.dart';
+import 'package:analyzer/dart/ast/ast.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/source/source_range.dart';
+import 'package:analyzer/src/dart/ast/extensions.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element;
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class FlutterConvertToStatelessWidget extends CorrectionProducer {
+ @override
+ AssistKind get assistKind =>
+ DartAssistKind.FLUTTER_CONVERT_TO_STATELESS_WIDGET;
+
+ @override
+ Future<void> compute(ChangeBuilder builder) async {
+ var widgetClass = node.thisOrAncestorOfType<ClassDeclaration>();
+ var superclass = widgetClass?.extendsClause?.superclass;
+ if (widgetClass == null || superclass == null) return;
+
+ // Don't spam, activate only from the `class` keyword to the class body.
+ if (selectionOffset < widgetClass.classKeyword.offset ||
+ selectionOffset > widgetClass.leftBracket.end) {
+ return;
+ }
+
+ // Must be a StatefulWidget subclass.
+ var widgetClassElement = widgetClass.declaredElement!;
+ var superType = widgetClassElement.supertype;
+ if (superType == null || !flutter.isExactlyStatefulWidgetType(superType)) {
+ return;
+ }
+
+ var createStateMethod = _findCreateStateMethod(widgetClass);
+ if (createStateMethod == null) return;
+
+ var stateClass = _findStateClass(widgetClassElement);
+ var stateClassElement = stateClass?.declaredElement;
+ if (stateClass == null ||
+ stateClassElement == null ||
+ !Identifier.isPrivateName(stateClass.name.name) ||
+ !_isSameTypeParameters(widgetClass, stateClass)) {
+ return;
+ }
+
+ var verifier = _StatelessVerifier();
+ var fieldFinder = _FieldFinder();
+
+ for (var member in stateClass.members) {
+ if (member is ConstructorDeclaration) {
+ member.accept(fieldFinder);
+ } else if (member is MethodDeclaration) {
+ member.accept(verifier);
+ if (!verifier.canBeStateless) {
+ return;
+ }
+ }
+ }
+
+ var usageVerifier =
+ _StateUsageVisitor(widgetClassElement, stateClassElement);
+ unit.visitChildren(usageVerifier);
+ if (usageVerifier.used) return;
+
+ var fieldsAssignedInConstructors = fieldFinder.fieldsAssignedInConstructors;
+
+ // Prepare nodes to move.
+ var nodesToMove = <ClassMember>[];
+ var elementsToMove = <Element>{};
+ for (var member in stateClass.members) {
+ if (member is FieldDeclaration) {
+ if (member.isStatic) {
+ return;
+ }
+ for (var fieldNode in member.fields.variables) {
+ var fieldElement = fieldNode.declaredElement as FieldElement;
+ if (!fieldsAssignedInConstructors.contains(fieldElement)) {
+ nodesToMove.add(member);
+ elementsToMove.add(fieldElement);
+
+ var getter = fieldElement.getter;
+ if (getter != null) {
+ elementsToMove.add(getter);
+ }
+
+ var setter = fieldElement.setter;
+ if (setter != null) {
+ elementsToMove.add(setter);
+ }
+ }
+ }
+ } else if (member is MethodDeclaration) {
+ if (member.isStatic) {
+ return;
+ }
+ if (!_isDefaultOverride(member)) {
+ nodesToMove.add(member);
+ elementsToMove.add(member.declaredElement!);
+ }
+ }
+ }
+
+ /// Return the code for the [movedNode], so that qualification of the
+ /// references to the widget (`widget.` or static `MyWidgetClass.`)
+ /// is removed
+ String rewriteWidgetMemberReferences(AstNode movedNode) {
+ var linesRange = utils.getLinesRange(range.node(movedNode));
+ var text = utils.getRangeText(linesRange);
+
+ // Remove `widget.` before references to the widget instance members.
+ var visitor = _ReplacementEditBuilder(
+ widgetClassElement, elementsToMove, linesRange);
+ movedNode.accept(visitor);
+ return SourceEdit.applySequence(text, visitor.edits.reversed);
+ }
+
+ var statelessWidgetClass = await sessionHelper.getClass(
+ flutter.widgetsUri,
+ 'StatelessWidget',
+ );
+ if (statelessWidgetClass == null) {
+ return;
+ }
+
+ await builder.addDartFileEdit(file, (builder) {
+ builder.addReplacement(range.node(superclass), (builder) {
+ builder.writeReference(statelessWidgetClass);
+ });
+
+ builder.addDeletion(range.deletionRange(stateClass));
+
+ var createStateNextToEnd = createStateMethod.endToken.next!;
+ createStateNextToEnd =
+ createStateNextToEnd.precedingComments ?? createStateNextToEnd;
+ var createStateRange = range.startOffsetEndOffset(
+ utils.getLineContentStart(createStateMethod.offset),
+ utils.getLineContentStart(createStateNextToEnd.offset));
+
+ var newLine = createStateNextToEnd.type != TokenType.CLOSE_CURLY_BRACKET;
+
+ builder.addReplacement(createStateRange, (builder) {
+ for (var i = 0; i < nodesToMove.length; i++) {
+ var member = nodesToMove[i];
+ var comments = member.beginToken.precedingComments;
+ if (comments != null) {
+ var offset = utils.getLineContentStart(comments.offset);
+ var length = comments.end - offset;
+ builder.writeln(utils.getText(offset, length));
+ }
+
+ var text = rewriteWidgetMemberReferences(member);
+ builder.write(text);
+ if (newLine || i < nodesToMove.length - 1) {
+ builder.writeln();
+ }
+ }
+ });
+ });
+ }
+
+ MethodDeclaration? _findCreateStateMethod(ClassDeclaration widgetClass) {
+ for (var member in widgetClass.members) {
+ if (member is MethodDeclaration && member.name.name == 'createState') {
+ var parameters = member.parameters;
+ if (parameters?.parameters.isEmpty ?? false) {
+ return member;
+ }
+ break;
+ }
+ }
+ return null;
+ }
+
+ ClassDeclaration? _findStateClass(ClassElement widgetClassElement) {
+ for (var declaration in unit.declarations) {
+ if (declaration is ClassDeclaration) {
+ var type = declaration.extendsClause?.superclass.type;
+
+ if (_isState(widgetClassElement, type)) {
+ return declaration;
+ }
+ }
+ }
+ return null;
+ }
+
+ bool _isSameTypeParameters(
+ ClassDeclaration widgetClass, ClassDeclaration stateClass) {
+ List<TypeParameter>? parameters(ClassDeclaration declaration) =>
+ declaration.typeParameters?.typeParameters;
+
+ var widgetParams = parameters(widgetClass);
+ var stateParams = parameters(stateClass);
+
+ if (widgetParams == null && stateParams == null) {
+ return true;
+ }
+ if (widgetParams == null || stateParams == null) {
+ return false;
+ }
+ if (widgetParams.length < stateParams.length) {
+ return false;
+ }
+ outer:
+ for (var stateParam in stateParams) {
+ for (var widgetParam in widgetParams) {
+ if (stateParam.name.name == widgetParam.name.name &&
+ stateParam.bound?.type == widgetParam.bound?.type) {
+ continue outer;
+ }
+ }
+ return false;
+ }
+ return true;
+ }
+
+ static bool _isDefaultOverride(MethodDeclaration? methodDeclaration) {
+ var body = methodDeclaration?.body;
+ if (body != null) {
+ Expression expression;
+ if (body is BlockFunctionBody) {
+ var statements = body.block.statements;
+ if (statements.isEmpty) return true;
+ if (statements.length > 1) return false;
+ var first = statements.first;
+ if (first is! ExpressionStatement) return false;
+ expression = first.expression;
+ } else if (body is ExpressionFunctionBody) {
+ expression = body.expression;
+ } else {
+ return false;
+ }
+ if (expression is MethodInvocation &&
+ expression.target is SuperExpression &&
+ methodDeclaration!.name.name == expression.methodName.name) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static bool _isState(ClassElement widgetClassElement, DartType? type) {
+ if (type is! ParameterizedType) return false;
+
+ var typeArguments = type.typeArguments;
+ if (typeArguments.length != 1 ||
+ typeArguments[0].element != widgetClassElement) {
+ return false;
+ }
+
+ var classElement = type.element;
+ return classElement is ClassElement &&
+ Flutter.instance.isExactState(classElement);
+ }
+}
+
+class _FieldFinder extends RecursiveAstVisitor<void> {
+ Set<FieldElement> fieldsAssignedInConstructors = {};
+
+ @override
+ void visitSimpleIdentifier(SimpleIdentifier node) {
+ if (node.parent is FieldFormalParameter) {
+ var element = node.staticElement;
+ if (element is FieldFormalParameterElement) {
+ var field = element.field;
+ if (field != null) {
+ fieldsAssignedInConstructors.add(field);
+ }
+ }
+ }
+ if (node.parent is ConstructorFieldInitializer) {
+ var element = node.staticElement;
+ if (element is FieldElement) {
+ fieldsAssignedInConstructors.add(element);
+ }
+ }
+ if (node.inSetterContext()) {
+ var element = node.writeOrReadElement;
+ if (element is PropertyAccessorElement) {
+ var field = element.variable;
+ if (field is FieldElement) {
+ fieldsAssignedInConstructors.add(field);
+ }
+ }
+ }
+ }
+}
+
+class _ReplacementEditBuilder extends RecursiveAstVisitor<void> {
+ final ClassElement widgetClassElement;
+
+ final Set<Element> elementsToMove;
+
+ final SourceRange linesRange;
+
+ List<SourceEdit> edits = [];
+
+ _ReplacementEditBuilder(
+ this.widgetClassElement, this.elementsToMove, this.linesRange);
+
+ @override
+ void visitSimpleIdentifier(SimpleIdentifier node) {
+ if (node.inDeclarationContext()) {
+ return;
+ }
+ var element = node.staticElement;
+ if (element is ExecutableElement &&
+ element.enclosingElement == widgetClassElement &&
+ !elementsToMove.contains(element)) {
+ var parent = node.parent;
+ if (parent is PrefixedIdentifier) {
+ var grandParent = parent.parent;
+ SourceEdit? rightBracketEdit;
+ if (!node.name.contains('\$') &&
+ grandParent is InterpolationExpression &&
+ grandParent.leftBracket.type ==
+ TokenType.STRING_INTERPOLATION_EXPRESSION) {
+ edits.add(SourceEdit(
+ grandParent.leftBracket.end - 1 - linesRange.offset, 1, ''));
+ var offset = grandParent.rightBracket?.offset;
+ if (offset != null) {
+ rightBracketEdit = SourceEdit(offset - linesRange.offset, 1, '');
+ }
+ }
+ var offset = parent.prefix.offset;
+ var length = parent.period.end - offset;
+ edits.add(SourceEdit(offset - linesRange.offset, length, ''));
+ if (rightBracketEdit != null) {
+ edits.add(rightBracketEdit);
+ }
+ } else if (parent is MethodInvocation) {
+ var target = parent.target;
+ var operator = parent.operator;
+ if (target != null && operator != null) {
+ var offset = target.beginToken.offset;
+ var length = operator.end - offset;
+ edits.add(SourceEdit(offset - linesRange.offset, length, ''));
+ }
+ }
+ }
+ }
+}
+
+class _StatelessVerifier extends RecursiveAstVisitor<void> {
+ var canBeStateless = true;
+
+ @override
+ void visitMethodInvocation(MethodInvocation node) {
+ var methodElement = node.methodName.staticElement?.declaration;
+ if (methodElement is ClassMemberElement) {
+ var classElement = methodElement.enclosingElement;
+ if (classElement is ClassElement &&
+ Flutter.instance.isExactState(classElement) &&
+ !FlutterConvertToStatelessWidget._isDefaultOverride(
+ node.thisOrAncestorOfType<MethodDeclaration>())) {
+ canBeStateless = false;
+ return;
+ }
+ }
+ super.visitMethodInvocation(node);
+ }
+}
+
+class _StateUsageVisitor extends RecursiveAstVisitor<void> {
+ bool used = false;
+ ClassElement widgetClassElement;
+ ClassElement stateClassElement;
+
+ _StateUsageVisitor(this.widgetClassElement, this.stateClassElement);
+
+ @override
+ void visitInstanceCreationExpression(InstanceCreationExpression node) {
+ super.visitInstanceCreationExpression(node);
+ if (node.staticType?.element != stateClassElement) {
+ return;
+ }
+ var methodDeclaration = node.thisOrAncestorOfType<MethodDeclaration>();
+ var classDeclaration =
+ methodDeclaration?.thisOrAncestorOfType<ClassDeclaration>();
+
+ if (methodDeclaration?.name.name != 'createState' ||
+ classDeclaration?.declaredElement != widgetClassElement) {
+ used = true;
+ }
+ }
+
+ @override
+ void visitMethodInvocation(MethodInvocation node) {
+ var type = node.staticType;
+ if (node.methodName.name == 'createState' &&
+ (FlutterConvertToStatelessWidget._isState(widgetClassElement, type) ||
+ type?.element == stateClassElement)) {
+ used = true;
+ }
+ }
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
index 9a156c4..59d04bd 100644
--- a/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/statement_analyzer.dart
@@ -28,7 +28,7 @@
featureSet: featureSet,
);
var token = scanner.tokenize();
- while (token.type != TokenType.EOF) {
+ while (!token.isEof) {
tokens.add(token);
token = token.next!;
}
diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index 3f0281a7..3c1c745 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -176,7 +176,7 @@
List<SourceRange> getCommentRanges(CompilationUnit unit) {
var ranges = <SourceRange>[];
var token = unit.beginToken;
- while (token.type != TokenType.EOF) {
+ while (!token.isEof) {
var commentToken = token.precedingComments;
while (commentToken != null) {
ranges.add(range.token(commentToken));
@@ -1450,7 +1450,7 @@
featureSet: featureSet,
);
var token = scanner.tokenize();
- while (token.type != TokenType.EOF) {
+ while (!token.isEof) {
tokens.add(token);
token = token.next!;
}
diff --git a/pkg/analysis_server/lib/src/utilities/extensions/range_factory.dart b/pkg/analysis_server/lib/src/utilities/extensions/range_factory.dart
index eedc3c7..f073fdb 100644
--- a/pkg/analysis_server/lib/src/utilities/extensions/range_factory.dart
+++ b/pkg/analysis_server/lib/src/utilities/extensions/range_factory.dart
@@ -119,7 +119,7 @@
/// the [token] if there is no such comment.
Token _leadingComment(LineInfo lineInfo, Token token) {
var previous = token.previous;
- if (previous == null || previous.type == TokenType.EOF) {
+ if (previous == null || previous.isEof) {
return token.precedingComments ?? token;
}
var previousLine = lineInfo.getLocation(previous.offset).lineNumber;
diff --git a/pkg/analysis_server/test/analysis/notification_navigation_test.dart b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
index 2d1b4e5..1502fd5 100644
--- a/pkg/analysis_server/test/analysis/notification_navigation_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_navigation_test.dart
@@ -1318,6 +1318,15 @@
assertHasFileTarget(unitFile, 0, 0);
}
+ Future<void> test_string_part_hasSource_notPart() async {
+ addTestFile('''
+library lib;
+part "test_unit.dart";
+''');
+ await prepareNavigation();
+ assertHasRegionString('"test_unit.dart"');
+ }
+
Future<void> test_string_part_invalidUri() async {
addTestFile('''
part ":[invalid]";
@@ -1326,15 +1335,6 @@
assertNoRegionString('":[invalid]"');
}
- Future<void> test_string_part_unresolvedUri() async {
- addTestFile('''
-library lib;
-part "test_unit.dart";
-''');
- await prepareNavigation();
- assertNoRegionString('"test_unit.dart"');
- }
-
Future<void> test_superConstructorInvocation() async {
addTestFile('''
class A {
diff --git a/pkg/analysis_server/test/client/completion_driver_test.dart b/pkg/analysis_server/test/client/completion_driver_test.dart
index 39d20e9..539374a 100644
--- a/pkg/analysis_server/test/client/completion_driver_test.dart
+++ b/pkg/analysis_server/test/client/completion_driver_test.dart
@@ -163,7 +163,11 @@
if (file != null && s.element?.location?.file != convertPath(file)) {
return false;
}
- if (libraryUri != null && s.libraryUri != libraryUri) {
+ // Library URIs are not available in protocol v1 so skip the check to
+ // allow the the same test to verify for v2.
+ if (!isProtocolVersion1 &&
+ libraryUri != null &&
+ s.libraryUri != libraryUri) {
return false;
}
return true;
@@ -621,6 +625,7 @@
assertSuggestion(
completion: 'A',
element: ElementKind.CLASS,
+ libraryUri: 'package:test/b.dart',
);
}
@@ -641,10 +646,12 @@
''');
// Should be only one suggestion, which comes from local declaration.
- assertSuggestion(
+ var suggestion = suggestionWith(
completion: 'A',
element: ElementKind.CLASS,
);
+ expect(suggestion, isNotNull);
+ expect(suggestion.libraryUri, isNull);
}
Future<void> test_project_lib_setters_class() async {
diff --git a/pkg/analysis_server/test/lsp/completion_dart_test.dart b/pkg/analysis_server/test/lsp/completion_dart_test.dart
index 9010d16..6eb8824 100644
--- a/pkg/analysis_server/test/lsp/completion_dart_test.dart
+++ b/pkg/analysis_server/test/lsp/completion_dart_test.dart
@@ -21,6 +21,7 @@
void main() {
defineReflectiveSuite(() {
defineReflectiveTests(CompletionTest);
+ defineReflectiveTests(CompletionWithPreviewNotImportedCompletionsTest);
defineReflectiveTests(DartSnippetCompletionTest);
defineReflectiveTests(FlutterSnippetCompletionTest);
defineReflectiveTests(FlutterSnippetCompletionWithoutNullSafetyTest);
@@ -30,6 +31,15 @@
@reflectiveTest
class CompletionTest extends AbstractLspAnalysisServerTest
with CompletionTestMixin {
+ CompletionTest({bool previewNotImportedCompletions = false}) {
+ defaultInitializationOptions = {
+ 'previewNotImportedCompletions': previewNotImportedCompletions,
+ // Default to a high budget for tests because everything is cold and
+ // may take longer to return.
+ 'notImportedCompletionBudgetMilliseconds': 50000
+ };
+ }
+
Future<void> checkCompleteFunctionCallInsertText(
String content, String completion,
{required String? editText, InsertTextFormat? insertTextFormat}) async {
@@ -1852,16 +1862,28 @@
}
Future<void> test_unimportedSymbols_enumValues() async {
+ // Enum values only show up in contexts with their types, so we need two
+ // extra files - one with the Enum definition, and one with a function that
+ // accepts the Enum type that is imported into the test files.
newFile(
- join(projectFolderPath, 'source_file.dart'),
+ join(projectFolderPath, 'lib', 'enum.dart'),
'''
- enum MyExportedEnum { One, Two }
+ enum MyExportedEnum { One, Two }
+ ''',
+ );
+ newFile(
+ join(projectFolderPath, 'lib', 'function_x.dart'),
+ '''
+ import 'package:test/enum.dart';
+ void x(MyExportedEnum e) {}
''',
);
final content = '''
+import 'package:test/function_x.dart';
+
void f() {
- var a = MyExported^
+ x(MyExported^
}
''';
@@ -1892,7 +1914,9 @@
// Ensure the detail field was update to show this will auto-import.
expect(
- resolved.detail, startsWith("Auto import from '../source_file.dart'"));
+ resolved.detail,
+ startsWith("Auto import from 'package:test/enum.dart'"),
+ );
// Ensure the edit was added on.
expect(resolved.textEdit, isNotNull);
@@ -1907,17 +1931,18 @@
// Ensure both edits were made - the completion, and the inserted import.
expect(newContent, equals('''
-import '../source_file.dart';
+import 'package:test/enum.dart';
+import 'package:test/function_x.dart';
void f() {
- var a = MyExportedEnum.One
+ x(MyExportedEnum.One
}
'''));
}
Future<void> test_unimportedSymbols_enumValuesAlreadyImported() async {
newFile(
- join(projectFolderPath, 'lib', 'source_file.dart'),
+ join(projectFolderPath, 'lib', 'enum.dart'),
'''
enum MyExportedEnum { One, Two }
''',
@@ -1925,13 +1950,15 @@
newFile(
join(projectFolderPath, 'lib', 'reexport1.dart'),
'''
- export 'source_file.dart';
+ import 'enum.dart';
+ export 'enum.dart';
+ void x(MyExportedEnum e) {}
''',
);
newFile(
join(projectFolderPath, 'lib', 'reexport2.dart'),
'''
- export 'source_file.dart';
+ export 'enum.dart';
''',
);
@@ -1939,7 +1966,7 @@
import 'reexport1.dart';
void f() {
- var a = MyExported^
+ x(MyExported^
}
''';
@@ -2265,6 +2292,57 @@
part 'main.dart';'''));
}
+ Future<void>
+ test_unimportedSymbols_isIncompleteNotSetIfBudgetNotExhausted() async {
+ final content = '''
+void f() {
+ InOtherF^
+}
+ ''';
+
+ final initialAnalysis = waitForAnalysisComplete();
+ await initialize(
+ initializationOptions: {
+ ...?defaultInitializationOptions,
+ // Set budget high to ensure it completes.
+ 'notImportedCompletionBudgetMilliseconds': 100000,
+ },
+ workspaceCapabilities:
+ withApplyEditSupport(emptyWorkspaceClientCapabilities));
+ await openFile(mainFileUri, withoutMarkers(content));
+ await initialAnalysis;
+ final res =
+ await getCompletionList(mainFileUri, positionFromMarker(content));
+
+ // Ensure we flagged that we returned everything.
+ expect(res.isIncomplete, isFalse);
+ }
+
+ Future<void> test_unimportedSymbols_isIncompleteSetIfBudgetExhausted() async {
+ final content = '''
+void f() {
+ InOtherF^
+}
+ ''';
+
+ final initialAnalysis = waitForAnalysisComplete();
+ await initialize(
+ initializationOptions: {
+ ...?defaultInitializationOptions,
+ // Set budget low to ensure we don't complete.
+ 'notImportedCompletionBudgetMilliseconds': 0,
+ },
+ workspaceCapabilities:
+ withApplyEditSupport(emptyWorkspaceClientCapabilities));
+ await openFile(mainFileUri, withoutMarkers(content));
+ await initialAnalysis;
+ final res =
+ await getCompletionList(mainFileUri, positionFromMarker(content));
+
+ // Ensure we flagged that we did not return everything.
+ expect(res.isIncomplete, isFalse);
+ }
+
/// This test reproduces a bug where the pathKey hash used in
/// available_declarations.dart would not change with the contents of the file
/// (as it always used 0 as the modification stamp) which would prevent
@@ -2449,6 +2527,7 @@
// Support applyEdit, but explicitly disable the suggestions.
await initialize(
initializationOptions: {
+ ...?defaultInitializationOptions,
'suggestFromUnimportedLibraries': false,
},
workspaceCapabilities:
@@ -2577,6 +2656,12 @@
}
@reflectiveTest
+class CompletionWithPreviewNotImportedCompletionsTest extends CompletionTest {
+ CompletionWithPreviewNotImportedCompletionsTest()
+ : super(previewNotImportedCompletions: true);
+}
+
+@reflectiveTest
class DartSnippetCompletionTest extends SnippetCompletionTest {
Future<void> test_snippets_class() async {
final content = '''
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index f5a74ab..9d9c88e 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -668,6 +668,10 @@
/// Whether to include 'clientRequestTime' fields in outgoing messages.
bool includeClientRequestTime = false;
+ /// Default initialization options to be used if [initialize] is not provided
+ /// options explicitly.
+ Map<String, Object?>? defaultInitializationOptions;
+
/// A stream of [NotificationMessage]s from the server that may be errors.
Stream<NotificationMessage> get errorNotificationsFromServer {
return notificationsFromServer.where(_isErrorNotification);
@@ -1489,7 +1493,8 @@
InitializeParams(
rootPath: rootPath,
rootUri: rootUri?.toString(),
- initializationOptions: initializationOptions,
+ initializationOptions:
+ initializationOptions ?? defaultInitializationOptions,
capabilities: clientCapabilities,
workspaceFolders: workspaceFolders?.map(toWorkspaceFolder).toList(),
));
diff --git a/pkg/analysis_server/test/mock_packages/flutter/lib/src/widgets/framework.dart b/pkg/analysis_server/test/mock_packages/flutter/lib/src/widgets/framework.dart
index 587cdf7..ab927f5 100644
--- a/pkg/analysis_server/test/mock_packages/flutter/lib/src/widgets/framework.dart
+++ b/pkg/analysis_server/test/mock_packages/flutter/lib/src/widgets/framework.dart
@@ -32,6 +32,8 @@
void dispose() {}
+ void initState() {}
+
void setState(VoidCallback fn) {}
}
diff --git a/pkg/analysis_server/test/protocol_server_test.dart b/pkg/analysis_server/test/protocol_server_test.dart
index 603ea68..0e72cb6 100644
--- a/pkg/analysis_server/test/protocol_server_test.dart
+++ b/pkg/analysis_server/test/protocol_server_test.dart
@@ -249,6 +249,7 @@
engine.ElementKind.LIBRARY_AUGMENTATION: ElementKind.UNKNOWN,
engine.ElementKind.NAME: ElementKind.UNKNOWN,
engine.ElementKind.NEVER: ElementKind.UNKNOWN,
+ engine.ElementKind.PART: ElementKind.COMPILATION_UNIT,
engine.ElementKind.UNIVERSE: ElementKind.UNKNOWN
});
}
diff --git a/pkg/analysis_server/test/src/cider/completion_test.dart b/pkg/analysis_server/test/src/cider/completion_test.dart
index c43ddad..b6d230e 100644
--- a/pkg/analysis_server/test/src/cider/completion_test.dart
+++ b/pkg/analysis_server/test/src/cider/completion_test.dart
@@ -475,6 +475,7 @@
Future<void> test_limitedResolution_hasPart() async {
newFile('/workspace/dart/test/lib/a.dart', r'''
+part of 'test.dart';
class A {}
''');
diff --git a/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart b/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart
index d222e07..02729db 100644
--- a/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/dart/completion_test.dart
@@ -225,6 +225,7 @@
Future<void> test_explicitTarget_method_inPart() async {
newFile(convertPath('$testPackageLibPath/part.dart'), '''
+part of 'test.dart';
extension E on String {
void m() {}
}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart
index 5e11735..4f73543 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart
@@ -505,32 +505,4 @@
}
''');
}
-
- Future<void> test_tail() async {
- await resolveTestCode(r'''
-import 'package:flutter/material.dart';
-
-class /*caret*/MyWidget extends StatelessWidget {
- @override
- Widget build(BuildContext context) {
- return Container();
- }
-}
-''');
- await assertHasAssist(r'''
-import 'package:flutter/material.dart';
-
-class MyWidget extends StatefulWidget {
- @override
- State<MyWidget> createState() => _MyWidgetState();
-}
-
-class _MyWidgetState extends State<MyWidget> {
- @override
- Widget build(BuildContext context) {
- return Container();
- }
-}
-''');
- }
}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateless_widget_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateless_widget_test.dart
new file mode 100644
index 0000000..f50beb7
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateless_widget_test.dart
@@ -0,0 +1,850 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'assist_processor.dart';
+
+void main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(FlutterConvertToStatelessWidgetTest);
+ });
+}
+
+@reflectiveTest
+class FlutterConvertToStatelessWidgetTest extends AssistProcessorTest {
+ @override
+ AssistKind get kind => DartAssistKind.FLUTTER_CONVERT_TO_STATELESS_WIDGET;
+
+ @override
+ void setUp() {
+ super.setUp();
+ writeTestPackageConfig(
+ flutter: true,
+ );
+ }
+
+ Future<void> test_comment() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+ const MyWidget();
+
+ @override
+ State<MyWidget> createState() => _MyWidgetState();
+
+ /// some m
+ void m() {}
+}
+
+/// comment for state
+class _MyWidgetState extends State<MyWidget> {
+ // something for a
+ final bool a = false;
+
+ // another for b
+ final bool b = true;
+
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+
+ /// some m
+ void m() {}
+}
+''');
+ await assertHasAssist('''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ const MyWidget();
+
+ // something for a
+ final bool a = false;
+
+ // another for b
+ final bool b = true;
+
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+
+ /// some m
+ void m() {}
+}
+''');
+ }
+
+ Future<void> test_default_override() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+ const MyWidget({super.key});
+
+ @override
+ State<MyWidget> createState() => _MyWidgetState();
+}
+
+class _MyWidgetState extends State<MyWidget> {
+
+ @override
+ void initState() {
+ // some comment
+ super.initState();
+ }
+
+ @override
+ void dispose() => super.dispose();
+
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+}
+''');
+ await assertHasAssist(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ const MyWidget({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+}
+''');
+ }
+
+ Future<void> test_empty() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+ const MyWidget({super.key});
+
+ @override
+ State<MyWidget> createState() => _MyWidgetState();
+}
+
+class _MyWidgetState extends State<MyWidget> {
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+}
+''');
+ await assertHasAssist(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ const MyWidget({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+}
+''');
+ }
+
+ Future<void> test_fields() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+ static String staticField1 = '';
+ final String instanceField1;
+ final String instanceField2;
+ String instanceField3 = '';
+ static String staticField2 = '';
+ static String staticField3 = '';
+
+ MyWidget(this.instanceField1) : instanceField2 = '' {
+ instanceField3 = '';
+ }
+
+ @override
+ State<MyWidget> createState() => _MyWidgetState();
+}
+
+class _MyWidgetState extends State<MyWidget> {
+ String instanceField4 = '';
+
+ String instanceField5 = '';
+
+ @override
+ Widget build(BuildContext context) {
+ instanceField4 = widget.instanceField1;
+ return Row(
+ children: [
+ Text(widget.instanceField1),
+ Text(widget.instanceField2),
+ Text(widget.instanceField3),
+ Text(instanceField4),
+ Text(instanceField5),
+ Text(MyWidget.staticField1),
+ Text(MyWidget.staticField2),
+ Text(MyWidget.staticField3),
+ ],
+ );
+ }
+}
+''');
+ await assertHasAssist(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ static String staticField1 = '';
+ final String instanceField1;
+ final String instanceField2;
+ String instanceField3 = '';
+ static String staticField2 = '';
+ static String staticField3 = '';
+
+ MyWidget(this.instanceField1) : instanceField2 = '' {
+ instanceField3 = '';
+ }
+
+ String instanceField4 = '';
+
+ String instanceField5 = '';
+
+ @override
+ Widget build(BuildContext context) {
+ instanceField4 = instanceField1;
+ return Row(
+ children: [
+ Text(instanceField1),
+ Text(instanceField2),
+ Text(instanceField3),
+ Text(instanceField4),
+ Text(instanceField5),
+ Text(staticField1),
+ Text(staticField2),
+ Text(staticField3),
+ ],
+ );
+ }
+}
+''');
+ }
+
+ Future<void> test_getters() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+ @override
+ State<MyWidget> createState() => _MyWidgetState();
+
+ static String get staticGetter1 => '';
+
+ static String get staticGetter2 => '';
+}
+
+class _MyWidgetState extends State<MyWidget> {
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ children: [
+ Text(MyWidget.staticGetter1),
+ Text(MyWidget.staticGetter2),
+ Text(instanceGetter1),
+ Text(instanceGetter2),
+ ],
+ );
+ }
+
+ String get instanceGetter1 => '';
+
+ String get instanceGetter2 => '';
+}
+''');
+ await assertHasAssist(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ children: [
+ Text(staticGetter1),
+ Text(staticGetter2),
+ Text(instanceGetter1),
+ Text(instanceGetter2),
+ ],
+ );
+ }
+
+ String get instanceGetter1 => '';
+
+ String get instanceGetter2 => '';
+
+ static String get staticGetter1 => '';
+
+ static String get staticGetter2 => '';
+}
+''');
+ }
+
+ Future<void> test_methods() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+ static String staticField = '';
+ final String instanceField1;
+
+ MyWidget(this.instanceField1);
+
+ @override
+ State<MyWidget> createState() => _MyWidgetState();
+
+ static void staticMethod1() {
+ print('static 1');
+ }
+
+ static void staticMethod2() {
+ print('static 2');
+ }
+}
+
+class _MyWidgetState extends State<MyWidget> {
+ String instanceField2 = '';
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ children: [
+ Text(widget.instanceField1),
+ Text(instanceField2),
+ Text(MyWidget.staticField),
+ ],
+ );
+ }
+
+ void instanceMethod1() {
+ instanceMethod1();
+ instanceMethod2();
+ MyWidget.staticMethod1();
+ }
+
+ void instanceMethod2() {
+ print('instance 2');
+ }
+}
+''');
+ await assertHasAssist(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ static String staticField = '';
+ final String instanceField1;
+
+ MyWidget(this.instanceField1);
+
+ String instanceField2 = '';
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ children: [
+ Text(instanceField1),
+ Text(instanceField2),
+ Text(staticField),
+ ],
+ );
+ }
+
+ void instanceMethod1() {
+ instanceMethod1();
+ instanceMethod2();
+ staticMethod1();
+ }
+
+ void instanceMethod2() {
+ print('instance 2');
+ }
+
+ static void staticMethod1() {
+ print('static 1');
+ }
+
+ static void staticMethod2() {
+ print('static 2');
+ }
+}
+''');
+ }
+
+ Future<void> test_notClass() async {
+ await resolveTestCode('''
+import 'package:flutter/material.dart';
+/*caret*/void f() {}
+''');
+ await assertNoAssist();
+ }
+
+ Future<void> test_notStatefulWidget() async {
+ await resolveTestCode('''
+import 'package:flutter/material.dart';
+class /*caret*/MyWidget extends AppBar {
+ MyWidget({super.key});
+}
+''');
+ await assertNoAssist();
+ }
+
+ Future<void> test_notWidget() async {
+ await resolveTestCode('''
+import 'package:flutter/material.dart';
+class /*caret*/MyWidget {}
+''');
+ await assertNoAssist();
+ }
+
+ Future<void> test_override() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+ const MyWidget({super.key});
+
+ @override
+ State<MyWidget> createState() => _MyWidgetState();
+}
+
+class _MyWidgetState extends State<MyWidget> {
+
+ @override
+ void initState() {
+ print('');
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+}
+''');
+ await assertNoAssist();
+ }
+
+ Future<void> test_public() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+ const MyWidget({super.key});
+
+ @override
+ State<MyWidget> createState() => MyWidgetState();
+}
+
+class MyWidgetState extends State<MyWidget> {
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+}
+''');
+ await assertNoAssist();
+ }
+
+ Future<void> test_simple() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+ final String aaa;
+ final String $bbb;
+
+ const MyWidget(this.aaa, this.$bbb);
+
+ @override
+ State<MyWidget> createState() => _MyWidgetState();
+}
+
+class _MyWidgetState extends State<MyWidget> {
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ children: [
+ Text(widget.aaa),
+ Text(widget.$bbb),
+ Text('${widget.aaa}'),
+ Text('${widget.$bbb}'),
+ ],
+ );
+ }
+}
+''');
+ await assertHasAssist(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ final String aaa;
+ final String $bbb;
+
+ const MyWidget(this.aaa, this.$bbb);
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ children: [
+ Text(aaa),
+ Text($bbb),
+ Text('$aaa'),
+ Text('${$bbb}'),
+ ],
+ );
+ }
+}
+''');
+ }
+
+ Future<void> test_state_first() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class _MyWidgetState extends State<MyWidget> {
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ children: [
+ Text(widget.aaa),
+ Text(widget.$bbb),
+ Text('${widget.aaa}'),
+ Text('${widget.$bbb}'),
+ ],
+ );
+ }
+}
+
+class /*caret*/MyWidget extends StatefulWidget {
+ final String aaa;
+ final String $bbb;
+
+ const MyWidget(this.aaa, this.$bbb);
+
+ @override
+ State<MyWidget> createState() => _MyWidgetState();
+}
+''');
+ await assertHasAssist(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget extends StatelessWidget {
+ final String aaa;
+ final String $bbb;
+
+ const MyWidget(this.aaa, this.$bbb);
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ children: [
+ Text(aaa),
+ Text($bbb),
+ Text('$aaa'),
+ Text('${$bbb}'),
+ ],
+ );
+ }
+}
+''');
+ }
+
+ Future<void> test_state_methodInvocation() async {
+ await resolveTestCode('''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+ const MyWidget({super.key});
+
+ @override
+ State<MyWidget> createState() => _MyWidgetState();
+}
+
+class _MyWidgetState extends State<MyWidget> {
+ @override
+ Widget build(BuildContext context) {
+ setState(() {});
+ return Container();
+ }
+}
+''');
+ await assertNoAssist();
+ }
+
+ Future<void> test_state_override() async {
+ await resolveTestCode('''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+ const MyWidget({super.key});
+
+ @override
+ State<MyWidget> createState() => _MyWidgetState();
+}
+
+class _MyWidgetState extends State<MyWidget> {
+ @override
+ Widget build(BuildContext context) {
+ setState(() {});
+ return Container();
+ }
+}
+''');
+ await assertNoAssist();
+ }
+
+ Future<void> test_state_used_anotherWidget() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/FirstWidget extends StatefulWidget {
+ const FirstWidget({super.key});
+
+ @override
+ createState() => _MyWidgetState();
+}
+
+class SecondWidget extends StatefulWidget {
+ const SecondWidget({super.key});
+
+ @override
+ createState() => _MyWidgetState();
+}
+
+class _MyWidgetState extends State<FirstWidget> {
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+}
+''');
+ await assertNoAssist();
+ }
+
+ Future<void> test_state_used_createState() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+ const MyWidget({super.key});
+
+ @override
+ State<MyWidget> createState() => _MyWidgetState();
+
+ State<MyWidget> another() => createState();
+}
+
+class _MyWidgetState extends State<MyWidget> {
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+}
+''');
+ await assertNoAssist();
+ }
+
+ Future<void> test_state_used_createState_return_stateClass() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+ const MyWidget({super.key});
+
+ @override
+ _MyWidgetState createState() => _MyWidgetState();
+
+ _MyWidgetState another() => createState();
+}
+
+class _MyWidgetState extends State<MyWidget> {
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+}
+''');
+ await assertNoAssist();
+ }
+
+ Future<void> test_state_used_instanceCreationExpression() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+ const MyWidget({super.key});
+
+ @override
+ State<MyWidget> createState() => _MyWidgetState();
+
+ State<MyWidget> another() => _MyWidgetState();
+}
+
+class _MyWidgetState extends State<MyWidget> {
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+}
+''');
+ await assertNoAssist();
+ }
+
+ Future<void> test_static_field() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+ const MyWidget({super.key});
+
+ @override
+ State<MyWidget> createState() => _MyWidgetState();
+}
+
+class _MyWidgetState extends State<MyWidget> {
+ static var field = 1;
+
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+}
+''');
+ await assertNoAssist();
+ }
+
+ Future<void> test_static_method() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget extends StatefulWidget {
+ const MyWidget({super.key});
+
+ @override
+ State<MyWidget> createState() => _MyWidgetState();
+}
+
+class _MyWidgetState extends State<MyWidget> {
+
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+
+ static void staticMethod1() {
+ print('static 1');
+ }
+}
+''');
+ await assertNoAssist();
+ }
+
+ Future<void> test_typeParam_bound() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget<T extends String> extends StatefulWidget {
+ @override
+ State<MyWidget<T>> createState() => _MyWidgetState<T>();
+}
+
+class _MyWidgetState<T extends String> extends State<MyWidget<T>> {
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+}
+''');
+ await assertHasAssist(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget<T extends String> extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+}
+''');
+ }
+
+ Future<void> test_typeParam_different_bound() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget<T extends String> extends StatefulWidget {
+ @override
+ State createState() => _MyWidgetState();
+}
+
+class _MyWidgetState<T extends List> extends State<MyWidget> {
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+}
+''');
+ await assertNoAssist();
+ }
+
+ Future<void> test_typeParam_different_name() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget<T> extends StatefulWidget {
+ @override
+ State<MyWidget<T>> createState() => _MyWidgetState<T>();
+}
+
+class _MyWidgetState<S> extends State<MyWidget<S>> {
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+}
+''');
+ await assertNoAssist();
+ }
+
+ Future<void> test_typeParam_empty() async {
+ await resolveTestCode(r'''
+import 'package:flutter/material.dart';
+
+class /*caret*/MyWidget<T> extends StatefulWidget {
+ @override
+ State<MyWidget<T>> createState() => _MyWidgetState<T>();
+}
+
+class _MyWidgetState<T> extends State<MyWidget<T>> {
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+}
+''');
+ await assertHasAssist(r'''
+import 'package:flutter/material.dart';
+
+class MyWidget<T> extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return Container();
+ }
+}
+''');
+ }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
index d32b3c0..4067547 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
@@ -48,6 +48,8 @@
import 'flutter_convert_to_children_test.dart' as flutter_convert_to_children;
import 'flutter_convert_to_stateful_widget_test.dart'
as flutter_convert_to_stateful_widget;
+import 'flutter_convert_to_stateless_widget_test.dart'
+ as flutter_convert_to_stateless_widget;
import 'flutter_move_down_test.dart' as flutter_move_down;
import 'flutter_move_up_test.dart' as flutter_move_up;
import 'flutter_remove_widget_test.dart' as flutter_remove_widget;
@@ -130,6 +132,7 @@
exchange_operands.main();
flutter_convert_to_children.main();
flutter_convert_to_stateful_widget.main();
+ flutter_convert_to_stateless_widget.main();
flutter_move_down.main();
flutter_move_up.main();
flutter_remove_widget.main();
diff --git a/pkg/analysis_server/test/stress/replay/replay.dart b/pkg/analysis_server/test/stress/replay/replay.dart
index fbfe0e1..8988b18 100644
--- a/pkg/analysis_server/test/stress/replay/replay.dart
+++ b/pkg/analysis_server/test/stress/replay/replay.dart
@@ -222,7 +222,7 @@
);
var token = scanner.tokenize();
// TODO(brianwilkerson) Randomize. Sometimes add zero (0) as a break point.
- while (token.type != TokenType.EOF) {
+ while (!token.isEof) {
// TODO(brianwilkerson) Break inside comments?
// Token comment = token.precedingComments;
var offset = token.offset;
diff --git a/pkg/analysis_server/tool/code_completion/visitors.dart b/pkg/analysis_server/tool/code_completion/visitors.dart
index 0e36d73..2cb870b 100644
--- a/pkg/analysis_server/tool/code_completion/visitors.dart
+++ b/pkg/analysis_server/tool/code_completion/visitors.dart
@@ -374,7 +374,7 @@
@override
void visitExportDirective(ExportDirective node) {
- safelyRecordKeywordCompletion(node.keyword);
+ safelyRecordKeywordCompletion(node.exportKeyword);
super.visitExportDirective(node);
}
@@ -494,7 +494,7 @@
@override
void visitImportDirective(ImportDirective node) {
- safelyRecordKeywordCompletion(node.keyword);
+ safelyRecordKeywordCompletion(node.importKeyword);
safelyRecordKeywordCompletion(node.asKeyword);
safelyRecordKeywordCompletion(node.deferredKeyword);
super.visitImportDirective(node);
diff --git a/pkg/analysis_server/tool/lsp_spec/generate_all.dart b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
index afe9147..e01e49a 100644
--- a/pkg/analysis_server/tool/lsp_spec/generate_all.dart
+++ b/pkg/analysis_server/tool/lsp_spec/generate_all.dart
@@ -298,12 +298,24 @@
// These fields have short-ish names because they're on the payload
// for all suggestion-set backed completions.
field('file', type: 'string'),
- field('offset', type: 'int'),
field('libId', type: 'int'),
- field('displayUri', type: 'string'),
- field('rOffset', type: 'int'), // replacementOffset
- field('iLength', type: 'int'), // insertLength
- field('rLength', type: 'int'), // replacementLength
+ ],
+ baseType: 'CompletionItemResolutionInfo',
+ ),
+ interface(
+ 'DartNotImportedCompletionResolutionInfo',
+ [
+ field(
+ 'file',
+ type: 'string',
+ comment: 'The file where the completion is being inserted.\n\n'
+ 'This is used to compute where to add the import.',
+ ),
+ field(
+ 'libraryUri',
+ type: 'string',
+ comment: 'The URI to be imported if this completion is selected.',
+ ),
],
baseType: 'CompletionItemResolutionInfo',
),
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index c089234..c84f8ed 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 4.3.0-dev
+* Deprecated `Directive.keyword`, use corresponding `xyzToken` in specific directives.
+* Deprecated `LibraryElement.parts`, use `parts2` instead.
+
## 4.2.0
* Update SDK constraints to `>=2.17.0 <3.0.0`.
* Deprecated `ImportDirective.COMPARATOR`, use appropriate custom logic, if necessary.
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 5f2d688..070e789 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -1525,6 +1525,7 @@
/// Return the token representing the keyword that introduces this directive
/// ('import', 'export', 'library' or 'part').
+ @Deprecated('Use specific xyzToken instead')
Token get keyword;
}
@@ -1704,6 +1705,9 @@
abstract class ExportDirective implements NamespaceDirective {
@override
ExportElement? get element;
+
+ /// The token representing the 'export' keyword.
+ Token get exportKeyword;
}
/// A node that represents an expression.
@@ -2876,6 +2880,9 @@
@override
ImportElement? get element;
+ /// The token representing the 'import' keyword.
+ Token get importKeyword;
+
/// Return the prefix to be used with the imported names, or `null` if the
/// imported names are not prefixed.
SimpleIdentifier? get prefix;
@@ -4532,6 +4539,7 @@
/// Return the content of the [uri], or `null` if the AST structure has not
/// been resolved, or if the [uri] has a string interpolation.
+ /// TODO(scheglov) Deprecate and remove it.
String? get uriContent;
/// Return the element associated with the [uri] of this directive, or `null`
@@ -4540,9 +4548,11 @@
///
/// Examples of the latter case include a directive that contains an invalid
/// URL or a URL that does not exist.
+ /// TODO(scheglov) Deprecate and remove it.
Element? get uriElement;
/// Return the source to which the [uri] was resolved.
+ /// TODO(scheglov) Deprecate and remove it.
Source? get uriSource;
}
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 4291006..6f64355 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -932,23 +932,25 @@
static const ElementKind PARAMETER =
ElementKind('PARAMETER', 21, "parameter");
- static const ElementKind PREFIX = ElementKind('PREFIX', 22, "import prefix");
+ static const ElementKind PART = ElementKind('PART', 22, "part");
- static const ElementKind SETTER = ElementKind('SETTER', 23, "setter");
+ static const ElementKind PREFIX = ElementKind('PREFIX', 23, "import prefix");
+
+ static const ElementKind SETTER = ElementKind('SETTER', 24, "setter");
static const ElementKind TOP_LEVEL_VARIABLE =
- ElementKind('TOP_LEVEL_VARIABLE', 24, "top level variable");
+ ElementKind('TOP_LEVEL_VARIABLE', 25, "top level variable");
static const ElementKind FUNCTION_TYPE_ALIAS =
- ElementKind('FUNCTION_TYPE_ALIAS', 25, "function type alias");
+ ElementKind('FUNCTION_TYPE_ALIAS', 26, "function type alias");
static const ElementKind TYPE_PARAMETER =
- ElementKind('TYPE_PARAMETER', 26, "type parameter");
+ ElementKind('TYPE_PARAMETER', 27, "type parameter");
static const ElementKind TYPE_ALIAS =
- ElementKind('TYPE_ALIAS', 27, "type alias");
+ ElementKind('TYPE_ALIAS', 28, "type alias");
- static const ElementKind UNIVERSE = ElementKind('UNIVERSE', 28, "<universe>");
+ static const ElementKind UNIVERSE = ElementKind('UNIVERSE', 29, "<universe>");
static const List<ElementKind> values = [
CLASS,
@@ -970,6 +972,7 @@
NAME,
NEVER,
PARAMETER,
+ PART,
PREFIX,
SETTER,
TOP_LEVEL_VARIABLE,
@@ -1071,6 +1074,8 @@
R? visitParameterElement(ParameterElement element);
+ R? visitPartElement(PartElement element);
+
R? visitPrefixElement(PrefixElement element);
R? visitPropertyAccessorElement(PropertyAccessorElement element);
@@ -1388,8 +1393,12 @@
/// Return a list containing all of the compilation units that are included in
/// this library using a `part` directive. This does not include the defining
/// compilation unit that contains the `part` directives.
+ @Deprecated('Use parts2 instead')
List<CompilationUnitElement> get parts;
+ /// Returns the list of `part` directives of this library.
+ List<PartElement> get parts2;
+
/// The public [Namespace] of this library.
Namespace get publicNamespace;
@@ -1656,6 +1665,30 @@
});
}
+/// A 'part' directive within a library.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class PartElement implements _ExistingElement {}
+
+/// [PartElementWithSource] that represents a valid part of this library.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class PartElementWithPart implements PartElementWithSource {
+ /// The part [CompilationUnitElement] referenced by [uriSource].
+ CompilationUnitElement get includedUnit;
+}
+
+/// [PartElement] with a relative URI that resolves to a [Source].
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class PartElementWithSource implements PartElement {
+ /// The string value of the URI.
+ String get relativeUriString;
+
+ /// The source to which [relativeUriString] resolves.
+ Source get uriSource;
+}
+
/// A prefix used to import one or more libraries into another library.
///
/// Clients may not extend, implement or mix-in this class.
diff --git a/pkg/analyzer/lib/dart/element/visitor.dart b/pkg/analyzer/lib/dart/element/visitor.dart
index ace3ca2..86e4839 100644
--- a/pkg/analyzer/lib/dart/element/visitor.dart
+++ b/pkg/analyzer/lib/dart/element/visitor.dart
@@ -167,6 +167,9 @@
visitLocalElement(element);
@override
+ R? visitPartElement(PartElement element) => visitElement(element);
+
+ @override
R? visitPrefixElement(PrefixElement element) => visitElement(element);
@override
@@ -318,6 +321,12 @@
}
@override
+ R? visitPartElement(PartElement element) {
+ element.visitChildren(this);
+ return null;
+ }
+
+ @override
R? visitPrefixElement(PrefixElement element) {
element.visitChildren(this);
return null;
@@ -422,6 +431,9 @@
R? visitParameterElement(ParameterElement element) => null;
@override
+ R? visitPartElement(PartElement element) => null;
+
+ @override
R? visitPrefixElement(PrefixElement element) => null;
@override
@@ -513,6 +525,9 @@
R? visitParameterElement(ParameterElement element) => _throw(element);
@override
+ R? visitPartElement(PartElement element) => _throw(element);
+
+ @override
R? visitPrefixElement(PrefixElement element) => _throw(element);
@override
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index cb70639..b692981 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -85,7 +85,7 @@
/// TODO(scheglov) Clean up the list of implicitly analyzed files.
class AnalysisDriver implements AnalysisDriverGeneric {
/// The version of data format, should be incremented on every format change.
- static const int DATA_VERSION = 227;
+ static const int DATA_VERSION = 228;
/// The number of exception contexts allowed to write. Once this field is
/// zero, we stop writing any new exception contexts in this process.
diff --git a/pkg/analyzer/lib/src/dart/analysis/index.dart b/pkg/analyzer/lib/src/dart/analysis/index.dart
index 8406aee..8d74735 100644
--- a/pkg/analyzer/lib/src/dart/analysis/index.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/index.dart
@@ -793,9 +793,9 @@
@override
void visitPartDirective(PartDirective node) {
- var element = node.element as CompilationUnitElement?;
- if (element?.source != null) {
- recordUriReference(element, node.uri);
+ final partElement = node.element;
+ if (partElement is PartElementWithPart) {
+ recordUriReference(partElement.includedUnit, node.uri);
}
super.visitPartDirective(node);
}
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 33a041e..1e61c76 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -805,8 +805,14 @@
}) {
StringLiteral partUri = directive.uri;
- final partState = _library.parts[partIndexes.directive++];
+ final index = partIndexes.directive++;
+
+ final partState = _library.parts[index];
directive.uriSource = partState.includedSource;
+
+ final partElement = _libraryElement.parts2[index];
+ directive.element = partElement;
+
if (partState is! PartDirectiveWithUri) {
libraryErrorReporter.reportErrorForNode(
CompileTimeErrorCode.URI_WITH_INTERPOLATION,
@@ -815,9 +821,7 @@
return;
}
- // TODO(scheglov) This should not be necessary if we build `PartElement`
- // for every `part` directive.
- if (partIndexes.element >= _libraryElement.parts.length) {
+ if (partState is! PartDirectiveWithFile) {
final errorCode = partState.uri.isValid
? CompileTimeErrorCode.URI_DOES_NOT_EXIST
: CompileTimeErrorCode.INVALID_URI;
@@ -828,15 +832,6 @@
);
return;
}
-
- if (partState is! PartDirectiveWithFile) {
- libraryErrorReporter.reportErrorForNode(
- CompileTimeErrorCode.URI_DOES_NOT_EXIST,
- directive.uri,
- [partState.uri.relativeUriStr],
- );
- return;
- }
final includedFile = partState.includedFile;
final includedKind = includedFile.kind;
@@ -887,10 +882,11 @@
return;
}
+ // TODO(scheglov) Unsafe.
var partUnit = units[includedFile]!;
- var partElement = _libraryElement.parts[partIndexes.element++];
- partUnit.element = partElement;
- directive.element = partElement;
+ if (partElement is PartElementWithPart) {
+ partUnit.element = partElement.includedUnit;
+ }
final partSource = includedKind.file.source;
directive.uriSource = partSource;
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index 0ef2a0e..b7b769b 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -125,7 +125,6 @@
var librariesLoaded = 0;
var librariesLinked = 0;
var librariesLinkedTimer = Stopwatch();
- var inputsTimer = Stopwatch();
var bytesGet = 0;
var bytesPut = 0;
@@ -176,54 +175,12 @@
cycle.libraries.map((e) => e.file.path).toSet(),
);
- inputsTimer.start();
- var inputLibraries = <LinkInputLibrary>[];
- for (var library in cycle.libraries) {
- var librarySource = library.file.source;
-
- var inputUnits = <LinkInputUnit>[];
- var partIndex = -1;
- for (var file in library.files) {
- var isSynthetic = !file.exists;
- var unit = file.parse();
-
- performance.getDataInt('parseCount').increment();
- performance.getDataInt('parseLength').add(unit.length);
-
- String? partUriStr;
- if (partIndex >= 0) {
- partUriStr = library.file.unlinked2.parts[partIndex].uri;
- }
- partIndex++;
-
- inputUnits.add(
- LinkInputUnit(
- // TODO(scheglov) bad, group part data
- partDirectiveIndex: partIndex - 1,
- partUriStr: partUriStr,
- source: file.source,
- sourceContent: file.content,
- isSynthetic: isSynthetic,
- unit: unit,
- ),
- );
- }
-
- inputLibraries.add(
- LinkInputLibrary(
- source: librarySource,
- units: inputUnits,
- ),
- );
- }
- inputsTimer.stop();
-
LinkResult linkResult;
try {
- linkResult = await link2(
+ linkResult = await link(
elementFactory: elementFactory,
performance: OperationPerformanceImpl('link'),
- inputLibraries: inputLibraries,
+ inputLibraries: cycle.libraries,
macroExecutor: macroExecutor,
);
librariesLinked += cycle.libraries.length;
@@ -290,7 +247,6 @@
logger.writeln(
'[librariesTotal: $librariesTotal]'
'[librariesLoaded: $librariesLoaded]'
- '[inputsTimer: ${inputsTimer.elapsedMilliseconds} ms]'
'[librariesLinked: $librariesLinked]'
'[librariesLinkedTimer: ${librariesLinkedTimer.elapsedMilliseconds} ms]'
'[bytesGet: $bytesGet][bytesPut: $bytesPut]',
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 463df80..d56a2cb 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -910,8 +910,9 @@
Token get endToken => semicolon;
@override
- Token get firstTokenAfterCommentAndMetadata => keyword;
+ Token get firstTokenAfterCommentAndMetadata => importKeyword;
+ @Deprecated('Use specific xyzToken instead')
@override
Token get keyword => importKeyword;
@@ -922,7 +923,7 @@
@override
ChildEntities get _childEntities => super._childEntities
- ..addToken('keyword', keyword)
+ ..addToken('importKeyword', importKeyword)
..addToken('augmentKeyword', augmentKeyword)
..addNode('uri', uri)
..addToken('semicolon', semicolon);
@@ -3250,7 +3251,8 @@
/// A node that represents a directive.
///
/// directive ::=
-/// [ExportDirective]
+/// [AugmentationImportDirective]
+/// | [ExportDirective]
/// | [ImportDirective]
/// | [LibraryDirective]
/// | [PartDirective]
@@ -3763,6 +3765,9 @@
/// [Annotation] 'export' [StringLiteral] [Combinator]* ';'
class ExportDirectiveImpl extends NamespaceDirectiveImpl
implements ExportDirective {
+ @override
+ Token exportKeyword;
+
/// Initialize a newly created export directive. Either or both of the
/// [comment] and [metadata] can be `null` if the directive does not have the
/// corresponding attribute. The list of [combinators] can be `null` if there
@@ -3770,7 +3775,7 @@
ExportDirectiveImpl(
super.comment,
super.metadata,
- super.keyword,
+ this.exportKeyword,
super.libraryUri,
super.configurations,
super.combinators,
@@ -3780,13 +3785,20 @@
ExportElement? get element => super.element as ExportElement?;
@override
+ Token get firstTokenAfterCommentAndMetadata => exportKeyword;
+
+ @Deprecated('Use specific xyzToken instead')
+ @override
+ Token get keyword => exportKeyword;
+
+ @override
LibraryElement? get uriElement {
return element?.exportedLibrary;
}
@override
ChildEntities get _childEntities => super._childEntities
- ..addToken('keyword', keyword)
+ ..addToken('exportKeyword', exportKeyword)
..addNode('uri', uri)
..addNodeList('combinators', combinators)
..addToken('semicolon', semicolon);
@@ -6369,6 +6381,9 @@
// [Combinator]* ';'
class ImportDirectiveImpl extends NamespaceDirectiveImpl
implements ImportDirective {
+ @override
+ Token importKeyword;
+
/// The token representing the 'deferred' keyword, or `null` if the imported
/// is not deferred.
@override
@@ -6392,7 +6407,7 @@
ImportDirectiveImpl(
CommentImpl? comment,
List<Annotation>? metadata,
- Token keyword,
+ this.importKeyword,
StringLiteralImpl libraryUri,
List<Configuration>? configurations,
this.deferredKeyword,
@@ -6400,8 +6415,8 @@
this._prefix,
List<Combinator>? combinators,
Token semicolon)
- : super(comment, metadata, keyword, libraryUri, configurations,
- combinators, semicolon) {
+ : super(comment, metadata, libraryUri, configurations, combinators,
+ semicolon) {
_becomeParentOf(_prefix);
}
@@ -6409,6 +6424,13 @@
ImportElement? get element => super.element as ImportElement?;
@override
+ Token get firstTokenAfterCommentAndMetadata => importKeyword;
+
+ @Deprecated('Use specific xyzToken instead')
+ @override
+ Token get keyword => importKeyword;
+
+ @override
SimpleIdentifierImpl? get prefix => _prefix;
set prefix(SimpleIdentifier? identifier) {
@@ -6422,7 +6444,7 @@
@override
ChildEntities get _childEntities => super._childEntities
- ..addToken('keyword', keyword)
+ ..addToken('importKeyword', importKeyword)
..addNode('uri', uri)
..addToken('deferredKeyword', deferredKeyword)
..addToken('asKeyword', asKeyword)
@@ -7265,6 +7287,7 @@
@override
Token get firstTokenAfterCommentAndMetadata => libraryKeyword;
+ @Deprecated('Use specific xyzToken instead')
@override
Token get keyword => libraryKeyword;
@@ -7318,6 +7341,7 @@
@override
Token get firstTokenAfterCommentAndMetadata => libraryKeyword;
+ @Deprecated('Use specific xyzToken instead')
@override
Token get keyword => libraryKeyword;
@@ -8168,10 +8192,6 @@
/// | [ImportDirective]
abstract class NamespaceDirectiveImpl extends UriBasedDirectiveImpl
implements NamespaceDirective {
- /// The token representing the 'import' or 'export' keyword.
- @override
- Token keyword;
-
/// The configurations used to control which library will actually be loaded
/// at run-time.
final NodeListImpl<Configuration> _configurations = NodeListImpl._();
@@ -8194,14 +8214,12 @@
/// corresponding attribute. The list of [combinators] can be `null` if there
/// are no combinators.
NamespaceDirectiveImpl(
- CommentImpl? comment,
- List<Annotation>? metadata,
- this.keyword,
- StringLiteralImpl libraryUri,
+ super.comment,
+ super.metadata,
+ super.libraryUri,
List<Configuration>? configurations,
List<Combinator>? combinators,
- this.semicolon)
- : super(comment, metadata, libraryUri) {
+ this.semicolon) {
_configurations._initialize(this, configurations);
_combinators._initialize(this, combinators);
}
@@ -8216,9 +8234,6 @@
Token get endToken => semicolon;
@override
- Token get firstTokenAfterCommentAndMetadata => keyword;
-
- @override
LibraryElement? get uriElement;
}
@@ -8757,11 +8772,18 @@
@override
Token get firstTokenAfterCommentAndMetadata => partKeyword;
+ @Deprecated('Use specific xyzToken instead')
@override
Token get keyword => partKeyword;
@override
- CompilationUnitElement? get uriElement => element as CompilationUnitElement?;
+ CompilationUnitElement? get uriElement {
+ final partElement = element as PartElement?;
+ if (partElement is PartElementWithPart) {
+ return partElement.includedUnit;
+ }
+ return null;
+ }
@override
ChildEntities get _childEntities => super._childEntities
@@ -8813,6 +8835,7 @@
@override
Token get firstTokenAfterCommentAndMetadata => partKeyword;
+ @Deprecated('Use specific xyzToken instead')
@override
Token get keyword => partKeyword;
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 46b2fb6..f1eb7bf 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -167,7 +167,7 @@
return isEqualNodes(
node.documentationComment, other.documentationComment) &&
_isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.keyword, other.keyword) &&
+ isEqualTokens(node.importKeyword, other.importKeyword) &&
isEqualNodes(node.uri, other.uri) &&
isEqualTokens(node.semicolon, other.semicolon);
}
@@ -468,7 +468,7 @@
return isEqualNodes(
node.documentationComment, other.documentationComment) &&
_isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.keyword, other.keyword) &&
+ isEqualTokens(node.exportKeyword, other.exportKeyword) &&
isEqualNodes(node.uri, other.uri) &&
_isEqualNodeLists(node.combinators, other.combinators) &&
isEqualTokens(node.semicolon, other.semicolon);
@@ -760,7 +760,7 @@
return isEqualNodes(
node.documentationComment, other.documentationComment) &&
_isEqualNodeLists(node.metadata, other.metadata) &&
- isEqualTokens(node.keyword, other.keyword) &&
+ isEqualTokens(node.importKeyword, other.importKeyword) &&
isEqualNodes(node.uri, other.uri) &&
_isEqualNodeLists(node.configurations, other.configurations) &&
isEqualTokens(node.deferredKeyword, other.deferredKeyword) &&
@@ -1481,7 +1481,7 @@
// Fasta scanner reports unterminated string literal errors
// and generates a synthetic string token with non-zero length.
// Because of this, check for length > 0 rather than !isSynthetic.
- if (endToken.type == TokenType.EOF || endToken.length > 0) {
+ if (endToken.isEof || endToken.length > 0) {
break;
}
endToken = endToken.previous!;
@@ -1570,7 +1570,7 @@
// Fasta scanner reports unterminated string literal errors
// and generates a synthetic string token with non-zero length.
// Because of this, check for length > 0 rather than !isSynthetic.
- if (endToken.type == TokenType.EOF || endToken.length > 0) {
+ if (endToken.isEof || endToken.length > 0) {
break;
}
endToken = endToken.previous!;
diff --git a/pkg/analyzer/lib/src/dart/element/display_string_builder.dart b/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
index 2e23aab..17553e0 100644
--- a/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/display_string_builder.dart
@@ -162,6 +162,17 @@
_writeNullability(type.nullabilitySuffix);
}
+ void writePartElement(PartElementImpl element) {
+ _write('part ');
+ if (element is PartElementWithPartImpl) {
+ _write('unit ${element.includedUnit.source.uri}');
+ } else if (element is PartElementWithSourceImpl) {
+ _write('uriSource ${element.uriSource}');
+ } else {
+ _write('<unknown>');
+ }
+ }
+
void writePrefixElement(PrefixElementImpl element) {
_write('as ');
_write(element.displayName);
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 305a074..41d1897 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -16,7 +16,6 @@
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/dart/element/type_system.dart';
import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/context/source.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/analysis/session.dart';
import 'package:analyzer/src/dart/ast/ast.dart';
@@ -48,6 +47,7 @@
import 'package:analyzer/src/summary2/macro_application_error.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/task/inference_error.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:collection/collection.dart';
/// A concrete implementation of a [ClassElement].
@@ -3730,9 +3730,8 @@
/// an entry point.
FunctionElement? _entryPoint;
- /// A list containing all of the compilation units that are included in this
- /// library using a `part` directive.
- List<CompilationUnitElement> _parts = const <CompilationUnitElement>[];
+ /// The list of `part` directives of this library.
+ List<PartElement> _parts2 = const <PartElement>[];
/// The element representing the synthetic function `loadLibrary` that is
/// defined for this library, or `null` if the element has not yet been
@@ -3930,18 +3929,27 @@
@override
String get name => super.name!;
+ @Deprecated('Use parts2 instead')
@override
- List<CompilationUnitElement> get parts => _parts;
+ List<CompilationUnitElement> get parts {
+ return _parts2
+ .whereType<PartElementWithPart>()
+ .map((partElement) => partElement.includedUnit)
+ .toList();
+ }
- /// Set the compilation units that are included in this library using a `part`
- /// directive to the given list of [parts].
- set parts(List<CompilationUnitElement> parts) {
- for (CompilationUnitElement compilationUnit in parts) {
- assert((compilationUnit as CompilationUnitElementImpl).librarySource ==
- source);
- (compilationUnit as CompilationUnitElementImpl).enclosingElement = this;
+ @override
+ List<PartElement> get parts2 => _parts2;
+
+ set parts2(List<PartElement> parts) {
+ for (final part in parts) {
+ part as PartElementImpl;
+ part.enclosingElement = this;
+ if (part is PartElementWithPartImpl) {
+ part.includedUnit.enclosingElement = this;
+ }
}
- _parts = parts;
+ _parts2 = parts;
}
@override
@@ -3984,10 +3992,10 @@
@override
List<CompilationUnitElement> get units {
- List<CompilationUnitElement> units = <CompilationUnitElement>[];
- units.add(_definingCompilationUnit);
- units.addAll(_parts);
- return units;
+ return [
+ _definingCompilationUnit,
+ ...parts2.whereType<PartElementWithPart>().map((e) => e.includedUnit),
+ ];
}
@override
@@ -4004,12 +4012,8 @@
}
ClassElement? getEnum(String name) {
- var element = _definingCompilationUnit.getEnum(name);
- if (element != null) {
- return element;
- }
- for (CompilationUnitElement part in _parts) {
- element = part.getEnum(name);
+ for (final unitElement in units) {
+ final element = unitElement.getEnum(name);
if (element != null) {
return element;
}
@@ -4024,8 +4028,14 @@
}
@override
- ClassElement? getType(String className) {
- return getTypeFromParts(className, _definingCompilationUnit, _parts);
+ ClassElement? getType(String name) {
+ for (final unitElement in units) {
+ final element = unitElement.getType(name);
+ if (element != null) {
+ return element;
+ }
+ }
+ return null;
}
/// Indicates whether it is unnecessary to report an undefined identifier
@@ -4060,8 +4070,10 @@
}
if (prefix == null && name.startsWith(r'_$')) {
- for (var partElement in parts) {
- if (partElement.isSynthetic && isGeneratedSource(partElement.source)) {
+ for (var partElement in parts2) {
+ if (partElement is PartElementWithSource &&
+ partElement is! PartElementWithPart &&
+ file_paths.isGenerated(partElement.relativeUriString)) {
return true;
}
}
@@ -4101,7 +4113,7 @@
@override
void visitChildren(ElementVisitor visitor) {
super.visitChildren(visitor);
- safelyVisitChildren(_parts, visitor);
+ safelyVisitChildren(parts2, visitor);
}
static List<PrefixElement> buildPrefixesFromImports(
@@ -5089,6 +5101,61 @@
}
}
+class PartElementImpl extends _ExistingElementImpl implements PartElement {
+ PartElementImpl() : super(null, -1);
+
+ @override
+ CompilationUnitElementImpl get enclosingUnit {
+ var enclosingLibrary = enclosingElement as LibraryElementImpl;
+ return enclosingLibrary._definingCompilationUnit;
+ }
+
+ @override
+ String get identifier => 'part';
+
+ @override
+ ElementKind get kind => ElementKind.PART;
+
+ @override
+ T? accept<T>(ElementVisitor<T> visitor) => visitor.visitPartElement(this);
+
+ @override
+ void appendTo(ElementDisplayStringBuilder builder) {
+ builder.writePartElement(this);
+ }
+}
+
+class PartElementWithPartImpl extends PartElementWithSourceImpl
+ implements PartElementWithPart {
+ @override
+ final CompilationUnitElementImpl includedUnit;
+
+ PartElementWithPartImpl({
+ required super.relativeUriString,
+ required super.uriSource,
+ required this.includedUnit,
+ });
+
+ @override
+ void visitChildren(ElementVisitor visitor) {
+ includedUnit.accept(visitor);
+ }
+}
+
+class PartElementWithSourceImpl extends PartElementImpl
+ implements PartElementWithSource {
+ @override
+ final String relativeUriString;
+
+ @override
+ final Source uriSource;
+
+ PartElementWithSourceImpl({
+ required this.relativeUriString,
+ required this.uriSource,
+ });
+}
+
/// A concrete implementation of a [PrefixElement].
class PrefixElementImpl extends _ExistingElementImpl implements PrefixElement {
/// The scope of this prefix, `null` if it has not been created yet.
diff --git a/pkg/analyzer/lib/src/dart/resolver/scope.dart b/pkg/analyzer/lib/src/dart/resolver/scope.dart
index 9a76055..84552fb 100644
--- a/pkg/analyzer/lib/src/dart/resolver/scope.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/scope.dart
@@ -180,9 +180,8 @@
/// [library].
Namespace createPublicNamespaceForLibrary(LibraryElement library) {
Map<String, Element> definedNames = HashMap<String, Element>();
- _addPublicNames(definedNames, library.definingCompilationUnit);
- for (CompilationUnitElement compilationUnit in library.parts) {
- _addPublicNames(definedNames, compilationUnit);
+ for (final unitElement in library.units) {
+ _addPublicNames(definedNames, unitElement);
}
// For libraries that import `dart:core` with a prefix, we have to add
diff --git a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
index 14775ba..55cd57b4 100644
--- a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
+++ b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
@@ -327,11 +327,11 @@
CompilationUnitElement element = node.declaredElement!;
if (element != _currentLibrary.definingCompilationUnit) {
addWithoutChecking(_currentLibrary.definingCompilationUnit);
- for (CompilationUnitElement part in _currentLibrary.parts) {
- if (element == part) {
+ for (final unitElement in _currentLibrary.units) {
+ if (element == unitElement) {
break;
}
- addWithoutChecking(part);
+ addWithoutChecking(unitElement);
}
}
for (CompilationUnitMember member in node.declarations) {
diff --git a/pkg/analyzer/lib/src/error/todo_finder.dart b/pkg/analyzer/lib/src/error/todo_finder.dart
index b3d3b24..bed283d 100644
--- a/pkg/analyzer/lib/src/error/todo_finder.dart
+++ b/pkg/analyzer/lib/src/error/todo_finder.dart
@@ -42,7 +42,7 @@
///
/// @param token the head of the list of tokens being searched
void _gatherTodoComments(Token? token, LineInfo lineInfo) {
- while (token != null && token.type != TokenType.EOF) {
+ while (token != null && !token.isEof) {
Token? commentToken = token.precedingComments;
while (commentToken != null) {
if (commentToken.type == TokenType.SINGLE_LINE_COMMENT ||
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart b/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart
index 38aa374..e81a7dc 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart
@@ -7,6 +7,12 @@
static const int genericFunctionElement = 1;
}
+enum PartElementKind {
+ withPart,
+ withSource,
+ withNothing,
+}
+
class Tag {
static const int Nothing = 0;
static const int Something = 1;
diff --git a/pkg/analyzer/lib/src/summary2/ast_text_printer.dart b/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
index 7f45994..22d52eb 100644
--- a/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_text_printer.dart
@@ -333,7 +333,7 @@
@override
void visitExportDirective(ExportDirective node) {
_directive(node);
- _token(node.keyword);
+ _token(node.exportKeyword);
node.uri.accept(this);
node.configurations.accept(this);
_nodeList(node.combinators);
@@ -597,7 +597,7 @@
@override
void visitImportDirective(ImportDirective node) {
_directive(node);
- _token(node.keyword);
+ _token(node.importKeyword);
node.uri.accept(this);
node.configurations.accept(this);
_token(node.deferredKeyword);
diff --git a/pkg/analyzer/lib/src/summary2/bundle_reader.dart b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
index 9efb948..b8a91b6 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_reader.dart
@@ -125,8 +125,6 @@
class CompilationUnitElementLinkedData
extends ElementLinkedData<CompilationUnitElementImpl> {
- ApplyConstantOffsets? applyConstantOffsets;
-
CompilationUnitElementLinkedData({
required Reference reference,
required LibraryReader libraryReader,
@@ -135,12 +133,7 @@
}) : super(reference, libraryReader, unitElement, offset);
@override
- void _read(element, reader) {
- element.metadata = reader._readAnnotationList(
- unitElement: unitElement,
- );
- applyConstantOffsets?.perform();
- }
+ void _read(element, reader) {}
}
class ConstructorElementLinkedData
@@ -393,6 +386,13 @@
export.exportedLibrary = reader.readElement() as LibraryElementImpl?;
}
+ for (final part in element.parts2) {
+ part as PartElementImpl;
+ part.metadata = reader._readAnnotationList(
+ unitElement: unitElement,
+ );
+ }
+
element.entryPoint = reader.readElement() as FunctionElement?;
applyConstantOffsets?.perform();
@@ -451,29 +451,30 @@
LibraryElementFlags.read(_reader, libraryElement);
var unitContainerRef = _reference.getChild('@unit');
- var unitCount = _reader.readUInt30();
- var units = <CompilationUnitElementImpl>[];
- for (var i = 0; i < unitCount; i++) {
- var unitElement = _readUnitElement(
- sourceFactory: sourceFactory,
+
+ libraryElement.definingCompilationUnit = _readUnitElement(
+ sourceFactory: sourceFactory,
+ unitContainerRef: unitContainerRef,
+ libraryElement: libraryElement,
+ librarySource: librarySource,
+ unitSource: librarySource,
+ );
+
+ libraryElement.parts2 = _reader.readTypedList(() {
+ return _readPartElement(
unitContainerRef: unitContainerRef,
libraryElement: libraryElement,
- librarySource: librarySource,
);
- units.add(unitElement);
- }
+ });
libraryElement.exportedReferences = _reader.readTypedList(
_readExportedReference,
);
- libraryElement.definingCompilationUnit = units[0];
- libraryElement.parts = units.skip(1).toList();
-
libraryElement.linkedData = LibraryElementLinkedData(
reference: _reference,
libraryReader: this,
- unitElement: units[0],
+ unitElement: libraryElement.definingCompilationUnit,
offset: resolutionOffset,
);
@@ -977,6 +978,47 @@
});
}
+ PartElement _readPartElement({
+ required Reference unitContainerRef,
+ required LibraryElementImpl libraryElement,
+ }) {
+ final analysisContext = _elementFactory.analysisContext;
+ final sourceFactory = analysisContext.sourceFactory;
+
+ final kindIndex = _reader.readByte();
+ final kind = PartElementKind.values[kindIndex];
+ switch (kind) {
+ case PartElementKind.withPart:
+ final relativeUriString = _reader.readStringReference();
+ final uriStr = _reader.readStringReference();
+ final uri = Uri.parse(uriStr);
+ final uriSource = sourceFactory.forUri2(uri)!;
+ final unitElement = _readUnitElement(
+ sourceFactory: sourceFactory,
+ unitContainerRef: unitContainerRef,
+ libraryElement: libraryElement,
+ librarySource: libraryElement.source,
+ unitSource: uriSource,
+ );
+ return PartElementWithPartImpl(
+ relativeUriString: relativeUriString,
+ uriSource: uriSource,
+ includedUnit: unitElement,
+ );
+ case PartElementKind.withSource:
+ final relativeUriString = _reader.readStringReference();
+ final uriStr = _reader.readStringReference();
+ final uri = Uri.parse(uriStr);
+ final uriSource = sourceFactory.forUri2(uri)!;
+ return PartElementWithSourceImpl(
+ relativeUriString: relativeUriString,
+ uriSource: uriSource,
+ );
+ case PartElementKind.withNothing:
+ return PartElementImpl();
+ }
+ }
+
PropertyAccessorElementImpl _readPropertyAccessorElement(
CompilationUnitElementImpl unitElement,
ElementImpl classElement,
@@ -1196,11 +1238,9 @@
required Reference unitContainerRef,
required LibraryElementImpl libraryElement,
required Source librarySource,
+ required Source unitSource,
}) {
var resolutionOffset = _baseResolutionOffset + _reader.readUInt30();
- var unitUriStr = _reader.readStringReference();
- var unitUri = Uri.parse(unitUriStr);
- var unitSource = sourceFactory.forUri2(unitUri)!;
var unitElement = CompilationUnitElementImpl(
source: unitSource,
@@ -1208,7 +1248,7 @@
lineInfo: LineInfo([0]),
);
- var unitReference = unitContainerRef.getChild(unitUriStr);
+ var unitReference = unitContainerRef.getChild('${unitSource.uri}');
unitElement.setLinkedData(
unitReference,
CompilationUnitElementLinkedData(
diff --git a/pkg/analyzer/lib/src/summary2/bundle_writer.dart b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
index ffd3fd6..1993b8e 100644
--- a/pkg/analyzer/lib/src/summary2/bundle_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/bundle_writer.dart
@@ -104,12 +104,14 @@
_resolutionSink._writeAnnotationList(libraryElement.metadata);
_writeList(libraryElement.imports, _writeImportElement);
_writeList(libraryElement.exports, _writeExportElement);
+ for (final partElement in libraryElement.parts2) {
+ _resolutionSink._writeAnnotationList(partElement.metadata);
+ }
_resolutionSink.writeElement(libraryElement.entryPoint);
LibraryElementFlags.write(_sink, libraryElement);
- _sink.writeUInt30(libraryElement.units.length);
- for (var unitElement in libraryElement.units) {
- _writeUnitElement(unitElement);
- }
+ _writeUnitElement(libraryElement.definingCompilationUnit);
+ _writeList(libraryElement.parts2, _writePartElement);
+
_writeExportedReferences(libraryElement.exportedReferences);
_libraries.add(
@@ -391,6 +393,21 @@
});
}
+ void _writePartElement(PartElement element) {
+ if (element is PartElementWithPart) {
+ _sink.writeByte(PartElementKind.withPart.index);
+ _sink._writeStringReference(element.relativeUriString);
+ _sink._writeStringReference('${element.uriSource.uri}');
+ _writeUnitElement(element.includedUnit);
+ } else if (element is PartElementWithSource) {
+ _sink.writeByte(PartElementKind.withSource.index);
+ _sink._writeStringReference(element.relativeUriString);
+ _sink._writeStringReference('${element.uriSource.uri}');
+ } else {
+ _sink.writeByte(PartElementKind.withNothing.index);
+ }
+ }
+
void _writePropertyAccessorElement(PropertyAccessorElement element) {
element as PropertyAccessorElementImpl;
_sink.writeUInt30(_resolutionSink.offset);
@@ -455,10 +472,8 @@
unitElement as CompilationUnitElementImpl;
_sink.writeUInt30(_resolutionSink.offset);
- _sink._writeStringReference('${unitElement.source.uri}');
_sink._writeOptionalStringReference(unitElement.uri);
_sink.writeBool(unitElement.isSynthetic);
- _resolutionSink._writeAnnotationList(unitElement.metadata);
_writeList(unitElement.classes, _writeClassElement);
_writeList(unitElement.enums, _writeEnumElement);
_writeList(unitElement.extensions, _writeExtensionElement);
diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart
index 63e3bb8..e53f62f 100644
--- a/pkg/analyzer/lib/src/summary2/element_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/element_builder.dart
@@ -381,7 +381,7 @@
@override
void visitExportDirective(covariant ExportDirectiveImpl node) {
- var element = ExportElementImpl(node.keyword.offset);
+ var element = ExportElementImpl(node.exportKeyword.offset);
element.combinators = _buildCombinators(node.combinators);
try {
@@ -759,7 +759,7 @@
void visitImportDirective(covariant ImportDirectiveImpl node) {
var uriStr = node.uri.stringValue;
- var element = ImportElementImpl(node.keyword.offset);
+ var element = ImportElementImpl(node.importKeyword.offset);
element.combinators = _buildCombinators(node.combinators);
try {
@@ -920,13 +920,10 @@
@override
void visitPartDirective(PartDirective node) {
- var index = _partDirectiveIndex++;
- // TODO(scheglov) With invalid URIs we will associate metadata incorrectly
- if (index < _libraryElement.parts.length) {
- var partElement = _libraryElement.parts[index];
- partElement as CompilationUnitElementImpl;
- partElement.metadata = _buildAnnotations(node.metadata);
- }
+ final index = _partDirectiveIndex++;
+ final partElement = _libraryElement.parts2[index];
+ partElement as PartElementImpl;
+ partElement.metadata = _buildAnnotations(node.metadata);
}
@override
diff --git a/pkg/analyzer/lib/src/summary2/informative_data.dart b/pkg/analyzer/lib/src/summary2/informative_data.dart
index 2cb8c14..086c90d 100644
--- a/pkg/analyzer/lib/src/summary2/informative_data.dart
+++ b/pkg/analyzer/lib/src/summary2/informative_data.dart
@@ -474,18 +474,11 @@
},
);
- forCorrespondingPairs<CompilationUnitElement, _InfoPart>(
- element.parts,
+ forCorrespondingPairs<PartElement, _InfoPart>(
+ element.parts2,
info.parts,
(element, info) {
- element as CompilationUnitElementImpl;
- var linkedData = element.linkedData as CompilationUnitElementLinkedData;
- linkedData.applyConstantOffsets = ApplyConstantOffsets(
- info.constantOffsets,
- (applier) {
- applier.applyToMetadata(element);
- },
- );
+ element as PartElementImpl;
},
);
@@ -496,6 +489,7 @@
applier.applyToMetadata(element);
applier.applyToDirectives(element.imports);
applier.applyToDirectives(element.exports);
+ applier.applyToPartDirectives(element.parts2);
},
);
}
@@ -1031,16 +1025,16 @@
}
class _InfoPart {
- final Uint32List constantOffsets;
+ final int nameOffset;
factory _InfoPart(SummaryDataReader reader) {
return _InfoPart._(
- constantOffsets: reader.readUInt30List(),
+ nameOffset: reader.readUInt30(),
);
}
_InfoPart._({
- required this.constantOffsets,
+ required this.nameOffset,
});
}
@@ -1061,20 +1055,18 @@
_writeDocumentationCommentNode(firstDirective?.documentationComment);
sink.writeList2<ImportDirective>(unit.directives, (directive) {
- sink.writeUInt30(directive.keyword.offset);
+ sink.writeUInt30(directive.importKeyword.offset);
sink.writeUInt30(1 + (directive.prefix?.offset ?? -1));
_writeCombinators(directive.combinators);
});
sink.writeList2<ExportDirective>(unit.directives, (directive) {
- sink.writeUInt30(directive.keyword.offset);
+ sink.writeUInt30(directive.exportKeyword.offset);
_writeCombinators(directive.combinators);
});
- sink.writeList2<PartDirective>(unit.directives, (node) {
- _writeOffsets(
- metadata: node.metadata,
- );
+ sink.writeList2<PartDirective>(unit.directives, (directive) {
+ sink.writeUInt30(directive.partKeyword.offset);
});
sink.writeList2<ClassDeclaration>(unit.declarations, (node) {
@@ -1398,6 +1390,7 @@
metadata: firstDirective?.metadata,
importDirectives: unit.directives.whereType<ImportDirective>(),
exportDirectives: unit.directives.whereType<ExportDirective>(),
+ partDirectives: unit.directives.whereType<PartDirective>(),
);
}
@@ -1427,6 +1420,7 @@
NodeList<Annotation>? metadata,
Iterable<ImportDirective>? importDirectives,
Iterable<ExportDirective>? exportDirectives,
+ Iterable<PartDirective>? partDirectives,
TypeParameterList? typeParameters,
FormalParameterList? formalParameters,
Expression? constantInitializer,
@@ -1472,6 +1466,7 @@
metadata?.accept(collector);
addDirectives(importDirectives);
addDirectives(exportDirectives);
+ addDirectives(partDirectives);
addTypeParameters(typeParameters);
addFormalParameters(formalParameters);
constantInitializer?.accept(collector);
@@ -1591,6 +1586,7 @@
libraryName: _InfoLibraryName(reader),
libraryConstantOffsets: reader.readUInt30List(),
docComment: reader.readStringUtf8(),
+ // TODO(scheglov)
imports: reader.readTypedList(
() => _InfoImport(reader),
),
@@ -1702,6 +1698,12 @@
}
}
+ void applyToPartDirectives(List<PartElement> elements) {
+ for (var element in elements) {
+ applyToMetadata(element);
+ }
+ }
+
void applyToTypeParameters(List<TypeParameterElement> typeParameters) {
for (var typeParameter in typeParameters) {
applyToMetadata(typeParameter);
diff --git a/pkg/analyzer/lib/src/summary2/library_builder.dart b/pkg/analyzer/lib/src/summary2/library_builder.dart
index 281b0ec..e0f47f2 100644
--- a/pkg/analyzer/lib/src/summary2/library_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/library_builder.dart
@@ -7,6 +7,7 @@
import 'package:analyzer/dart/ast/ast.dart' as ast;
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/visitor.dart';
+import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/ast/ast.dart' as ast;
import 'package:analyzer/src/dart/ast/mixin_super_invoked_names.dart';
import 'package:analyzer/src/dart/element/element.dart';
@@ -39,6 +40,7 @@
class LibraryBuilder {
final Linker linker;
+ final LibraryFileStateKind kind;
final Uri uri;
final Reference reference;
final LibraryElementImpl element;
@@ -74,6 +76,7 @@
LibraryBuilder._({
required this.linker,
+ required this.kind,
required this.uri,
required this.reference,
required this.element,
@@ -305,8 +308,9 @@
// For now we model augmentation libraries as parts.
var unitUri = uri.resolve('_macro_types.dart');
+ final unitSource = _sourceFactory.forUri2(unitUri)!;
var unitElement = CompilationUnitElementImpl(
- source: _sourceFactory.forUri2(unitUri)!,
+ source: unitSource,
librarySource: element.source,
lineInfo: parseResult.lineInfo,
)
@@ -317,7 +321,13 @@
var unitReference = reference.getChild('@unit').getChild('$unitUri');
_bindReference(unitReference, unitElement);
- element.parts.add(unitElement);
+ element.parts2.add(
+ PartElementWithPartImpl(
+ relativeUriString: '_macro_types.dart',
+ uriSource: unitSource,
+ includedUnit: unitElement,
+ ),
+ );
ElementBuilder(
libraryBuilder: this,
@@ -402,20 +412,20 @@
}
}
- static void build(Linker linker, LinkInputLibrary inputLibrary) {
- var elementFactory = linker.elementFactory;
+ static void build(Linker linker, LibraryFileStateKind inputLibrary) {
+ final elementFactory = linker.elementFactory;
+ final rootReference = linker.rootReference;
- var rootReference = linker.rootReference;
- var libraryUriStr = inputLibrary.uriStr;
- var libraryReference = rootReference.getChild(libraryUriStr);
+ final libraryFile = inputLibrary.file;
+ final libraryUriStr = libraryFile.uriStr;
+ final libraryReference = rootReference.getChild(libraryUriStr);
- var definingUnit = inputLibrary.units[0];
- var definingUnitNode = definingUnit.unit as ast.CompilationUnitImpl;
+ final libraryUnitNode = libraryFile.parse();
var name = '';
var nameOffset = -1;
var nameLength = 0;
- for (var directive in definingUnitNode.directives) {
+ for (final directive in libraryUnitNode.directives) {
if (directive is ast.LibraryDirective) {
name = directive.name.components.map((e) => e.name).join('.');
nameOffset = directive.name.offset;
@@ -424,56 +434,101 @@
}
}
- var libraryElement = LibraryElementImpl(
+ final libraryElement = LibraryElementImpl(
elementFactory.analysisContext,
elementFactory.analysisSession,
name,
nameOffset,
nameLength,
- definingUnitNode.featureSet,
+ libraryUnitNode.featureSet,
);
- libraryElement.isSynthetic = definingUnit.isSynthetic;
- libraryElement.languageVersion = definingUnitNode.languageVersion!;
+ libraryElement.isSynthetic = !libraryFile.exists;
+ libraryElement.languageVersion = libraryUnitNode.languageVersion!;
_bindReference(libraryReference, libraryElement);
elementFactory.setLibraryTypeSystem(libraryElement);
- var unitContainerRef = libraryReference.getChild('@unit');
- var unitElements = <CompilationUnitElementImpl>[];
- var isDefiningUnit = true;
- var linkingUnits = <LinkingUnit>[];
- for (var inputUnit in inputLibrary.units) {
- var unitNode = inputUnit.unit as ast.CompilationUnitImpl;
+ final unitContainerRef = libraryReference.getChild('@unit');
- var unitElement = CompilationUnitElementImpl(
- source: inputUnit.source,
- librarySource: inputLibrary.source,
- lineInfo: unitNode.lineInfo,
+ final linkingUnits = <LinkingUnit>[];
+ {
+ final unitElement = CompilationUnitElementImpl(
+ source: libraryFile.source,
+ librarySource: libraryFile.source,
+ lineInfo: libraryUnitNode.lineInfo,
);
- unitElement.isSynthetic = inputUnit.isSynthetic;
- unitElement.uri = inputUnit.partUriStr;
- unitElement.setCodeRange(0, unitNode.length);
+ unitElement.isSynthetic = !libraryFile.exists;
+ unitElement.setCodeRange(0, libraryUnitNode.length);
- var unitReference = unitContainerRef.getChild(inputUnit.uriStr);
+ final unitReference = unitContainerRef.getChild(libraryFile.uriStr);
_bindReference(unitReference, unitElement);
- unitElements.add(unitElement);
linkingUnits.add(
LinkingUnit(
- isDefiningUnit: isDefiningUnit,
+ isDefiningUnit: true,
reference: unitReference,
- node: unitNode,
+ node: libraryUnitNode,
element: unitElement,
),
);
- isDefiningUnit = false;
+
+ libraryElement.definingCompilationUnit = unitElement;
}
- libraryElement.definingCompilationUnit = unitElements[0];
- libraryElement.parts = unitElements.skip(1).toList();
+ final parts = <PartElementImpl>[];
+ for (final partState in inputLibrary.parts) {
+ if (partState is PartDirectiveWithFile) {
+ final includedPart = partState.includedPart;
+ if (includedPart != null) {
+ final partFile = includedPart.file;
+ final partUnitNode = partFile.parse();
+ final unitElement = CompilationUnitElementImpl(
+ source: partFile.source,
+ librarySource: libraryFile.source,
+ lineInfo: partUnitNode.lineInfo,
+ );
+ unitElement.isSynthetic = !partFile.exists;
+ unitElement.uri = partFile.uriStr;
+ unitElement.setCodeRange(0, partUnitNode.length);
+ parts.add(
+ PartElementWithPartImpl(
+ relativeUriString: partState.uri.relativeUriStr,
+ uriSource: partFile.source,
+ includedUnit: unitElement,
+ ),
+ );
- var builder = LibraryBuilder._(
+ final unitReference = unitContainerRef.getChild(partFile.uriStr);
+ _bindReference(unitReference, unitElement);
+
+ linkingUnits.add(
+ LinkingUnit(
+ isDefiningUnit: false,
+ reference: unitReference,
+ node: partUnitNode,
+ element: unitElement,
+ ),
+ );
+ } else {
+ parts.add(
+ PartElementWithSourceImpl(
+ relativeUriString: partState.uri.relativeUriStr,
+ uriSource: partState.includedFile.source,
+ ),
+ );
+ }
+ } else {
+ parts.add(
+ PartElementImpl(),
+ );
+ }
+ }
+
+ libraryElement.parts2 = parts;
+
+ final builder = LibraryBuilder._(
linker: linker,
- uri: inputLibrary.uri,
+ kind: inputLibrary,
+ uri: libraryFile.uri,
reference: libraryReference,
element: libraryElement,
units: linkingUnits,
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index e099e37..8bf045ab 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -10,9 +10,9 @@
import 'package:analyzer/dart/ast/ast.dart' as ast;
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/context/context.dart';
+import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
-import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary2/bundle_writer.dart';
import 'package:analyzer/src/summary2/detach_nodes.dart';
import 'package:analyzer/src/summary2/library_builder.dart';
@@ -27,26 +27,10 @@
import 'package:analyzer/src/summary2/variance_builder.dart';
import 'package:analyzer/src/util/performance/operation_performance.dart';
-/// Note that AST units and tokens of [inputLibraries] will be damaged.
-@Deprecated('Use link2() instead')
-Future<LinkResult> link(
- LinkedElementFactory elementFactory,
- List<LinkInputLibrary> inputLibraries, {
- macro.MultiMacroExecutor? macroExecutor,
- OperationPerformanceImpl? performance,
-}) async {
- return await link2(
- elementFactory: elementFactory,
- inputLibraries: inputLibraries,
- performance: OperationPerformanceImpl('<root>'),
- );
-}
-
-/// Note that AST units and tokens of [inputLibraries] will be damaged.
-Future<LinkResult> link2({
+Future<LinkResult> link({
required LinkedElementFactory elementFactory,
required OperationPerformanceImpl performance,
- required List<LinkInputLibrary> inputLibraries,
+ required List<LibraryFileStateKind> inputLibraries,
macro.MultiMacroExecutor? macroExecutor,
}) async {
final linker = Linker(elementFactory, macroExecutor);
@@ -101,7 +85,7 @@
Future<void> link({
required OperationPerformanceImpl performance,
- required List<LinkInputLibrary> inputLibraries,
+ required List<LibraryFileStateKind> inputLibraries,
}) async {
for (var inputLibrary in inputLibraries) {
LibraryBuilder.build(this, inputLibrary);
@@ -311,42 +295,6 @@
}
}
-class LinkInputLibrary {
- final Source source;
- final List<LinkInputUnit> units;
-
- LinkInputLibrary({
- required this.source,
- required this.units,
- });
-
- Uri get uri => source.uri;
-
- String get uriStr => '$uri';
-}
-
-class LinkInputUnit {
- final int? partDirectiveIndex;
- final String? partUriStr;
- final Source source;
- final String? sourceContent;
- final bool isSynthetic;
- final ast.CompilationUnit unit;
-
- LinkInputUnit({
- required this.partDirectiveIndex,
- this.partUriStr,
- required this.source,
- this.sourceContent,
- required this.isSynthetic,
- required this.unit,
- });
-
- Uri get uri => source.uri;
-
- String get uriStr => '$uri';
-}
-
class LinkMacroGeneratedUnit {
final Uri uri;
final String content;
diff --git a/pkg/analyzer/lib/src/test_utilities/find_element.dart b/pkg/analyzer/lib/src/test_utilities/find_element.dart
index 0c572a2..29ff647 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_element.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_element.dart
@@ -216,19 +216,22 @@
}
CompilationUnitElement part(String targetUri) {
- CompilationUnitElement? partElement;
+ CompilationUnitElement? result;
- for (var part in libraryElement.parts) {
- if (part.uri == targetUri) {
- if (partElement != null) {
- throw StateError('Not unique: $targetUri');
+ for (final part in libraryElement.parts2) {
+ if (part is PartElementWithPart) {
+ final unitElement = part.includedUnit;
+ if ('${unitElement.source.uri}' == targetUri) {
+ if (result != null) {
+ throw StateError('Not unique: $targetUri');
+ }
+ result = unitElement;
}
- partElement = part;
}
}
- if (partElement != null) {
- return partElement;
+ if (result != null) {
+ return result;
}
throw StateError('Not found: $targetUri');
}
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index da576fd..4b27f79 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
name: analyzer
-version: 4.2.0
+version: 4.3.0-dev
description: This package provides a library that performs static analysis of Dart code.
repository: https://github.com/dart-lang/sdk/tree/main/pkg/analyzer
diff --git a/pkg/analyzer/test/generated/scanner_test.dart b/pkg/analyzer/test/generated/scanner_test.dart
index 8dff3c5..db9c70a 100644
--- a/pkg/analyzer/test/generated/scanner_test.dart
+++ b/pkg/analyzer/test/generated/scanner_test.dart
@@ -286,7 +286,7 @@
late Token previousToken;
int previousEnd = -1;
Token? currentToken = token;
- while (currentToken != null && currentToken.type != TokenType.EOF) {
+ while (currentToken != null && !currentToken.isEof) {
_validateStream(buffer, currentToken.precedingComments);
TokenType type = currentToken.type;
if (type == TokenType.OPEN_CURLY_BRACKET ||
diff --git a/pkg/analyzer/test/generated/top_level_parser_test.dart b/pkg/analyzer/test/generated/top_level_parser_test.dart
index 8bb9be2..f20c303 100644
--- a/pkg/analyzer/test/generated/top_level_parser_test.dart
+++ b/pkg/analyzer/test/generated/top_level_parser_test.dart
@@ -1098,7 +1098,7 @@
assertNoErrors();
expect(directive, TypeMatcher<ExportDirective>());
var exportDirective = directive as ExportDirective;
- expect(exportDirective.keyword, isNotNull);
+ expect(exportDirective.exportKeyword, isNotNull);
expect(exportDirective.uri, isNotNull);
expect(exportDirective.combinators, hasLength(0));
expect(exportDirective.semicolon, isNotNull);
@@ -1117,7 +1117,7 @@
assertNoErrors();
expect(directive, TypeMatcher<ImportDirective>());
var importDirective = directive as ImportDirective;
- expect(importDirective.keyword, isNotNull);
+ expect(importDirective.importKeyword, isNotNull);
expect(importDirective.uri, isNotNull);
expect(importDirective.asKeyword, isNull);
expect(importDirective.prefix, isNull);
@@ -1384,7 +1384,7 @@
var directive = parseFullDirective() as ExportDirective;
expect(directive, isNotNull);
assertNoErrors();
- expect(directive.keyword, isNotNull);
+ expect(directive.exportKeyword, isNotNull);
expect(directive.uri, isNotNull);
expect(directive.configurations, hasLength(2));
expectDottedName(directive.configurations[0].name, ['a']);
@@ -1398,7 +1398,7 @@
var directive = parseFullDirective() as ExportDirective;
expect(directive, isNotNull);
assertNoErrors();
- expect(directive.keyword, isNotNull);
+ expect(directive.exportKeyword, isNotNull);
expect(directive.uri, isNotNull);
expect(directive.configurations, hasLength(1));
expectDottedName(directive.configurations[0].name, ['a', 'b']);
@@ -1411,7 +1411,7 @@
var directive = parseFullDirective() as ExportDirective;
expect(directive, isNotNull);
assertNoErrors();
- expect(directive.keyword, isNotNull);
+ expect(directive.exportKeyword, isNotNull);
expect(directive.uri, isNotNull);
expect(directive.combinators, hasLength(1));
expect(directive.semicolon, isNotNull);
@@ -1422,7 +1422,7 @@
var directive = parseFullDirective() as ExportDirective;
expect(directive, isNotNull);
assertNoErrors();
- expect(directive.keyword, isNotNull);
+ expect(directive.exportKeyword, isNotNull);
expect(directive.uri, isNotNull);
expect(directive.combinators, hasLength(2));
expect(directive.semicolon, isNotNull);
@@ -1433,7 +1433,7 @@
var directive = parseFullDirective() as ExportDirective;
expect(directive, isNotNull);
assertNoErrors();
- expect(directive.keyword, isNotNull);
+ expect(directive.exportKeyword, isNotNull);
expect(directive.uri, isNotNull);
expect(directive.combinators, hasLength(0));
expect(directive.semicolon, isNotNull);
@@ -1444,7 +1444,7 @@
var directive = parseFullDirective() as ExportDirective;
expect(directive, isNotNull);
assertNoErrors();
- expect(directive.keyword, isNotNull);
+ expect(directive.exportKeyword, isNotNull);
expect(directive.uri, isNotNull);
expect(directive.combinators, hasLength(1));
expect(directive.semicolon, isNotNull);
@@ -1455,7 +1455,7 @@
var directive = parseFullDirective() as ExportDirective;
expect(directive, isNotNull);
assertNoErrors();
- expect(directive.keyword, isNotNull);
+ expect(directive.exportKeyword, isNotNull);
expect(directive.uri, isNotNull);
expect(directive.combinators, hasLength(2));
expect(directive.semicolon, isNotNull);
@@ -1786,7 +1786,7 @@
var directive = parseFullDirective() as ImportDirective;
expect(directive, isNotNull);
assertNoErrors();
- expect(directive.keyword, isNotNull);
+ expect(directive.importKeyword, isNotNull);
expect(directive.uri, isNotNull);
expect(directive.configurations, hasLength(2));
expectDottedName(directive.configurations[0].name, ['a']);
@@ -1803,7 +1803,7 @@
var directive = parseFullDirective() as ImportDirective;
expect(directive, isNotNull);
assertNoErrors();
- expect(directive.keyword, isNotNull);
+ expect(directive.importKeyword, isNotNull);
expect(directive.uri, isNotNull);
expect(directive.configurations, hasLength(1));
expectDottedName(directive.configurations[0].name, ['a', 'b']);
@@ -1819,7 +1819,7 @@
var directive = parseFullDirective() as ImportDirective;
expect(directive, isNotNull);
assertNoErrors();
- expect(directive.keyword, isNotNull);
+ expect(directive.importKeyword, isNotNull);
expect(directive.uri, isNotNull);
expect(directive.deferredKeyword, isNotNull);
expect(directive.asKeyword, isNotNull);
@@ -1833,7 +1833,7 @@
var directive = parseFullDirective() as ImportDirective;
expect(directive, isNotNull);
assertNoErrors();
- expect(directive.keyword, isNotNull);
+ expect(directive.importKeyword, isNotNull);
expect(directive.uri, isNotNull);
expect(directive.deferredKeyword, isNull);
expect(directive.asKeyword, isNull);
@@ -1847,7 +1847,7 @@
var directive = parseFullDirective() as ImportDirective;
expect(directive, isNotNull);
assertNoErrors();
- expect(directive.keyword, isNotNull);
+ expect(directive.importKeyword, isNotNull);
expect(directive.uri, isNotNull);
expect(directive.deferredKeyword, isNull);
expect(directive.asKeyword, isNull);
@@ -1861,7 +1861,7 @@
var directive = parseFullDirective() as ImportDirective;
expect(directive, isNotNull);
assertNoErrors();
- expect(directive.keyword, isNotNull);
+ expect(directive.importKeyword, isNotNull);
expect(directive.uri, isNotNull);
expect(directive.deferredKeyword, isNull);
expect(directive.asKeyword, isNotNull);
@@ -1875,7 +1875,7 @@
var directive = parseFullDirective() as ImportDirective;
expect(directive, isNotNull);
assertNoErrors();
- expect(directive.keyword, isNotNull);
+ expect(directive.importKeyword, isNotNull);
expect(directive.uri, isNotNull);
expect(directive.deferredKeyword, isNull);
expect(directive.asKeyword, isNotNull);
@@ -1889,7 +1889,7 @@
var directive = parseFullDirective() as ImportDirective;
expect(directive, isNotNull);
assertNoErrors();
- expect(directive.keyword, isNotNull);
+ expect(directive.importKeyword, isNotNull);
expect(directive.uri, isNotNull);
expect(directive.deferredKeyword, isNull);
expect(directive.asKeyword, isNotNull);
@@ -1903,7 +1903,7 @@
var directive = parseFullDirective() as ImportDirective;
expect(directive, isNotNull);
assertNoErrors();
- expect(directive.keyword, isNotNull);
+ expect(directive.importKeyword, isNotNull);
expect(directive.uri, isNotNull);
expect(directive.deferredKeyword, isNull);
expect(directive.asKeyword, isNull);
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 0d9b911..0149bed 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -692,57 +692,6 @@
expect(allResults.pathList, [b]);
}
- test_analyze_resolveDirectives() async {
- var lib = convertPath('/test/lib.dart');
- var part1 = convertPath('/test/part1.dart');
- var part2 = convertPath('/test/part2.dart');
- newFile(lib, '''
-library lib;
-part 'part1.dart';
-part 'part2.dart';
-''');
- newFile(part1, '''
-part of lib;
-''');
- newFile(part2, '''
-part of 'lib.dart';
-''');
-
- ResolvedUnitResult libResult = await driver.getResultValid(lib);
- ResolvedUnitResult partResult1 = await driver.getResultValid(part1);
- ResolvedUnitResult partResult2 = await driver.getResultValid(part2);
-
- CompilationUnit libUnit = libResult.unit;
- CompilationUnit partUnit1 = partResult1.unit;
- CompilationUnit partUnit2 = partResult2.unit;
-
- CompilationUnitElement unitElement = libUnit.declaredElement!;
- CompilationUnitElement partElement1 = partUnit1.declaredElement!;
- CompilationUnitElement partElement2 = partUnit2.declaredElement!;
-
- LibraryElement libraryElement = unitElement.library;
- {
- expect(libraryElement.entryPoint, isNull);
- expect(libraryElement.source, unitElement.source);
- expect(libraryElement.definingCompilationUnit, unitElement);
- expect(libraryElement.parts, hasLength(2));
- }
-
- expect((libUnit.directives[0] as LibraryDirective).element, libraryElement);
- expect((libUnit.directives[1] as PartDirective).element, partElement1);
- expect((libUnit.directives[2] as PartDirective).element, partElement2);
-
- {
- var partOf = partUnit1.directives.single as PartOfDirective;
- expect(partOf.element, libraryElement);
- }
-
- {
- var partOf = partUnit2.directives.single as PartOfDirective;
- expect(partOf.element, libraryElement);
- }
- }
-
test_analyze_resolveDirectives_error_missingLibraryDirective() async {
var lib = convertPath('/test/lib.dart');
var part = convertPath('/test/part.dart');
diff --git a/pkg/analyzer/test/src/dart/analysis/index_test.dart b/pkg/analyzer/test/src/dart/analysis/index_test.dart
index f16ec1f..b3245ba 100644
--- a/pkg/analyzer/test/src/dart/analysis/index_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/index_test.dart
@@ -740,7 +740,7 @@
library my_lib;
part 'my_unit.dart';
''');
- var element = findElement.part('my_unit.dart');
+ var element = findElement.part('package:test/my_unit.dart');
assertThat(element).isReferencedAt("'my_unit.dart';", true, length: 14);
}
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index 490c069..9714635 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -1292,8 +1292,10 @@
part 'unitB.dart';
''');
LibraryElement element = result.libraryElement;
- CompilationUnitElement unitElementA = element.parts[0];
- CompilationUnitElement unitElementB = element.parts[1];
+ CompilationUnitElement unitElementA =
+ (element.parts2[0] as PartElementWithPart).includedUnit;
+ CompilationUnitElement unitElementB =
+ (element.parts2[1] as PartElementWithPart).includedUnit;
var expected = [
ExpectedResult(unitElementA, SearchResultKind.REFERENCE,
codeA.indexOf('lib; // A'), 'lib'.length),
@@ -1328,8 +1330,10 @@
part 'unitB.dart';
''');
LibraryElement element = result.libraryElement;
- CompilationUnitElement unitElementA = element.parts[0];
- CompilationUnitElement unitElementB = element.parts[1];
+ CompilationUnitElement unitElementA =
+ (element.parts2[0] as PartElementWithPart).includedUnit;
+ CompilationUnitElement unitElementB =
+ (element.parts2[1] as PartElementWithPart).includedUnit;
var expected = [
ExpectedResult(unitElementA, SearchResultKind.REFERENCE,
codeA.indexOf('lib; // A'), 'lib'.length),
@@ -1843,7 +1847,7 @@
''');
var element = findElement.prefix('ppp');
var main = findElement.function('main');
- var c = findElement.partFind('my_part.dart').topVar('c');
+ var c = findElement.partFind('package:test/my_part.dart').topVar('c');
var expected = [
_expectId(main, SearchResultKind.REFERENCE, 'ppp.Future'),
_expectId(main, SearchResultKind.REFERENCE, 'ppp.Stream'),
@@ -1882,7 +1886,7 @@
''');
var element = findElement.prefix('ppp');
var main = findElement.function('main');
- var c = findElement.partFind('my_part.dart').topVar('c');
+ var c = findElement.partFind('package:aaa/my_part.dart').topVar('c');
var expected = [
_expectId(main, SearchResultKind.REFERENCE, 'ppp.Future'),
_expectId(main, SearchResultKind.REFERENCE, 'ppp.Stream'),
@@ -1912,8 +1916,8 @@
''');
var element = findElement.class_('_C');
Element v = findElement.topVar('v');
- Element v1 = findElement.partFind('part1.dart').topVar('v1');
- Element v2 = findElement.partFind('part2.dart').topVar('v2');
+ Element v1 = findElement.partFind('package:test/part1.dart').topVar('v1');
+ Element v2 = findElement.partFind('package:test/part2.dart').topVar('v2');
var expected = [
_expectId(v, SearchResultKind.REFERENCE, '_C v;', length: 2),
ExpectedResult(
@@ -1948,10 +1952,11 @@
await resolveTestCode(code);
- ClassElement element = findElement.partFind('part1.dart').class_('_C');
+ ClassElement element =
+ findElement.partFind('package:test/part1.dart').class_('_C');
Element v = findElement.topVar('v');
- Element v1 = findElement.partFind('part1.dart').topVar('v1');
- Element v2 = findElement.partFind('part2.dart').topVar('v2');
+ Element v1 = findElement.partFind('package:test/part1.dart').topVar('v1');
+ Element v2 = findElement.partFind('package:test/part2.dart').topVar('v2');
var expected = [
ExpectedResult(v, SearchResultKind.REFERENCE, code.indexOf('_C v;'), 2),
ExpectedResult(
@@ -1992,8 +1997,8 @@
ClassElement element = findElement.class_('_C');
Element v = findElement.topVar('v');
- Element v1 = findElement.partFind('part1.dart').topVar('v1');
- Element v2 = findElement.partFind('part2.dart').topVar('v2');
+ Element v1 = findElement.partFind('package:aaa/part1.dart').topVar('v1');
+ Element v2 = findElement.partFind('package:aaa/part2.dart').topVar('v2');
var expected = [
ExpectedResult(
v, SearchResultKind.REFERENCE, testCode.indexOf('_C v;'), 2),
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index 5267086b..b69f6c9 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -1292,23 +1292,6 @@
}
}
- void test_getUnits() {
- AnalysisContext context = TestAnalysisContext();
- LibraryElementImpl library = ElementFactory.library(context, "test");
- CompilationUnitElement unitLib = library.definingCompilationUnit;
- CompilationUnitElementImpl unitA = ElementFactory.compilationUnit(
- source: TestSource("unit_a.dart"),
- librarySource: unitLib.source,
- );
- CompilationUnitElementImpl unitB = ElementFactory.compilationUnit(
- source: TestSource("unit_b.dart"),
- librarySource: unitLib.source,
- );
- library.parts = <CompilationUnitElement>[unitA, unitB];
- expect(library.units,
- unorderedEquals(<CompilationUnitElement>[unitLib, unitA, unitB]));
- }
-
void test_setImports() {
AnalysisContext context = TestAnalysisContext();
LibraryElementImpl library = LibraryElementImpl(
diff --git a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
index 89598f8..659f3e6 100644
--- a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
+++ b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
@@ -460,9 +460,12 @@
var b = B(0);
''');
+ final b = newFile('/workspace/dart/test/lib/b.dart', r'''
+part of 'a.dart';
+''');
+
result = await resolveFile(a.path);
assertErrorsInResolvedUnit(result, [
- error(CompileTimeErrorCode.URI_DOES_NOT_EXIST, 5, 8),
error(CompileTimeErrorCode.UNDEFINED_FUNCTION, 24, 1),
]);
@@ -477,7 +480,7 @@
// Update b.dart, but do not notify the resolver.
// If we try to read it now, it will throw.
- final b = newFile('/workspace/dart/test/lib/b.dart', r'''
+ newFile(b.path, r'''
part of 'a.dart';
class B {
diff --git a/pkg/analyzer/test/src/dart/resolution/part_test.dart b/pkg/analyzer/test/src/dart/resolution/part_test.dart
new file mode 100644
index 0000000..54aad7c
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/part_test.dart
@@ -0,0 +1,143 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(PartDirectiveResolutionTest);
+ });
+}
+
+@reflectiveTest
+class PartDirectiveResolutionTest extends PubPackageResolutionTest {
+ test_withoutString() async {
+ await assertErrorsInCode(r'''
+part '${'foo'}.dart';
+''', [
+ error(CompileTimeErrorCode.URI_WITH_INTERPOLATION, 5, 15),
+ ]);
+
+ assertResolvedNodeText(findNode.part('.dart'), r'''
+PartDirective
+ partKeyword: part
+ uri: StringInterpolation
+ elements
+ InterpolationString
+ contents: '
+ InterpolationExpression
+ leftBracket: ${
+ expression: SimpleStringLiteral
+ literal: 'foo'
+ rightBracket: }
+ InterpolationString
+ contents: .dart'
+ staticType: String
+ stringValue: null
+ semicolon: ;
+ element: PartElement
+ uriContent: null
+ uriElement: notUnitElement
+ uriSource: <null>
+''');
+ }
+
+ test_withPart_partOfName() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+part of my.lib;
+''');
+
+ await assertNoErrorsInCode(r'''
+library my.lib;
+part 'a.dart';
+''');
+
+ assertResolvedNodeText(findNode.part('a.dart'), r'''
+PartDirective
+ partKeyword: part
+ uri: SimpleStringLiteral
+ literal: 'a.dart'
+ semicolon: ;
+ element: PartElementWithPart
+ part: package:test/a.dart
+ uriContent: null
+ uriElement: unitElement package:test/a.dart
+ uriSource: package:test/a.dart
+''');
+ }
+
+ test_withPart_partOfUri() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+part of 'test.dart';
+''');
+
+ await assertNoErrorsInCode(r'''
+part 'a.dart';
+''');
+
+ assertResolvedNodeText(findNode.part('a.dart'), r'''
+PartDirective
+ partKeyword: part
+ uri: SimpleStringLiteral
+ literal: 'a.dart'
+ semicolon: ;
+ element: PartElementWithPart
+ part: package:test/a.dart
+ uriContent: null
+ uriElement: unitElement package:test/a.dart
+ uriSource: package:test/a.dart
+''');
+ }
+
+ test_withSource_notPart_augmentation() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+library augment 'test.dart';
+''');
+
+ await assertErrorsInCode(r'''
+part 'a.dart';
+''', [
+ error(CompileTimeErrorCode.PART_OF_NON_PART, 5, 8),
+ ]);
+
+ assertResolvedNodeText(findNode.part('a.dart'), r'''
+PartDirective
+ partKeyword: part
+ uri: SimpleStringLiteral
+ literal: 'a.dart'
+ semicolon: ;
+ element: PartElementWithSource
+ source: package:test/a.dart
+ uriContent: null
+ uriElement: notUnitElement
+ uriSource: package:test/a.dart
+''');
+ }
+
+ test_withSource_notPart_library() async {
+ newFile('$testPackageLibPath/a.dart', '');
+
+ await assertErrorsInCode(r'''
+part 'a.dart';
+''', [
+ error(CompileTimeErrorCode.PART_OF_NON_PART, 5, 8),
+ ]);
+
+ assertResolvedNodeText(findNode.part('a.dart'), r'''
+PartDirective
+ partKeyword: part
+ uri: SimpleStringLiteral
+ literal: 'a.dart'
+ semicolon: ;
+ element: PartElementWithSource
+ source: package:test/a.dart
+ uriContent: null
+ uriElement: notUnitElement
+ uriSource: package:test/a.dart
+''');
+ }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart
index eb4521e..4c46650 100644
--- a/pkg/analyzer/test/src/dart/resolution/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart
@@ -54,6 +54,7 @@
import 'non_nullable_bazel_workspace_test.dart' as non_nullable_bazel_workspace;
import 'non_nullable_test.dart' as non_nullable;
import 'optional_const_test.dart' as optional_const;
+import 'part_test.dart' as part_;
import 'postfix_expression_test.dart' as postfix_expression;
import 'prefix_element_test.dart' as prefix_element;
import 'prefix_expression_test.dart' as prefix_expression;
@@ -118,6 +119,7 @@
non_nullable_bazel_workspace.main();
non_nullable.main();
optional_const.main();
+ part_.main();
postfix_expression.main();
prefix_element.main();
prefix_expression.main();
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 0befcb4..73308ff 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -164,13 +164,7 @@
_writeUnitElement(e.definingCompilationUnit);
});
- _writeElements('parts', e.parts, (CompilationUnitElement e) {
- _writelnWithIndent(e.uri!);
- _withIndent(() {
- _writeMetadata(e);
- _writeUnitElement(e);
- });
- });
+ _writeElements('parts', e.parts2, _writePartElement);
if (withExportScope) {
_writelnWithIndent('exportedReferences');
@@ -717,6 +711,28 @@
_writeElements('parameters', elements, _writeParameterElement);
}
+ void _writePartElement(PartElement e) {
+ if (e is PartElementWithPart) {
+ _writelnWithIndent('${e.includedUnit.source.uri}');
+ _withIndent(() {
+ _writeMetadata(e);
+ _writeUnitElement(e.includedUnit);
+ });
+ } else if (e is PartElementWithSource) {
+ _writelnWithIndent("source '${e.uriSource.uri}'");
+ _withIndent(() {
+ _writeMetadata(e);
+ });
+ } else if (e is PartElementImpl) {
+ _writelnWithIndent('noSource');
+ _withIndent(() {
+ _writeMetadata(e);
+ });
+ } else {
+ throw UnimplementedError('(${e.runtimeType}) $e');
+ }
+ }
+
void _writePropertyAccessorElement(PropertyAccessorElement e) {
e as PropertyAccessorElementImpl;
diff --git a/pkg/analyzer/test/src/summary/elements_test.dart b/pkg/analyzer/test/src/summary/elements_test.dart
index 2c410d6..b49c61b 100644
--- a/pkg/analyzer/test/src/summary/elements_test.dart
+++ b/pkg/analyzer/test/src/summary/elements_test.dart
@@ -4069,7 +4069,7 @@
synthetic get b @-1
returnType: double
parts
- a.dart
+ package:test/a.dart
topLevelVariables
static final a @19
type: int
@@ -7896,7 +7896,7 @@
nameOffset: 8
definingUnit
parts
- a.dart
+ package:test/a.dart
topLevelVariables
static final f @19
type: double Function(int)
@@ -20690,7 +20690,7 @@
nameOffset: 8
definingUnit
parts
- a.dart
+ package:test/a.dart
functions
main @16
returnType: dynamic
@@ -25379,7 +25379,9 @@
<unresolved>
definingUnit
parts
- :[invaliduri]
+ noSource
+ source 'package:test/a3.dart'
+ noSource
''');
}
@@ -25442,6 +25444,136 @@
''');
}
+ test_library_parts() async {
+ addSource('$testPackageLibPath/a.dart', 'part of my.lib;');
+ addSource('$testPackageLibPath/b.dart', 'part of my.lib;');
+ var library =
+ await buildLibrary('library my.lib; part "a.dart"; part "b.dart";');
+ checkElementText(library, r'''
+library
+ name: my.lib
+ nameOffset: 8
+ definingUnit
+ parts
+ package:test/a.dart
+ package:test/b.dart
+''');
+ }
+
+ test_library_parts_noRelativeUriStr() async {
+ final library = await buildLibrary(r'''
+part '${'foo'}.dart';
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ parts
+ noSource
+''');
+ }
+
+ test_library_parts_withPart_partOfName() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+part of my.lib;
+class B {}
+''');
+ final library = await buildLibrary(r'''
+library my.lib;
+part 'a.dart';
+class A {}
+''');
+ checkElementText(library, r'''
+library
+ name: my.lib
+ nameOffset: 8
+ definingUnit
+ classes
+ class A @37
+ constructors
+ synthetic @-1
+ parts
+ package:test/a.dart
+ classes
+ class B @22
+ constructors
+ synthetic @-1
+''');
+ }
+
+ test_library_parts_withPart_partOfUri() async {
+ newFile('$testPackageLibPath/a.dart', r'''
+part of 'test.dart';
+class B {}
+''');
+ final library = await buildLibrary(r'''
+part 'a.dart';
+class A {}
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ classes
+ class A @21
+ constructors
+ synthetic @-1
+ parts
+ package:test/a.dart
+ classes
+ class B @27
+ constructors
+ synthetic @-1
+''');
+ }
+
+ test_library_parts_withRelativeUri_notPart_emptyUriSelf() async {
+ final library = await buildLibrary(r'''
+part '';
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ parts
+ source 'package:test/test.dart'
+''');
+ }
+
+ test_library_parts_withRelativeUri_notPart_library() async {
+ newFile('$testPackageLibPath/a.dart', '');
+ final library = await buildLibrary(r'''
+part 'a.dart';
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ parts
+ source 'package:test/a.dart'
+''');
+ }
+
+ test_library_parts_withRelativeUri_notPart_notExists() async {
+ final library = await buildLibrary(r'''
+part 'a.dart';
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ parts
+ source 'package:test/a.dart'
+''');
+ }
+
+ test_library_parts_withRelativeUriString() async {
+ final library = await buildLibrary(r'''
+part ':';
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ parts
+ noSource
+''');
+ }
+
test_localFunctions() async {
var library = await buildLibrary(r'''
f() {
@@ -29455,7 +29587,7 @@
synthetic static get foo @-1
returnType: int
parts
- a.dart
+ package:test/a.dart
metadata
Annotation
atSign: @ @17
@@ -29464,7 +29596,7 @@
staticElement: self::@getter::foo
staticType: null
element: self::@getter::foo
- b.dart
+ package:test/b.dart
metadata
Annotation
atSign: @ @38
@@ -29698,7 +29830,7 @@
synthetic static get a @-1
returnType: dynamic
parts
- foo.dart
+ package:test/foo.dart
metadata
Annotation
atSign: @ @11
@@ -29724,7 +29856,7 @@
// The difference with the test above is that we ask the part first.
// There was a bug that we were not loading library directives.
- expect(library.parts[0].metadata, isEmpty);
+ expect(library.parts2[0].metadata, isEmpty);
}
test_metadata_prefixed_variable() async {
@@ -32861,78 +32993,6 @@
''');
}
- /// TODO(scheglov) The part should disappear after finishing [PartElement].
- test_part_emptyUri() async {
- var library = await buildLibrary(r'''
-part '';
-class B extends A {}
-''');
- checkElementText(library, r'''
-library
- definingUnit
- classes
- class B @15
- constructors
- synthetic @-1
- parts
-
- classes
- class B @15
- constructors
- synthetic @-1
-''');
- }
-
- test_part_uri() async {
- var library = await buildLibrary('''
-part 'foo.dart';
-''');
- expect(library.parts[0].uri, 'foo.dart');
- }
-
- test_parts() async {
- addSource('$testPackageLibPath/a.dart', 'part of my.lib;');
- addSource('$testPackageLibPath/b.dart', 'part of my.lib;');
- var library =
- await buildLibrary('library my.lib; part "a.dart"; part "b.dart";');
- checkElementText(library, r'''
-library
- name: my.lib
- nameOffset: 8
- definingUnit
- parts
- a.dart
- b.dart
-''');
- }
-
- test_parts_invalidUri() async {
- addSource('$testPackageLibPath/foo/bar.dart', 'part of my.lib;');
- var library = await buildLibrary('library my.lib; part "foo/";');
- checkElementText(library, r'''
-library
- name: my.lib
- nameOffset: 8
- definingUnit
- parts
- foo/
-''');
- }
-
- test_parts_invalidUri_nullStringValue() async {
- addSource('$testPackageLibPath/foo/bar.dart', 'part of my.lib;');
- var library = await buildLibrary(r'''
-library my.lib;
-part "${foo}/bar.dart";
-''');
- checkElementText(library, r'''
-library
- name: my.lib
- nameOffset: 8
- definingUnit
-''');
- }
-
test_propagated_type_refers_to_closure() async {
var library = await buildLibrary('''
void f() {
@@ -34259,7 +34319,7 @@
alias: self::@typeAlias::F
returnType: void
parts
- a.dart
+ package:test/a.dart
classes
class C @17
constructors
@@ -34369,7 +34429,7 @@
aliasedElement: GenericFunctionTypeElement
returnType: dynamic
parts
- a.dart
+ package:test/a.dart
topLevelVariables
static c @13
type: C
@@ -34417,7 +34477,7 @@
nameOffset: 8
definingUnit
parts
- a.dart
+ package:test/a.dart
classes
class C @17
constructors
@@ -34466,7 +34526,7 @@
aliasedType: dynamic Function()
aliasedElement: GenericFunctionTypeElement
returnType: dynamic
- b.dart
+ package:test/b.dart
topLevelVariables
static c @13
type: C
@@ -34512,7 +34572,7 @@
nameOffset: 8
definingUnit
parts
- a.dart
+ package:test/a.dart
classes
class C @17
constructors
@@ -37886,16 +37946,6 @@
''');
}
- test_unresolved_part() async {
- var library = await buildLibrary("part 'foo.dart';", allowErrors: true);
- checkElementText(library, r'''
-library
- definingUnit
- parts
- foo.dart
-''');
- }
-
test_unused_type_parameter() async {
var library = await buildLibrary('''
class C<T> {
@@ -38055,7 +38105,7 @@
static get x @39
returnType: int
parts
- a.dart
+ package:test/a.dart
topLevelVariables
synthetic static x @-1
type: int
@@ -38093,7 +38143,7 @@
type: int
returnType: void
parts
- a.dart
+ package:test/a.dart
topLevelVariables
synthetic static x @-1
type: int
@@ -38115,14 +38165,14 @@
nameOffset: 8
definingUnit
parts
- a.dart
+ package:test/a.dart
topLevelVariables
synthetic static x @-1
type: int
accessors
static get x @24
returnType: int
- b.dart
+ package:test/b.dart
topLevelVariables
synthetic static x @-1
type: int
@@ -38392,7 +38442,7 @@
synthetic static get b @-1
returnType: double
parts
- a.dart
+ package:test/a.dart
topLevelVariables
static final a @19
type: int
@@ -38447,7 +38497,7 @@
nameOffset: 8
definingUnit
parts
- a.dart
+ package:test/a.dart
topLevelVariables
synthetic static x @-1
type: int
@@ -38457,7 +38507,7 @@
requiredPositional _ @31
type: int
returnType: void
- b.dart
+ package:test/b.dart
topLevelVariables
synthetic static x @-1
type: int
diff --git a/pkg/analyzer/test/src/summary/macro_test.dart b/pkg/analyzer/test/src/summary/macro_test.dart
index 0f417e7..2a23acf 100644
--- a/pkg/analyzer/test/src/summary/macro_test.dart
+++ b/pkg/analyzer/test/src/summary/macro_test.dart
@@ -1806,7 +1806,8 @@
}
if (expected != null) {
- final x = library.parts.single.topLevelVariables.single;
+ final partElement = library.parts2.single as PartElementWithPart;
+ final x = partElement.includedUnit.topLevelVariables.single;
expect(x.name, 'x');
x as ConstTopLevelVariableElementImpl;
final actual = (x.constantInitializer as SimpleStringLiteral).value;
@@ -1868,7 +1869,8 @@
library.definingCompilationUnit.getType('A'),
);
- var x = library.parts.single.topLevelVariables.single;
+ final partElement = library.parts2.single as PartElementWithPart;
+ final x = partElement.includedUnit.topLevelVariables.single;
expect(x.name, 'x');
x as ConstTopLevelVariableElementImpl;
var x_literal = x.constantInitializer as SimpleStringLiteral;
diff --git a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
index f7f158b..1b9b710 100644
--- a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
+++ b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
@@ -879,7 +879,7 @@
_writeNamedChildEntities(node);
_writeElement('element', node.element);
_writeRaw('uriContent', node.uriContent);
- _writeElement('uriElement', node.uriElement);
+ _writePartUnitElement('uriElement', node.uriElement);
_writeSource('uriSource', node.uriSource);
});
}
@@ -1330,6 +1330,10 @@
return '${_referenceToString(parent)}::$name';
}
+ String _stringOfSource(Source source) {
+ return '${source.uri}';
+ }
+
String _substitutionMapStr(Map<TypeParameterElement, DartType> map) {
var entriesStr = map.entries.map((entry) {
return '${entry.key.name}: ${_typeStr(entry.value)}';
@@ -1377,6 +1381,8 @@
});
} else if (element is MultiplyDefinedElement) {
_sink.writeln('<null>');
+ } else if (element is PartElement) {
+ _writePartElement(element);
} else {
final referenceStr = _elementToReferenceString(element);
_sink.writeln(referenceStr);
@@ -1497,6 +1503,36 @@
}
}
+ void _writePartElement(PartElement element) {
+ if (element is PartElementWithPart) {
+ _writeln('PartElementWithPart');
+ _withIndent(() {
+ final uriStr = _stringOfSource(element.includedUnit.source);
+ _writelnWithIndent('part: $uriStr');
+ });
+ } else if (element is PartElementWithSource) {
+ _writeln('PartElementWithSource');
+ _withIndent(() {
+ final uriStr = _stringOfSource(element.uriSource);
+ _writelnWithIndent('source: $uriStr');
+ });
+ } else {
+ _writeln('PartElement');
+ }
+ }
+
+ void _writePartUnitElement(String name, Element? element) {
+ if (_withResolution) {
+ _sink.write(_indent);
+ _sink.write('$name: ');
+ if (element is CompilationUnitElement) {
+ _sink.writeln('unitElement ${_stringOfSource(element.source)}');
+ } else {
+ _sink.writeln('notUnitElement');
+ }
+ }
+ }
+
void _writeRaw(String name, Object? value) {
_writelnWithIndent('$name: $value');
}
diff --git a/pkg/analyzer_cli/lib/src/analyzer_impl.dart b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
index 7e40fff..06fe1f4 100644
--- a/pkg/analyzer_cli/lib/src/analyzer_impl.dart
+++ b/pkg/analyzer_cli/lib/src/analyzer_impl.dart
@@ -67,9 +67,8 @@
return;
}
// Add compilation units.
- addCompilationUnitSource(library.definingCompilationUnit, units);
- for (var child in library.parts) {
- addCompilationUnitSource(child, units);
+ for (final unitElement in library.units) {
+ addCompilationUnitSource(unitElement, units);
}
// Add referenced libraries.
for (var child in library.importedLibraries) {
@@ -164,7 +163,7 @@
bool _isAnalyzedLibrary(LibraryElement library) {
var source = library.source;
if (source.uri.isScheme('dart')) {
- return options.showSdkWarnings;
+ return false;
} else if (source.uri.isScheme('package')) {
if (_isPathInPubCache(source.fullName)) {
return false;
@@ -183,12 +182,8 @@
var packageName = uri.pathSegments.first;
if (packageName == _selfPackageName) {
return true;
- } else if (!options.showPackageWarnings) {
- return false;
- } else if (options.showPackageWarningsPrefix == null) {
- return true;
} else {
- return packageName.startsWith(options.showPackageWarningsPrefix!);
+ return false;
}
}
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 56b1585..7b82956 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -417,11 +417,6 @@
bool _shouldBeFatal(ErrorSeverity severity, CommandLineOptions options) {
if (severity == ErrorSeverity.ERROR) {
return true;
- } else if (severity == ErrorSeverity.WARNING &&
- (options.warningsAreFatal || options.infosAreFatal)) {
- return true;
- } else if (severity == ErrorSeverity.INFO && options.infosAreFatal) {
- return true;
} else {
return false;
}
@@ -449,11 +444,6 @@
_equalMaps(newOptions.declaredVariables, previous.declaredVariables) &&
newOptions.log == previous.log &&
newOptions.disableHints == previous.disableHints &&
- newOptions.showPackageWarnings == previous.showPackageWarnings &&
- newOptions.showPackageWarningsPrefix ==
- previous.showPackageWarningsPrefix &&
- newOptions.showSdkWarnings == previous.showSdkWarnings &&
- newOptions.lints == previous.lints &&
newOptions.defaultLanguageVersion == previous.defaultLanguageVersion &&
newOptions.disableCacheFlushing == previous.disableCacheFlushing &&
_equalLists(
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index 23a11be..bb914e3 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -23,7 +23,6 @@
const _enableInitializingFormalAccessFlag = 'initializing-formal-access';
const _ignoreUnrecognizedFlagsFlag = 'ignore-unrecognized-flags';
const _implicitCastsFlag = 'implicit-casts';
-const _lintsFlag = 'lints';
const _noImplicitDynamicFlag = 'no-implicit-dynamic';
const _packagesOption = 'packages';
const _sdkPathOption = 'dart-sdk';
@@ -98,24 +97,9 @@
/// Batch mode (for unit testing)
final bool batchMode;
- /// Whether to show package: warnings
- final bool showPackageWarnings;
-
- /// If not null, show package: warnings only for matching packages.
- final String? showPackageWarningsPrefix;
-
- /// Whether to show SDK warnings
- final bool showSdkWarnings;
-
/// The source files to analyze
final List<String> sourceFiles;
- /// Whether to treat warnings as fatal
- final bool warningsAreFatal;
-
- /// Whether to treat info level items as fatal
- final bool infosAreFatal;
-
/// Emit output in a verbose mode.
final bool verbose;
@@ -141,15 +125,7 @@
machineFormat = args['format'] == 'machine',
perfReport = castNullable(args['x-perf-report']),
batchMode = cast(args['batch']),
- showPackageWarnings = cast(args['show-package-warnings']) ||
- cast(args['package-warnings']) ||
- args['x-package-warnings-prefix'] != null,
- showPackageWarningsPrefix =
- castNullable(args['x-package-warnings-prefix']),
- showSdkWarnings = cast(args['sdk-warnings']),
sourceFiles = args.rest,
- infosAreFatal = cast(args['fatal-infos']) || cast(args['fatal-hints']),
- warningsAreFatal = cast(args['fatal-warnings']),
trainSnapshot = cast(args['train-snapshot']),
verbose = cast(args['verbose']),
color = cast(args['color']) {
@@ -201,8 +177,6 @@
bool? get implicitCasts => _argResults[_implicitCastsFlag] as bool?;
- bool? get lints => _argResults[_lintsFlag] as bool?;
-
bool? get noImplicitDynamic => _argResults[_noImplicitDynamicFlag] as bool?;
/// Update the [analysisOptions] with flags that the user specified
@@ -233,11 +207,6 @@
analysisOptions.implicitCasts = implicitCasts;
}
- var lints = this.lints;
- if (lints != null) {
- analysisOptions.lint = lints;
- }
-
var noImplicitDynamic = this.noImplicitDynamic;
if (noImplicitDynamic != null) {
analysisOptions.implicitDynamic = !noImplicitDynamic;
@@ -404,10 +373,6 @@
defaultsTo: false,
negatable: false,
hide: hide || ddc);
- if (!ddc) {
- parser.addFlag(_lintsFlag,
- help: 'Show lint results.', defaultsTo: null, negatable: true);
- }
}
static String _getVersion() {
@@ -453,12 +418,6 @@
help: 'Do not show hint results.',
defaultsTo: false,
negatable: false)
- ..addFlag('fatal-infos',
- help: 'Treat infos as fatal.', defaultsTo: false, negatable: false)
- ..addFlag('fatal-warnings',
- help: 'Treat non-type warnings as fatal.',
- defaultsTo: false,
- negatable: false)
..addFlag('help',
abbr: 'h',
help:
@@ -500,56 +459,22 @@
..addOption('x-perf-report',
help: 'Writes a performance report to the given file (experimental).',
hide: hide)
- ..addOption('x-package-warnings-prefix',
- help:
- 'Show warnings from package: imports that match the given prefix (deprecated).',
- hide: hide)
..addFlag('enable-conditional-directives',
help:
'deprecated -- Enable support for conditional directives (DEP 40).',
defaultsTo: false,
negatable: false,
hide: hide)
- ..addFlag('show-package-warnings',
- help: 'Show warnings from package: imports (deprecated).',
- defaultsTo: false,
- negatable: false,
- hide: hide)
- ..addFlag('sdk-warnings',
- help: 'Show warnings from SDK imports (deprecated).',
- defaultsTo: false,
- negatable: false,
- hide: hide)
..addFlag('log',
help: 'Log additional messages and exceptions.',
defaultsTo: false,
negatable: false,
hide: hide)
- ..addFlag('enable_type_checks',
- help: 'Check types in constant evaluation (deprecated).',
- defaultsTo: false,
- negatable: false,
- hide: true)
..addFlag('use-analysis-driver-memory-byte-store',
help: 'Use memory byte store, not the file system cache.',
defaultsTo: false,
negatable: false,
hide: hide)
- ..addFlag('fatal-hints',
- help: 'Treat hints as fatal (deprecated: use --fatal-infos).',
- defaultsTo: false,
- negatable: false,
- hide: hide)
- ..addFlag('fatal-lints',
- help: 'Treat lints as fatal.',
- defaultsTo: false,
- negatable: false,
- hide: hide)
- ..addFlag('package-warnings',
- help: 'Show warnings from package: imports (deprecated).',
- defaultsTo: false,
- negatable: false,
- hide: hide)
..addMultiOption('url-mapping',
help: '--url-mapping=libraryUri,/path/to/library.dart directs the '
'analyzer to use "library.dart" as the source for an import '
diff --git a/pkg/analyzer_cli/lib/src/perf_report.dart b/pkg/analyzer_cli/lib/src/perf_report.dart
index 04caa35..216c19a 100644
--- a/pkg/analyzer_cli/lib/src/perf_report.dart
+++ b/pkg/analyzer_cli/lib/src/perf_report.dart
@@ -35,9 +35,6 @@
var optionsJson = <String, dynamic>{
'dartSdkPath': options.dartSdkPath,
- 'showPackageWarnings': options.showPackageWarnings,
- 'showPackageWarningsPrefix': options.showPackageWarningsPrefix,
- 'showSdkWarnings': options.showSdkWarnings,
'definedVariables': options.declaredVariables,
'packageConfigPath': options.defaultPackagesPath,
'sourceFiles': options.sourceFiles,
diff --git a/pkg/analyzer_cli/test/all.dart b/pkg/analyzer_cli/test/all.dart
index c56ee1b..b7f9afa 100644
--- a/pkg/analyzer_cli/test/all.dart
+++ b/pkg/analyzer_cli/test/all.dart
@@ -8,7 +8,6 @@
import 'errors_reported_once_test.dart' as errors_reported_once;
import 'errors_upgrade_fails_cli_test.dart' as errors_upgrade_fails_cli;
import 'options_test.dart' as options;
-import 'package_prefix_test.dart' as package_prefix;
import 'perf_report_test.dart' as perf_report;
import 'reporter_test.dart' as reporter;
import 'strong_mode_test.dart' as strong_mode;
@@ -20,7 +19,6 @@
errors_reported_once.main();
errors_upgrade_fails_cli.main();
options.main();
- package_prefix.main();
perf_report.main();
reporter.main();
strong_mode.main();
diff --git a/pkg/analyzer_cli/test/driver_test.dart b/pkg/analyzer_cli/test/driver_test.dart
index c26a9e6..154362b 100644
--- a/pkg/analyzer_cli/test/driver_test.dart
+++ b/pkg/analyzer_cli/test/driver_test.dart
@@ -166,11 +166,6 @@
expect(exitCode, 3);
}
- Future<void> test_fatalHints() async {
- await drive('data/file_with_hint.dart', args: ['--fatal-hints']);
- expect(exitCode, 1);
- }
-
Future<void> test_missingDartFile() async {
await drive('data/NO_DART_FILE_HERE.dart');
expect(exitCode, 3);
@@ -246,41 +241,6 @@
expect(containsLintRuleEntry(options), false);
}
- Future<void> test_defaultLints_generatedLints() async {
- await _runLinter_defaultLints();
- expect(bulletToDash(outSink),
- contains('lint - Name types using UpperCamelCase'));
- }
-
- Future<void> test_defaultLints_getsDefaultLints() async {
- await _runLinter_defaultLints();
-
- /// Lints should be enabled.
- expect(analysisOptions.lint, isTrue);
-
- /// Default list should include camel_case_types.
- var lintNames = analysisOptions.lintRules.map((r) => r.name);
- expect(lintNames, contains('camel_case_types'));
- }
-
- Future<void> test_lintsInOptions_generatedLints() async {
- await _runLinter_lintsInOptions();
- expect(bulletToDash(outSink),
- contains('lint - Name types using UpperCamelCase'));
- }
-
- Future<void> test_lintsInOptions_getAnalysisOptions() async {
- await _runLinter_lintsInOptions();
-
- /// Lints should be enabled.
- expect(analysisOptions.lint, isTrue);
-
- /// The analysis options file specifies 'camel_case_types' and 'sort_pub_dependencies'.
- var lintNames = analysisOptions.lintRules.map((r) => r.name);
- expect(lintNames,
- orderedEquals(['camel_case_types', 'sort_pub_dependencies']));
- }
-
Future<void> test_noLints_lintsDisabled() async {
await _runLinter_noLintsFlag();
expect(analysisOptions.lint, isFalse);
@@ -305,16 +265,6 @@
YamlMap _parseOptions(String src) =>
AnalysisOptionsProvider().getOptionsFromString(src);
- Future<void> _runLinter_defaultLints() async {
- await drive('data/linter_project/test_file.dart',
- options: 'data/linter_project/$analysisOptionsYaml', args: ['--lints']);
- }
-
- Future<void> _runLinter_lintsInOptions() async {
- await drive('data/linter_project/test_file.dart',
- options: 'data/linter_project/$analysisOptionsYaml', args: ['--lints']);
- }
-
Future<void> _runLinter_noLintsFlag() async {
await drive('data/no_lints_project/test_file.dart',
options: 'data/no_lints_project/$analysisOptionsYaml');
@@ -468,24 +418,6 @@
expect(outSink.toString(), contains('1 error and 1 warning found.'));
}
- Future<void> test_includeDirective() async {
- var testDir = path.join(
- testDirectory, 'data', 'options_include_directive_tests_project');
- await drive(
- path.join(testDir, 'lib', 'test_file.dart'),
- args: [
- '--fatal-warnings',
- '--packages',
- path.join(testDir, '_packages'),
- ],
- options: path.join(testDir, 'analysis_options.yaml'),
- );
- expect(exitCode, 3);
- expect(outSink.toString(), contains('Unnecessary cast.'));
- expect(outSink.toString(), contains('isn\'t defined'));
- expect(outSink.toString(), contains('Avoid empty else statements'));
- }
-
Future<void> test_multiple_inputs_two_directories() async {
await driveMany([
'data/multiple_inputs_two_directories/bin',
@@ -507,23 +439,6 @@
expect(outSink.toString().contains('[info]'), isFalse);
}
- Future<void> test_withFlags_overrideFatalWarning() async {
- await drive('data/options_tests_project/test_file.dart',
- args: ['--fatal-warnings'],
- options: 'data/options_tests_project/$analysisOptionsYaml');
-
- // missing_return: error
- var undefined_function = AnalysisError(
- TestSource(), 0, 1, CompileTimeErrorCode.UNDEFINED_FUNCTION, [
- ['x']
- ]);
- expect(processorFor(undefined_function).severity, ErrorSeverity.WARNING);
- // Should not be made fatal by `--fatal-warnings`.
- expect(bulletToDash(outSink),
- contains("warning - The function 'baz' isn't defined"));
- expect(outSink.toString(), contains('1 error and 1 warning found.'));
- }
-
Future<void> _driveBasic() async {
await drive('data/options_tests_project/test_file.dart',
options: 'data/options_tests_project/$analysisOptionsYaml');
diff --git a/pkg/analyzer_cli/test/mocks.dart b/pkg/analyzer_cli/test/mocks.dart
index 3de1eb3..7b2cdc8 100644
--- a/pkg/analyzer_cli/test/mocks.dart
+++ b/pkg/analyzer_cli/test/mocks.dart
@@ -62,8 +62,6 @@
class MockCommandLineOptions implements CommandLineOptions {
bool enableTypeChecks = false;
@override
- bool infosAreFatal = false;
- @override
bool jsonFormat = false;
@override
bool machineFormat = false;
diff --git a/pkg/analyzer_cli/test/options_test.dart b/pkg/analyzer_cli/test/options_test.dart
index 690b5c9..397a42f 100644
--- a/pkg/analyzer_cli/test/options_test.dart
+++ b/pkg/analyzer_cli/test/options_test.dart
@@ -59,9 +59,7 @@
expect(options.disableCacheFlushing, isFalse);
expect(options.disableHints, isFalse);
expect(options.enabledExperiments, isEmpty);
- expect(options.lints, isNull);
expect(options.displayVersion, isFalse);
- expect(options.infosAreFatal, isFalse);
expect(options.ignoreUnrecognizedFlags, isFalse);
expect(options.implicitCasts, isNull);
expect(options.log, isFalse);
@@ -69,10 +67,7 @@
expect(options.machineFormat, isFalse);
expect(options.noImplicitDynamic, isNull);
expect(options.batchMode, isFalse);
- expect(options.showPackageWarnings, isFalse);
- expect(options.showSdkWarnings, isFalse);
expect(options.sourceFiles, equals(['foo.dart']));
- expect(options.warningsAreFatal, isFalse);
expect(options.trainSnapshot, isFalse);
});
@@ -171,16 +166,6 @@
});
});
- test('hintsAreFatal', () {
- var options = parse(['--dart-sdk', '.', '--fatal-hints', 'foo.dart'])!;
- expect(options.infosAreFatal, isTrue);
- });
-
- test('infosAreFatal', () {
- var options = parse(['--dart-sdk', '.', '--fatal-infos', 'foo.dart'])!;
- expect(options.infosAreFatal, isTrue);
- });
-
test('log', () {
var options = parse(['--dart-sdk', '.', '--log', 'foo.dart'])!;
expect(options.log, isTrue);
@@ -213,22 +198,6 @@
expect(options.defaultAnalysisOptionsPath, endsWith('options.yaml'));
});
- test('lints', () {
- var options = parse(['--dart-sdk', '.', '--lints', 'foo.dart'])!;
- expect(options.lints, isTrue);
- });
-
- test('package warnings', () {
- var options =
- parse(['--dart-sdk', '.', '--package-warnings', 'foo.dart'])!;
- expect(options.showPackageWarnings, isTrue);
- });
-
- test('sdk warnings', () {
- var options = parse(['--dart-sdk', '.', '--sdk-warnings', 'foo.dart'])!;
- expect(options.showSdkWarnings, isTrue);
- });
-
test('sourceFiles', () {
var options = parse([
'--dart-sdk',
@@ -242,12 +211,6 @@
equals(['foo.dart', 'foo2.dart', 'foo3.dart']));
});
- test('warningsAreFatal', () {
- var options =
- parse(['--dart-sdk', '.', '--fatal-warnings', 'foo.dart'])!;
- expect(options.warningsAreFatal, isTrue);
- });
-
test('ignore unrecognized flags', () {
var options = parse([
'--ignore-unrecognized-flags',
@@ -464,52 +427,6 @@
);
}
- void test_updateAnalysisOptions_lints() {
- // Turn lints on.
- _applyAnalysisOptions(
- ['--lints', 'a.dart'],
- (analysisOptions) {
- analysisOptions.lint = false;
- },
- (analysisOptions) {
- expect(analysisOptions.lint, isTrue);
- },
- );
-
- // Turn lints off.
- _applyAnalysisOptions(
- ['--no-lints', 'a.dart'],
- (analysisOptions) {
- analysisOptions.lint = true;
- },
- (analysisOptions) {
- expect(analysisOptions.lint, isFalse);
- },
- );
-
- // Don't change if not provided, false.
- _applyAnalysisOptions(
- ['a.dart'],
- (analysisOptions) {
- analysisOptions.lint = false;
- },
- (analysisOptions) {
- expect(analysisOptions.lint, isFalse);
- },
- );
-
- // Don't change if not provided, true.
- _applyAnalysisOptions(
- ['a.dart'],
- (analysisOptions) {
- analysisOptions.lint = true;
- },
- (analysisOptions) {
- expect(analysisOptions.lint, isTrue);
- },
- );
- }
-
void test_updateAnalysisOptions_noImplicitDynamic() {
_applyAnalysisOptions(
['--no-implicit-dynamic', 'a.dart'],
diff --git a/pkg/analyzer_cli/test/package_prefix_test.dart b/pkg/analyzer_cli/test/package_prefix_test.dart
deleted file mode 100644
index 9aa0d57..0000000
--- a/pkg/analyzer_cli/test/package_prefix_test.dart
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:io' show exitCode;
-
-import 'package:analyzer_cli/src/driver.dart' show Driver, outSink, errorSink;
-import 'package:analyzer_cli/src/options.dart' show ExitHandler, exitHandler;
-import 'package:path/path.dart';
-import 'package:test/test.dart';
-
-import 'utils.dart' show testDirectory;
-
-void main() {
- group('--x-package-warnings-prefix', () {
- late _Runner runner;
-
- setUp(() {
- runner = _Runner.setUp();
- });
-
- tearDown(() {
- runner.tearDown();
- });
-
- test('shows only the hint whose package matches the prefix', () async {
- await runner.run2([
- '--packages',
- join(testDirectory, 'data', 'package_prefix', 'packagelist'),
- '--x-package-warnings-prefix=f',
- join(testDirectory, 'data', 'package_prefix', 'main.dart')
- ]);
- expect(runner.stdout, contains('1 hint found'));
- expect(runner.stdout, contains('Unused import'));
- expect(runner.stdout,
- contains(join('package_prefix', 'pkg', 'foo', 'foo.dart')));
- expect(runner.stdout, isNot(contains('bar.dart')));
- });
- });
-}
-
-class _Runner {
- final _stdout = StringBuffer();
- final _stderr = StringBuffer();
-
- final StringSink _savedOutSink;
- final StringSink _savedErrorSink;
- final int _savedExitCode;
- final ExitHandler _savedExitHandler;
-
- _Runner.setUp()
- : _savedOutSink = outSink,
- _savedErrorSink = errorSink,
- _savedExitHandler = exitHandler,
- _savedExitCode = exitCode {
- outSink = _stdout;
- errorSink = _stderr;
- exitHandler = (_) {};
- }
-
- String get stderr => _stderr.toString();
-
- String get stdout => _stdout.toString();
-
- Future<void> run2(List<String> args) async {
- await Driver().start(args);
- if (stderr.isNotEmpty) {
- fail('Unexpected output to stderr:\n$stderr');
- }
- }
-
- void tearDown() {
- outSink = _savedOutSink;
- errorSink = _savedErrorSink;
- exitCode = _savedExitCode;
- exitHandler = _savedExitHandler;
- }
-}
diff --git a/pkg/analyzer_cli/test/reporter_test.dart b/pkg/analyzer_cli/test/reporter_test.dart
index 54a2964..4f65380 100644
--- a/pkg/analyzer_cli/test/reporter_test.dart
+++ b/pkg/analyzer_cli/test/reporter_test.dart
@@ -28,7 +28,6 @@
options = MockCommandLineOptions();
options.enableTypeChecks = false;
- options.infosAreFatal = false;
options.jsonFormat = false;
options.machineFormat = false;
options.verbose = false;
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
index 70b8e89..7257b10 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
@@ -578,7 +578,7 @@
// Usually if the offset is greater than the token it can't be in the comment
// but for EOF this is not the case - the offset at EOF could still be inside
// the comment if EOF is on the same line as the comment.
- if (token.type != TokenType.EOF && offset >= token.offset) {
+ if (!token.isEof && offset >= token.offset) {
return null;
}
final startToken = token;
diff --git a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
index 1a89f2a..29b6891 100644
--- a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
@@ -383,7 +383,21 @@
@override
void visitPartDirective(PartDirective node) {
- _addUriDirectiveRegion(node, node.element);
+ final element = node.element;
+ if (element is PartElementWithPart) {
+ computer._addRegionForNode(node.uri, element.includedUnit);
+ } else if (element is PartElementWithSource) {
+ final uriNode = node.uri;
+ final source = element.uriSource;
+ computer.collector.addRegion(
+ uriNode.offset,
+ uriNode.length,
+ protocol.ElementKind.FILE,
+ protocol.Location(source.fullName, 0, 0, 0, 0,
+ endLine: 0, endColumn: 0),
+ );
+ }
+
super.visitPartDirective(node);
}
diff --git a/pkg/analyzer_plugin/lib/utilities/range_factory.dart b/pkg/analyzer_plugin/lib/utilities/range_factory.dart
index b967af5..cfbfea8 100644
--- a/pkg/analyzer_plugin/lib/utilities/range_factory.dart
+++ b/pkg/analyzer_plugin/lib/utilities/range_factory.dart
@@ -60,6 +60,35 @@
}
}
+ /// Return the deletion range of the [node], considering the spaces and
+ /// comments before and after it.
+ SourceRange deletionRange(AstNode node) {
+ var begin = node.beginToken;
+ begin = begin.precedingComments ?? begin;
+
+ var end = node.endToken.next!;
+ end = end.precedingComments ?? end;
+
+ int startOffset;
+ int endOffset;
+ if (end.isEof) {
+ var type = begin.type;
+ if (node is AnnotatedNode &&
+ (type == TokenType.SINGLE_LINE_COMMENT ||
+ type == TokenType.MULTI_LINE_COMMENT)) {
+ var firstToken = node.firstTokenAfterCommentAndMetadata;
+ startOffset = firstToken.previous!.end;
+ } else {
+ startOffset = begin.previous!.end;
+ }
+ endOffset = node.endToken.end;
+ } else {
+ startOffset = begin.offset;
+ endOffset = end.offset;
+ }
+ return startOffsetEndOffset(startOffset, endOffset);
+ }
+
/// Return a source range that covers the name of the given [element].
SourceRange elementName(Element element) {
return SourceRange(element.nameOffset, element.nameLength);
diff --git a/pkg/analyzer_plugin/test/utilities/range_factory_test.dart b/pkg/analyzer_plugin/test/utilities/range_factory_test.dart
index 6825c53..c6757b2c 100644
--- a/pkg/analyzer_plugin/test/utilities/range_factory_test.dart
+++ b/pkg/analyzer_plugin/test/utilities/range_factory_test.dart
@@ -307,6 +307,170 @@
@reflectiveTest
class RangeFactoryTest extends AbstractSingleUnitTest {
+ Future<void> test_deletionRange_first() async {
+ await _deletionRange(declarationIndex: 0, '''
+class A {}
+
+class B {}
+''', expected: '''
+class B {}
+''');
+ }
+
+ Future<void> test_deletionRange_first_comment() async {
+ await _deletionRange(declarationIndex: 0, '''
+/// for a
+class A {}
+
+/// for b
+class B {}
+''', expected: '''
+/// for b
+class B {}
+''');
+ }
+
+ Future<void> test_deletionRange_first_directive() async {
+ await _deletionRange(declarationIndex: 0, '''
+import 'dart:collection';
+
+class A {}
+
+class B {}
+''', expected: '''
+import 'dart:collection';
+
+class B {}
+''');
+ }
+
+ Future<void> test_deletionRange_first_directive_comment() async {
+ await _deletionRange(declarationIndex: 0, '''
+import 'dart:collection';
+
+/// for a
+class A {}
+
+/// for b
+class B {}
+''', expected: '''
+import 'dart:collection';
+
+/// for b
+class B {}
+''');
+ }
+
+ Future<void> test_deletionRange_last() async {
+ await _deletionRange(declarationIndex: 1, '''
+/// for a
+class A {}
+
+class B {}
+''', expected: '''
+/// for a
+class A {}
+''');
+ }
+
+ Future<void> test_deletionRange_last_before_comment() async {
+ await _deletionRange(declarationIndex: 1, '''
+/// for a
+class A {}
+
+class B {}
+
+// another
+''', expected: '''
+/// for a
+class A {}
+
+// another
+''');
+ }
+
+ Future<void> test_deletionRange_last_multiLineComment() async {
+ await _deletionRange(declarationIndex: 1, '''
+/// for a
+class A {}
+
+/**
+ * for b
+ */
+class B {}
+''', expected: '''
+/// for a
+class A {}
+''');
+ }
+
+ Future<void> test_deletionRange_last_singeLineComment() async {
+ await _deletionRange(declarationIndex: 1, '''
+/// for a
+class A {}
+
+/// for b
+class B {}
+''', expected: '''
+/// for a
+class A {}
+''');
+ }
+
+ Future<void> test_deletionRange_middle() async {
+ await _deletionRange(declarationIndex: 1, '''
+class A {}
+
+class B {}
+
+class C {}
+''', expected: '''
+class A {}
+
+class C {}
+''');
+ }
+
+ Future<void> test_deletionRange_middle_comment() async {
+ await _deletionRange(declarationIndex: 1, '''
+/// for a
+class A {}
+
+/// for b
+class B {}
+
+/// for c
+class C {}
+''', expected: '''
+/// for a
+class A {}
+
+/// for c
+class C {}
+''');
+ }
+
+ Future<void> test_deletionRange_variableDeclaration() async {
+ await _deletionRange(declarationIndex: 0, '''
+var x = 1;
+
+class B {}
+''', expected: '''
+class B {}
+''');
+ }
+
+ Future<void> test_deletionRange_variableDeclaration_comment() async {
+ await _deletionRange(declarationIndex: 0, '''
+// something
+var x = 1;
+
+class B {}
+''', expected: '''
+class B {}
+''');
+ }
+
Future<void> test_elementName() async {
await resolveTestCode('class ABC {}');
var element = findElement.class_('ABC');
@@ -403,4 +567,14 @@
var mainName = mainFunction.name;
expect(range.token(mainName.beginToken), SourceRange(1, 4));
}
+
+ Future<void> _deletionRange(String code,
+ {required String expected, required int declarationIndex}) async {
+ await resolveTestCode(code);
+ var member = testUnit.declarations[declarationIndex];
+ var deletionRange = range.deletionRange(member);
+ var codeAfterDeletion = code.substring(0, deletionRange.offset) +
+ code.substring(deletionRange.end);
+ expect(codeAfterDeletion, expected);
+ }
}
diff --git a/pkg/async_helper/analysis_options.yaml b/pkg/async_helper/analysis_options.yaml
new file mode 100644
index 0000000..c36c2c5
--- /dev/null
+++ b/pkg/async_helper/analysis_options.yaml
@@ -0,0 +1 @@
+include: package:lints/core.yaml
diff --git a/pkg/async_helper/lib/async_minitest.dart b/pkg/async_helper/lib/async_minitest.dart
index 5b58930..e529aa4 100644
--- a/pkg/async_helper/lib/async_minitest.dart
+++ b/pkg/async_helper/lib/async_minitest.dart
@@ -286,6 +286,7 @@
void call(dynamic o);
}
+// ignore: camel_case_types
class isInstanceOf<T> implements _Matcher {
void call(dynamic o) {
Expect.type<T>(o);
diff --git a/pkg/async_helper/pubspec.yaml b/pkg/async_helper/pubspec.yaml
index dc909f9..daaf7a8 100644
--- a/pkg/async_helper/pubspec.yaml
+++ b/pkg/async_helper/pubspec.yaml
@@ -14,3 +14,7 @@
# Use 'any' constraints here; we get our versions from the DEPS file.
dependencies:
expect: any
+
+# Use 'any' constraints here; we get our versions from the DEPS file.
+dev_dependencies:
+ lints: any
diff --git a/pkg/build_integration/analysis_options.yaml b/pkg/build_integration/analysis_options.yaml
new file mode 100644
index 0000000..572dd23
--- /dev/null
+++ b/pkg/build_integration/analysis_options.yaml
@@ -0,0 +1 @@
+include: package:lints/recommended.yaml
diff --git a/pkg/build_integration/lib/file_system/multi_root.dart b/pkg/build_integration/lib/file_system/multi_root.dart
index 7fff8e7..7b8a048 100644
--- a/pkg/build_integration/lib/file_system/multi_root.dart
+++ b/pkg/build_integration/lib/file_system/multi_root.dart
@@ -4,6 +4,7 @@
import 'dart:async';
+// ignore: implementation_imports
import 'package:front_end/src/api_unstable/build_integration.dart';
/// Wraps a file system to create an overlay of files from multiple roots.
@@ -39,13 +40,14 @@
@override
FileSystemEntity entityForUri(Uri uri) =>
- new MultiRootFileSystemEntity(this, uri);
+ MultiRootFileSystemEntity(this, uri);
}
/// Entity that searches the multiple roots and resolve a, possibly multi-root,
/// entity to a plain entity under `multiRootFileSystem.original`.
class MultiRootFileSystemEntity implements FileSystemEntity {
final MultiRootFileSystem multiRootFileSystem;
+ @override
final Uri uri;
FileSystemEntity? _delegate;
Future<FileSystemEntity> get delegate async =>
@@ -54,7 +56,7 @@
Future<FileSystemEntity> _resolveEntity() async {
if (uri.isScheme(multiRootFileSystem.markerScheme)) {
if (!uri.isAbsolute) {
- throw new FileSystemException(
+ throw FileSystemException(
uri, "This MultiRootFileSystem only handles absolutes URIs: $uri");
}
var original = multiRootFileSystem.original;
diff --git a/pkg/build_integration/lib/file_system/single_root.dart b/pkg/build_integration/lib/file_system/single_root.dart
index 896dfc3..bf3d17c 100644
--- a/pkg/build_integration/lib/file_system/single_root.dart
+++ b/pkg/build_integration/lib/file_system/single_root.dart
@@ -2,6 +2,7 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+// ignore: implementation_imports
import 'package:front_end/src/api_unstable/build_integration.dart';
/// A [FileSystem] that resolves custom URIs to entities under a specified root
@@ -34,17 +35,17 @@
@override
FileSystemEntity entityForUri(Uri uri) {
if (!uri.isScheme(markerScheme)) {
- throw new FileSystemException(
+ throw FileSystemException(
uri,
"This SingleRootFileSystem only handles URIs with the '$markerScheme'"
" scheme and cannot handle URIs with scheme '${uri.scheme}': $uri");
}
if (!uri.path.startsWith('/')) {
- throw new FileSystemException(
+ throw FileSystemException(
uri, "This SingleRootFileSystem only handles absolutes URIs: $uri");
}
var path = uri.path.substring(1);
- return new SingleRootFileSystemEntity(
+ return SingleRootFileSystemEntity(
uri, original.entityForUri(root.resolve(path)));
}
}
@@ -53,6 +54,7 @@
/// that delegates all operations to an underlying entity in the original
/// `SingleRootFileSystem.filesystem`.
class SingleRootFileSystemEntity implements FileSystemEntity {
+ @override
final Uri uri;
final FileSystemEntity delegate;
diff --git a/pkg/build_integration/pubspec.yaml b/pkg/build_integration/pubspec.yaml
index fbb8715..7045b18 100644
--- a/pkg/build_integration/pubspec.yaml
+++ b/pkg/build_integration/pubspec.yaml
@@ -14,4 +14,5 @@
# Use 'any' constraints here; we get our versions from the DEPS file.
dev_dependencies:
+ lints: any
test: any
diff --git a/pkg/build_integration/test/file_system/multi_root_test.dart b/pkg/build_integration/test/file_system/multi_root_test.dart
index 09d3cc9..9ca9230 100644
--- a/pkg/build_integration/test/file_system/multi_root_test.dart
+++ b/pkg/build_integration/test/file_system/multi_root_test.dart
@@ -38,9 +38,9 @@
.toString();
setUp(() {
- memoryFs = new MemoryFileSystem(root);
+ memoryFs = MemoryFileSystem(root);
final rootUris = ['r1', 'r2/', 'A/B/', ''].map((r) => root.resolve(r)).toList();
- multiRoot = new MultiRootFileSystem('multi-root', rootUris, memoryFs);
+ multiRoot = MultiRootFileSystem('multi-root', rootUris, memoryFs);
});
test('roots are normalized', () async {
@@ -120,7 +120,7 @@
// If we remove '' as a root, those URIs are not resolved.
multiRoot =
- new MultiRootFileSystem('multi-root', [root.resolve('A/B/')], memoryFs);
+ MultiRootFileSystem('multi-root', [root.resolve('A/B/')], memoryFs);
expect(await effectiveUriOf('multi-root:///../A/B/a/8.dart'),
'multi-root:///A/B/a/8.dart');
expect(await effectiveUriOf('multi-root:///../../A/B/a/8.dart'),
diff --git a/pkg/build_integration/test/file_system/single_root_test.dart b/pkg/build_integration/test/file_system/single_root_test.dart
index 50fb984..73ca23a 100644
--- a/pkg/build_integration/test/file_system/single_root_test.dart
+++ b/pkg/build_integration/test/file_system/single_root_test.dart
@@ -9,8 +9,8 @@
main() {
var root = Uri.parse('org-dartlang-test:///');
- var fileSystem = new SingleRootFileSystem(
- 'single-root', root.resolve('A/B'), new MemoryFileSystem(root));
+ var fileSystem = SingleRootFileSystem(
+ 'single-root', root.resolve('A/B'), MemoryFileSystem(root));
SingleRootFileSystemEntity entityOf(String uri) =>
fileSystem.entityForUri(Uri.parse(uri)) as SingleRootFileSystemEntity;
diff --git a/pkg/compiler/lib/src/inferrer/builder.dart b/pkg/compiler/lib/src/inferrer/builder.dart
index 01f4f58..80bb03c 100644
--- a/pkg/compiler/lib/src/inferrer/builder.dart
+++ b/pkg/compiler/lib/src/inferrer/builder.dart
@@ -572,13 +572,18 @@
_setupBreaksAndContinues(jumpTarget);
List<JumpTarget> continueTargets = <JumpTarget>[];
+ bool hasDefaultCase = false;
for (ir.SwitchCase switchCase in node.cases) {
JumpTarget continueTarget =
_localsMap.getJumpTargetForSwitchCase(switchCase);
if (continueTarget != null) {
continueTargets.add(continueTarget);
}
+ if (switchCase.isDefault) {
+ hasDefaultCase = true;
+ }
}
+ LocalState stateBefore = _state;
if (continueTargets.isNotEmpty) {
continueTargets.forEach(_setupBreaksAndContinues);
@@ -586,43 +591,47 @@
// visit all cases and update [locals] until we have reached a
// fixed point.
bool changed;
- _state.startLoop(_inferrer, node);
+ stateBefore.startLoop(_inferrer, node);
do {
changed = false;
+ // We first visit every case and collect the updated continue states.
+ // We must do a full pass as the jumps may be to earlier cases.
+ _visitCasesForSwitch(node, stateBefore);
+
+ // We then pass back over the cases and update the state of any continue
+ // targets with the states we collected in the last pass.
for (ir.SwitchCase switchCase in node.cases) {
- LocalState stateBeforeCase = _state;
- _state = LocalState.childPath(stateBeforeCase);
- visit(switchCase);
- LocalState stateAfterCase = _state;
- changed =
- stateBeforeCase.mergeAll(_inferrer, [stateAfterCase]) || changed;
- _state = stateBeforeCase;
+ final continueTarget =
+ _localsMap.getJumpTargetForSwitchCase(switchCase);
+ if (continueTarget != null) {
+ changed |= stateBefore.mergeAll(
+ _inferrer, _getLoopBackEdges(continueTarget));
+ }
}
} while (changed);
- _state.endLoop(_inferrer, node);
+ stateBefore.endLoop(_inferrer, node);
continueTargets.forEach(_clearBreaksAndContinues);
} else {
- LocalState stateBeforeCase = _state;
- List<LocalState> statesToMerge = <LocalState>[];
- bool hasDefaultCase = false;
-
- for (ir.SwitchCase switchCase in node.cases) {
- if (switchCase.isDefault) {
- hasDefaultCase = true;
- }
- _state = LocalState.childPath(stateBeforeCase);
- visit(switchCase);
- statesToMerge.add(_state);
- }
- stateBeforeCase.mergeAfterBreaks(_inferrer, statesToMerge,
- keepOwnLocals: !hasDefaultCase);
- _state = stateBeforeCase;
+ // Gather the termination states of each case by visiting all the breaks.
+ _visitCasesForSwitch(node, stateBefore);
}
+
+ // Combine all the termination states accumulated from all the visited
+ // breaks that target this switch.
+ _state = stateBefore.mergeAfterBreaks(_inferrer, _getBreaks(jumpTarget),
+ keepOwnLocals: !hasDefaultCase);
_clearBreaksAndContinues(jumpTarget);
return null;
}
+ _visitCasesForSwitch(ir.SwitchStatement node, LocalState stateBefore) {
+ for (ir.SwitchCase switchCase in node.cases) {
+ _state = LocalState.childPath(stateBefore);
+ visit(switchCase);
+ }
+ }
+
@override
visitSwitchCase(ir.SwitchCase node) {
visit(node.body);
diff --git a/pkg/compiler/lib/src/options.dart b/pkg/compiler/lib/src/options.dart
index 83b6ac6..f27676d 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -103,6 +103,7 @@
/// [FeatureOption]s which default to enabled.
late final List<FeatureOption> shipping = [
+ deferredSerialization,
useContentSecurityPolicy,
];
@@ -113,7 +114,6 @@
simpleAsyncToFuture,
cfeConstants,
internValues,
- deferredSerialization,
];
/// Forces canary feature on. This must run after [Option].parse.
diff --git a/pkg/compiler/test/dump_info/data/deferred/main.dart b/pkg/compiler/test/dump_info/data/deferred/main.dart
index 2ab399c..c4f9945 100644
--- a/pkg/compiler/test/dump_info/data/deferred/main.dart
+++ b/pkg/compiler/test/dump_info/data/deferred/main.dart
@@ -4,7 +4,122 @@
// @dart = 2.7
-/*library:
+/*spec.library:
+ constant=[
+ {
+ "id": "constant/B.C_Deferred = A.lib__funky$closure();\n",
+ "kind": "constant",
+ "name": "",
+ "size": 39,
+ "outputUnit": "outputUnit/1",
+ "code": "B.C_Deferred = A.lib__funky$closure();\n"
+},
+ {
+ "id": "constant/B.C_JS_CONST = function getTagFallback(o) {\n var s = Object.prototype.toString.call(o);\n return s.substring(8, s.length - 1);\n};\n",
+ "kind": "constant",
+ "name": "",
+ "size": 131,
+ "outputUnit": "outputUnit/main",
+ "code": "B.C_JS_CONST = function getTagFallback(o) {\n var s = Object.prototype.toString.call(o);\n return s.substring(8, s.length - 1);\n};\n"
+},
+ {
+ "id": "constant/B.C__RootZone = new A._RootZone();\n",
+ "kind": "constant",
+ "name": "",
+ "size": 35,
+ "outputUnit": "outputUnit/main",
+ "code": "B.C__RootZone = new A._RootZone();\n"
+},
+ {
+ "id": "constant/B.C__StringStackTrace = new A._StringStackTrace();\n",
+ "kind": "constant",
+ "name": "",
+ "size": 51,
+ "outputUnit": "outputUnit/main",
+ "code": "B.C__StringStackTrace = new A._StringStackTrace();\n"
+},
+ {
+ "id": "constant/B.Interceptor_methods = J.Interceptor.prototype;\n",
+ "kind": "constant",
+ "name": "",
+ "size": 49,
+ "outputUnit": "outputUnit/main",
+ "code": "B.Interceptor_methods = J.Interceptor.prototype;\n"
+},
+ {
+ "id": "constant/B.JSArray_methods = J.JSArray.prototype;\n",
+ "kind": "constant",
+ "name": "",
+ "size": 41,
+ "outputUnit": "outputUnit/main",
+ "code": "B.JSArray_methods = J.JSArray.prototype;\n"
+},
+ {
+ "id": "constant/B.JSInt_methods = J.JSInt.prototype;\n",
+ "kind": "constant",
+ "name": "",
+ "size": 37,
+ "outputUnit": "outputUnit/main",
+ "code": "B.JSInt_methods = J.JSInt.prototype;\n"
+},
+ {
+ "id": "constant/B.JSString_methods = J.JSString.prototype;\n",
+ "kind": "constant",
+ "name": "",
+ "size": 43,
+ "outputUnit": "outputUnit/main",
+ "code": "B.JSString_methods = J.JSString.prototype;\n"
+},
+ {
+ "id": "constant/B.JavaScriptObject_methods = J.JavaScriptObject.prototype;\n",
+ "kind": "constant",
+ "name": "",
+ "size": 59,
+ "outputUnit": "outputUnit/main",
+ "code": "B.JavaScriptObject_methods = J.JavaScriptObject.prototype;\n"
+}],
+ deferredFiles=[{
+ "main.dart": {
+ "name": "<unnamed>",
+ "imports": {
+ "lib": [
+ "out_1.part.js"
+ ]
+ }
+ }
+}],
+ dependencies=[{}],
+ library=[{
+ "id": "library/memory:sdk/tests/web/native/main.dart::",
+ "kind": "library",
+ "name": "<unnamed>",
+ "size": 301,
+ "children": [
+ "function/memory:sdk/tests/web/native/main.dart::main"
+ ],
+ "canonicalUri": "memory:sdk/tests/web/native/main.dart"
+}],
+ outputUnits=[
+ {
+ "id": "outputUnit/1",
+ "kind": "outputUnit",
+ "name": "1",
+ "size": 1087,
+ "filename": "out_1.part.js",
+ "imports": [
+ "lib"
+ ]
+},
+ {
+ "id": "outputUnit/main",
+ "kind": "outputUnit",
+ "name": "main",
+ "filename": "out",
+ "imports": []
+}]
+*/
+
+/*canary.library:
constant=[
{
"id": "constant/B.C_Deferred = A.lib__funky$closure();\n",
diff --git a/pkg/compiler/test/dump_info/data/deferred_future/main.dart b/pkg/compiler/test/dump_info/data/deferred_future/main.dart
index e95b65c..f9347fc 100644
--- a/pkg/compiler/test/dump_info/data/deferred_future/main.dart
+++ b/pkg/compiler/test/dump_info/data/deferred_future/main.dart
@@ -2,7 +2,130 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-/*library:
+/*spec.library:
+ constant=[
+ {
+ "id": "constant/B.C_A = new A.A();\n",
+ "kind": "constant",
+ "name": "",
+ "size": 19,
+ "outputUnit": "outputUnit/1",
+ "code": "B.C_A = new A.A();\n"
+},
+ {
+ "id": "constant/B.C_Deferred = B.C_A;\n",
+ "kind": "constant",
+ "name": "",
+ "size": 22,
+ "outputUnit": "outputUnit/1",
+ "code": "B.C_Deferred = B.C_A;\n"
+},
+ {
+ "id": "constant/B.C_JS_CONST = function getTagFallback(o) {\n var s = Object.prototype.toString.call(o);\n return s.substring(8, s.length - 1);\n};\n",
+ "kind": "constant",
+ "name": "",
+ "size": 131,
+ "outputUnit": "outputUnit/main",
+ "code": "B.C_JS_CONST = function getTagFallback(o) {\n var s = Object.prototype.toString.call(o);\n return s.substring(8, s.length - 1);\n};\n"
+},
+ {
+ "id": "constant/B.C__RootZone = new A._RootZone();\n",
+ "kind": "constant",
+ "name": "",
+ "size": 35,
+ "outputUnit": "outputUnit/main",
+ "code": "B.C__RootZone = new A._RootZone();\n"
+},
+ {
+ "id": "constant/B.C__StringStackTrace = new A._StringStackTrace();\n",
+ "kind": "constant",
+ "name": "",
+ "size": 51,
+ "outputUnit": "outputUnit/main",
+ "code": "B.C__StringStackTrace = new A._StringStackTrace();\n"
+},
+ {
+ "id": "constant/B.Interceptor_methods = J.Interceptor.prototype;\n",
+ "kind": "constant",
+ "name": "",
+ "size": 49,
+ "outputUnit": "outputUnit/main",
+ "code": "B.Interceptor_methods = J.Interceptor.prototype;\n"
+},
+ {
+ "id": "constant/B.JSArray_methods = J.JSArray.prototype;\n",
+ "kind": "constant",
+ "name": "",
+ "size": 41,
+ "outputUnit": "outputUnit/main",
+ "code": "B.JSArray_methods = J.JSArray.prototype;\n"
+},
+ {
+ "id": "constant/B.JSInt_methods = J.JSInt.prototype;\n",
+ "kind": "constant",
+ "name": "",
+ "size": 37,
+ "outputUnit": "outputUnit/main",
+ "code": "B.JSInt_methods = J.JSInt.prototype;\n"
+},
+ {
+ "id": "constant/B.JSString_methods = J.JSString.prototype;\n",
+ "kind": "constant",
+ "name": "",
+ "size": 43,
+ "outputUnit": "outputUnit/main",
+ "code": "B.JSString_methods = J.JSString.prototype;\n"
+},
+ {
+ "id": "constant/B.JavaScriptObject_methods = J.JavaScriptObject.prototype;\n",
+ "kind": "constant",
+ "name": "",
+ "size": 59,
+ "outputUnit": "outputUnit/main",
+ "code": "B.JavaScriptObject_methods = J.JavaScriptObject.prototype;\n"
+}],
+ deferredFiles=[{
+ "main.dart": {
+ "name": "<unnamed>",
+ "imports": {
+ "lib1": [
+ "out_1.part.js"
+ ]
+ }
+ }
+}],
+ dependencies=[{}],
+ library=[{
+ "id": "library/memory:sdk/tests/web/native/main.dart::",
+ "kind": "library",
+ "name": "<unnamed>",
+ "size": 857,
+ "children": [
+ "function/memory:sdk/tests/web/native/main.dart::main"
+ ],
+ "canonicalUri": "memory:sdk/tests/web/native/main.dart"
+}],
+ outputUnits=[
+ {
+ "id": "outputUnit/1",
+ "kind": "outputUnit",
+ "name": "1",
+ "size": 870,
+ "filename": "out_1.part.js",
+ "imports": [
+ "lib1"
+ ]
+},
+ {
+ "id": "outputUnit/main",
+ "kind": "outputUnit",
+ "name": "main",
+ "filename": "out",
+ "imports": []
+}]
+*/
+
+/*canary.library:
constant=[
{
"id": "constant/B.C_A = new A.A();\n",
diff --git a/pkg/compiler/test/inference/data/issue_46770.dart b/pkg/compiler/test/inference/data/issue_46770.dart
new file mode 100644
index 0000000..739bd53
--- /dev/null
+++ b/pkg/compiler/test/inference/data/issue_46770.dart
@@ -0,0 +1,364 @@
+// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+abstract class L {
+ void m1();
+}
+
+/*member: L1.:[exact=L1]*/
+class L1 implements L {
+ @pragma('dart2js:noInline')
+ /*member: L1.m1:[null]*/
+ void m1() => print("L1");
+}
+
+/*member: L2.:[exact=L2]*/
+class L2 implements L {
+ @pragma('dart2js:noInline')
+ /*member: L2.m1:[null]*/
+ void m1() => print("L2");
+}
+
+/*member: L3.:[exact=L3]*/
+class L3 implements L {
+ @pragma('dart2js:noInline')
+ /*member: L3.m1:[null]*/
+ void m1() => print("L3");
+}
+
+/*member: cTrue:[exact=JSBool]*/
+bool cTrue = confuse(true);
+/*member: value:[exact=JSUInt31]*/
+int value = confuse(1);
+
+@pragma('dart2js:noInline')
+/*member: confuse:Union([exact=JSBool], [exact=JSUInt31])*/
+confuse(/*Union([exact=JSBool], [exact=JSUInt31])*/ x) => x;
+
+/*member: test1:Union(null, [exact=L2], [exact=L3])*/
+test1() {
+ L? sourceInfo = L1();
+ switch (value) {
+ case 1:
+ if (cTrue) {
+ sourceInfo = L2();
+ break;
+ }
+ sourceInfo = L3();
+ break;
+ default:
+ return null;
+ }
+
+ sourceInfo. /*invoke: Union([exact=L2], [exact=L3])*/ m1();
+ return sourceInfo;
+}
+
+/*member: test2:Union([exact=L1], [exact=L2], [exact=L3])*/
+test2() {
+ L? sourceInfo = L1();
+ switch (value) {
+ case 1:
+ if (cTrue) {
+ sourceInfo = L2();
+ break;
+ }
+ sourceInfo = L3();
+ break;
+ default:
+ // Do nothing
+ }
+
+ sourceInfo. /*invoke: Union([exact=L1], [exact=L2], [exact=L3])*/ m1();
+ return sourceInfo;
+}
+
+/*member: test3:Union(null, [exact=L2], [exact=L3])*/
+test3() {
+ L? sourceInfo = L1();
+ switchTarget:
+ switch (value) {
+ case 1:
+ while (cTrue) {
+ sourceInfo = L2();
+ break switchTarget;
+ }
+ sourceInfo = L3();
+ break;
+ default:
+ return null;
+ }
+
+ sourceInfo. /*invoke: Union([exact=L2], [exact=L3])*/ m1();
+ return sourceInfo;
+}
+
+/*member: test4:Union(null, [exact=L1], [exact=L3])*/
+test4() {
+ L sourceInfo = L1();
+ switch (value) {
+ case 1:
+ if (cTrue) {
+ sourceInfo = L2();
+ continue otherCase;
+ }
+ sourceInfo = L3();
+ break;
+ otherCase:
+ case 2:
+ sourceInfo. /*invoke: Union([exact=L1], [exact=L2])*/ m1();
+ sourceInfo = L1();
+ break;
+ default:
+ return null;
+ }
+
+ sourceInfo. /*invoke: Union([exact=L1], [exact=L3])*/ m1();
+ return sourceInfo;
+}
+
+/*member: test5:Union(null, [exact=L1], [exact=L2], [exact=L3])*/
+test5() {
+ L sourceInfo = L1();
+ switch (value) {
+ case 1:
+ if (cTrue) {
+ sourceInfo = L2();
+ continue otherCase;
+ }
+ sourceInfo = L3();
+ break;
+ otherCase:
+ case 2:
+ break;
+ default:
+ return null;
+ }
+
+ sourceInfo. /*invoke: Union([exact=L1], [exact=L2], [exact=L3])*/ m1();
+ return sourceInfo;
+}
+
+/*member: test6:Union(null, [exact=L2], [exact=L3])*/
+test6() {
+ L sourceInfo = L1();
+ switch (value) {
+ case 1:
+ if (cTrue) {
+ sourceInfo = L2();
+ continue otherCase;
+ }
+ sourceInfo = L3();
+ break;
+ otherCase:
+ case 2:
+ sourceInfo = L2();
+ break;
+ default:
+ return null;
+ }
+
+ sourceInfo. /*invoke: Union([exact=L2], [exact=L3])*/ m1();
+ return sourceInfo;
+}
+
+/*member: test7:[null|exact=L3]*/
+test7() {
+ L? sourceInfo = L1();
+ switch (value) {
+ case 1:
+ if (cTrue) {
+ sourceInfo = L2();
+ return null;
+ }
+ sourceInfo = L3();
+ break;
+ default:
+ return null;
+ }
+
+ sourceInfo. /*invoke: [exact=L3]*/ m1();
+ return sourceInfo;
+}
+
+/*member: test8:[null|exact=L3]*/
+test8() {
+ L? sourceInfo = L1();
+ switch (value) {
+ case 1:
+ while (cTrue) {
+ sourceInfo = L2();
+ break;
+ }
+ sourceInfo = L3();
+ break;
+ default:
+ return null;
+ }
+
+ sourceInfo. /*invoke: [exact=L3]*/ m1();
+ return sourceInfo;
+}
+
+/*member: test9:[null|exact=L3]*/
+test9() {
+ L? sourceInfo = L1();
+ switch (value) {
+ case 1:
+ while (cTrue) {
+ sourceInfo = L2();
+ return null;
+ }
+ sourceInfo = L3();
+ break;
+ default:
+ return null;
+ }
+
+ sourceInfo. /*invoke: [exact=L3]*/ m1();
+ return sourceInfo;
+}
+
+/*member: test10:Union(null, [exact=L1], [exact=L2], [exact=L3])*/
+test10() {
+ L sourceInfo = L1();
+ try {
+ switch (value) {
+ case 1:
+ if (cTrue) {
+ sourceInfo = L2();
+ throw Exception();
+ }
+ sourceInfo = L3();
+ break;
+ default:
+ return null;
+ }
+ } catch (e) {
+ // Do nothing
+ }
+
+ sourceInfo. /*invoke: Union([exact=L1], [exact=L2], [exact=L3])*/ m1();
+ return sourceInfo;
+}
+
+/*member: test11:[null|exact=L3]*/
+test11() {
+ L sourceInfo = L1();
+ switch (value) {
+ case 1:
+ if (cTrue) {
+ sourceInfo = L2();
+ throw Exception();
+ }
+ sourceInfo = L3();
+ break;
+ default:
+ return null;
+ }
+ sourceInfo. /*invoke: [exact=L3]*/ m1();
+ return sourceInfo;
+}
+
+/*member: test12:Union(null, [exact=L1], [exact=L3])*/
+test12() {
+ L? sourceInfo = L1();
+ switch (value) {
+ case 1:
+ if (cTrue) {
+ sourceInfo = L2();
+ return null;
+ }
+ sourceInfo = L3();
+ break;
+ default:
+ // Do nothing
+ }
+
+ sourceInfo. /*invoke: Union([exact=L1], [exact=L3])*/ m1();
+ return sourceInfo;
+}
+
+/*member: test13:Union(null, [exact=L2], [exact=L3])*/
+test13() {
+ L? sourceInfo = L1();
+ switch (value) {
+ case 1:
+ if (cTrue) {
+ sourceInfo = L2();
+ return null;
+ }
+ sourceInfo = L3();
+ break;
+ default:
+ sourceInfo = L2();
+ }
+
+ sourceInfo. /*invoke: Union([exact=L2], [exact=L3])*/ m1();
+ return sourceInfo;
+}
+
+/*member: test14:Union(null, [exact=L1], [exact=L2], [exact=L3])*/
+test14() {
+ L sourceInfo = L1();
+ whileLabel:
+ while (true) {
+ switch (value) {
+ case 1:
+ if (cTrue) {
+ sourceInfo = L2();
+ break whileLabel;
+ }
+ sourceInfo = L3();
+ break;
+ default:
+ return null;
+ }
+ sourceInfo. /*invoke: [exact=L3]*/ m1();
+ break;
+ }
+ sourceInfo. /*invoke: Union([exact=L1], [exact=L2], [exact=L3])*/ m1();
+ return sourceInfo;
+}
+
+/*member: test15:[null|exact=L3]*/
+test15() {
+ L sourceInfo = L1();
+ switch (value) {
+ case 1:
+ if (cTrue) {
+ sourceInfo = L2();
+ continue otherCase;
+ }
+ sourceInfo = L3();
+ break;
+ otherCase:
+ case 2:
+ return null;
+ default:
+ return null;
+ }
+
+ sourceInfo. /*invoke: [exact=L3]*/ m1();
+ return sourceInfo;
+}
+
+/*member: main:[null]*/
+main() {
+ test1();
+ test2();
+ test3();
+ test4();
+ test5();
+ test6();
+ test7();
+ test8();
+ test9();
+ test10();
+ test11();
+ test12();
+ test13();
+ test14();
+ test15();
+}
diff --git a/pkg/compiler/test/inference/data/switch.dart b/pkg/compiler/test/inference/data/switch.dart
index df79306..be09435 100644
--- a/pkg/compiler/test/inference/data/switch.dart
+++ b/pkg/compiler/test/inference/data/switch.dart
@@ -90,7 +90,7 @@
// Switch statement with continue.
////////////////////////////////////////////////////////////////////////////////
-/*member: _switchWithContinue:Union(null, [exact=JSBool], [exact=JSString], [exact=JSUInt31])*/
+/*member: _switchWithContinue:Union([exact=JSBool], [exact=JSString])*/
_switchWithContinue(/*[exact=JSUInt31]*/ o) {
dynamic local;
switch (o) {
@@ -99,8 +99,7 @@
continue label;
label:
case 1:
- local = local
- . /*Union(null, [exact=JSBool], [exact=JSString], [exact=JSUInt31])*/ isEven;
+ local = local. /*Union(null, [exact=JSString], [exact=JSUInt31])*/ isEven;
break;
case 2:
default:
diff --git a/pkg/dart_internal/analysis_options.yaml b/pkg/dart_internal/analysis_options.yaml
index 6f7501d..a5a786b 100644
--- a/pkg/dart_internal/analysis_options.yaml
+++ b/pkg/dart_internal/analysis_options.yaml
@@ -1,3 +1,5 @@
+include: package:lints/recommended.yaml
+
analyzer:
errors:
import_internal_library: ignore
diff --git a/pkg/dart_internal/pubspec.yaml b/pkg/dart_internal/pubspec.yaml
index 0c52966..5d59e77 100644
--- a/pkg/dart_internal/pubspec.yaml
+++ b/pkg/dart_internal/pubspec.yaml
@@ -10,3 +10,7 @@
# Restrict the upper bound so that we can remove support for this in a later
# version of the SDK without it being a breaking change.
sdk: ">=2.12.0 <2.19.0"
+
+# Use 'any' constraints here; we get our versions from the DEPS file.
+dev_dependencies:
+ lints: any
diff --git a/pkg/dds_service_extensions/analysis_options.yaml b/pkg/dds_service_extensions/analysis_options.yaml
index dee8927..572dd23 100644
--- a/pkg/dds_service_extensions/analysis_options.yaml
+++ b/pkg/dds_service_extensions/analysis_options.yaml
@@ -1,30 +1 @@
-# This file configures the static analysis results for your project (errors,
-# warnings, and lints).
-#
-# This enables the 'recommended' set of lints from `package:lints`.
-# This set helps identify many issues that may lead to problems when running
-# or consuming Dart code, and enforces writing Dart using a single, idiomatic
-# style and format.
-#
-# If you want a smaller set of lints you can change this to specify
-# 'package:lints/core.yaml'. These are just the most critical lints
-# (the recommended set includes the core lints).
-# The core lints are also what is used by pub.dev for scoring packages.
-
include: package:lints/recommended.yaml
-
-# Uncomment the following section to specify additional rules.
-
-# linter:
-# rules:
-# - camel_case_types
-
-# analyzer:
-# exclude:
-# - path/to/excluded/files/**
-
-# For more information about the core and recommended set of lints, see
-# https://dart.dev/go/core-lints
-
-# For additional information about configuring this file, see
-# https://dart.dev/guides/language/analysis-options
diff --git a/pkg/frontend_server/README.md b/pkg/frontend_server/README.md
index afebf6c..eed933c 100644
--- a/pkg/frontend_server/README.md
+++ b/pkg/frontend_server/README.md
@@ -10,7 +10,6 @@
This API stability does not cover any of the source code APIs.
-
### Stable subset
* The frontend_server kernel compilation and expression evaluation for kernel should be considered "stable".
diff --git a/pkg/frontend_server/analysis_options.yaml b/pkg/frontend_server/analysis_options.yaml
new file mode 100644
index 0000000..c36c2c5
--- /dev/null
+++ b/pkg/frontend_server/analysis_options.yaml
@@ -0,0 +1 @@
+include: package:lints/core.yaml
diff --git a/pkg/frontend_server/bin/frontend_server_starter.dart b/pkg/frontend_server/bin/frontend_server_starter.dart
index 82b6fb8..526c396 100644
--- a/pkg/frontend_server/bin/frontend_server_starter.dart
+++ b/pkg/frontend_server/bin/frontend_server_starter.dart
@@ -4,7 +4,7 @@
import 'dart:async';
import 'dart:io';
-import '../lib/frontend_server.dart';
+import 'package:frontend_server/frontend_server.dart';
Future<Null> main(List<String> args) async {
exitCode = await starter(args);
diff --git a/pkg/frontend_server/lib/frontend_server.dart b/pkg/frontend_server/lib/frontend_server.dart
index a3f6508..5d7088c 100644
--- a/pkg/frontend_server/lib/frontend_server.dart
+++ b/pkg/frontend_server/lib/frontend_server.dart
@@ -634,7 +634,7 @@
return errors.isEmpty;
}
- void _outputDependenciesDelta(Iterable<Uri> compiledSources) async {
+ Future<void> _outputDependenciesDelta(Iterable<Uri> compiledSources) async {
if (!_printIncrementalDependencies) {
return;
}
@@ -948,7 +948,7 @@
final procedure = await expressionCompiler.compileExpressionToJs(
libraryUri, line, column, jsFrameValues, expression);
- final result = errors.length > 0 ? errors[0] : procedure;
+ final result = errors.isNotEmpty ? errors[0] : procedure;
// TODO(annagrin): kernelBinaryFilename is too specific
// rename to _outputFileName?
@@ -1271,8 +1271,9 @@
if (string == boundaryKey) {
compiler.recompileDelta(entryPoint: recompileEntryPoint);
state = _State.READY_FOR_INSTRUCTION;
- } else
+ } else {
compiler.invalidate(Uri.base.resolve(string));
+ }
break;
case _State.COMPILE_EXPRESSION_EXPRESSION:
compileExpressionRequest.expression = string;
diff --git a/pkg/frontend_server/lib/src/javascript_bundle.dart b/pkg/frontend_server/lib/src/javascript_bundle.dart
index 00ddccb..d6a340b 100644
--- a/pkg/frontend_server/lib/src/javascript_bundle.dart
+++ b/pkg/frontend_server/lib/src/javascript_bundle.dart
@@ -161,8 +161,7 @@
// Source locations come through as absolute file uris. In order to
// make relative paths in the source map we get the absolute uri for
// the module and make them relative to that.
- sourceMapBase =
- p.dirname((await _packageConfig.resolve(moduleUri)).path);
+ sourceMapBase = p.dirname((_packageConfig.resolve(moduleUri)).path);
}
final code = jsProgramToCode(
diff --git a/pkg/frontend_server/lib/src/strong_components.dart b/pkg/frontend_server/lib/src/strong_components.dart
index a436b7c..3fca363 100644
--- a/pkg/frontend_server/lib/src/strong_components.dart
+++ b/pkg/frontend_server/lib/src/strong_components.dart
@@ -82,7 +82,7 @@
final List<List<Library>> results =
computeStrongComponents(_LibraryGraph(entrypoint, loadedLibraries));
for (List<Library> component in results) {
- assert(component.length > 0);
+ assert(component.isNotEmpty);
final Uri moduleUri = component
.firstWhere((lib) => lib.importUri == mainUri,
orElse: () => component.first)
diff --git a/pkg/frontend_server/pubspec.yaml b/pkg/frontend_server/pubspec.yaml
index 93b3740..5218bd1 100644
--- a/pkg/frontend_server/pubspec.yaml
+++ b/pkg/frontend_server/pubspec.yaml
@@ -22,5 +22,6 @@
# Use 'any' constraints here; we get our versions from the DEPS file.
dev_dependencies:
+ lints: any
mockito: any
test: any
diff --git a/pkg/frontend_server/test/frontend_server_flutter.dart b/pkg/frontend_server/test/frontend_server_flutter.dart
index f0d5f2f..fee26f6 100644
--- a/pkg/frontend_server/test/frontend_server_flutter.dart
+++ b/pkg/frontend_server/test/frontend_server_flutter.dart
@@ -13,7 +13,7 @@
import 'package:front_end/src/api_unstable/vm.dart'
show CompilerOptions, NnbdMode, StandardFileSystem;
-import '../lib/frontend_server.dart';
+import 'package:frontend_server/frontend_server.dart';
main(List<String> args) async {
String flutterDir;
@@ -70,7 +70,7 @@
f.uri
.toString()
.endsWith("/flutter_patched_sdk/platform_strong.dill")));
- if (platformFiles.length < 1) {
+ if (platformFiles.isEmpty) {
throw "Expected to find a flutter platform file but didn't.";
}
flutterPlatformDirectoryTmp = platformFiles.first.parent;
diff --git a/pkg/frontend_server/test/frontend_server_flutter_suite.dart b/pkg/frontend_server/test/frontend_server_flutter_suite.dart
index 0a6b249..8473358 100644
--- a/pkg/frontend_server/test/frontend_server_flutter_suite.dart
+++ b/pkg/frontend_server/test/frontend_server_flutter_suite.dart
@@ -182,8 +182,8 @@
}
}
-void writeLinesToFile(Uri uri, List<String> lines) async {
- await File.fromUri(uri).writeAsString(lines.map((line) => "$line\n").join());
+void writeLinesToFile(Uri uri, List<String> lines) {
+ File.fromUri(uri).writeAsStringSync(lines.map((line) => "$line\n").join());
}
main([List<String> arguments = const <String>[]]) async {
@@ -254,8 +254,8 @@
// Write results.json and logs.json.
Uri resultJsonUri = options.outputDirectory.resolve("results.json");
Uri logsJsonUri = options.outputDirectory.resolve("logs.json");
- await writeLinesToFile(resultJsonUri, results);
- await writeLinesToFile(logsJsonUri, logs);
+ writeLinesToFile(resultJsonUri, results);
+ writeLinesToFile(logsJsonUri, logs);
print("Log files written to ${resultJsonUri.toFilePath()} and"
" ${logsJsonUri.toFilePath()}");
diff --git a/pkg/frontend_server/test/frontend_server_test.dart b/pkg/frontend_server/test/frontend_server_test.dart
index d9d8b6f..9cc623d 100644
--- a/pkg/frontend_server/test/frontend_server_test.dart
+++ b/pkg/frontend_server/test/frontend_server_test.dart
@@ -1,4 +1,6 @@
// @dart = 2.9
+// ignore_for_file: empty_catches
+
import 'dart:async';
import 'dart:convert';
import 'dart:io';
@@ -7,6 +9,7 @@
import 'package:_fe_analyzer_shared/src/macros/compiler/request_channel.dart';
import 'package:front_end/src/api_unstable/vm.dart';
+import 'package:frontend_server/frontend_server.dart';
import 'package:kernel/ast.dart' show Component;
import 'package:kernel/binary/ast_to_binary.dart';
import 'package:kernel/kernel.dart' show loadComponentFromBinary;
@@ -16,8 +19,6 @@
import 'package:test/test.dart';
import 'package:vm/incremental_compiler.dart';
-import '../lib/frontend_server.dart';
-
void main() async {
group('basic', () {
final CompilerInterface compiler = _MockedCompiler();
@@ -499,10 +500,9 @@
file.writeAsStringSync("main() {\n}\n");
var dillFile = File('${tempDir.path}/app.dill');
- var package_config =
- File('${tempDir.path}/.dart_tool/package_config.json')
- ..createSync(recursive: true)
- ..writeAsStringSync('''
+ var packageConfig = File('${tempDir.path}/.dart_tool/package_config.json')
+ ..createSync(recursive: true)
+ ..writeAsStringSync('''
{
"configVersion": 2,
"packages": [
@@ -521,7 +521,7 @@
'--incremental',
'--platform=${platformKernel.path}',
'--output-dill=${dillFile.path}',
- '--packages=${package_config.path}',
+ '--packages=${packageConfig.path}',
];
final StreamController<List<int>> streamController =
@@ -2024,10 +2024,9 @@
test('compile to JavaScript', () async {
var file = File('${tempDir.path}/foo.dart')..createSync();
file.writeAsStringSync("main() {\n}\n");
- var package_config =
- File('${tempDir.path}/.dart_tool/package_config.json')
- ..createSync(recursive: true)
- ..writeAsStringSync('''
+ var packageConfig = File('${tempDir.path}/.dart_tool/package_config.json')
+ ..createSync(recursive: true)
+ ..writeAsStringSync('''
{
"configVersion": 2,
"packages": [
@@ -2048,7 +2047,7 @@
'--incremental',
'--platform=${ddcPlatformKernel.path}',
'--output-dill=${dillFile.path}',
- '--packages=${package_config.path}',
+ '--packages=${packageConfig.path}',
'--target=dartdevc',
file.path,
];
@@ -2190,10 +2189,9 @@
var file = File('${tempDir.path}/foo.dart')..createSync();
file.writeAsStringSync("main() {\n\n}\n");
- var package_config =
- File('${tempDir.path}/.dart_tool/package_config.json')
- ..createSync(recursive: true)
- ..writeAsStringSync('''
+ var packageConfig = File('${tempDir.path}/.dart_tool/package_config.json')
+ ..createSync(recursive: true)
+ ..writeAsStringSync('''
{
"configVersion": 2,
"packages": [
@@ -2226,7 +2224,7 @@
'--platform=${ddcPlatformKernel.path}',
'--output-dill=${dillFile.path}',
'--target=dartdevc',
- '--packages=${package_config.path}',
+ '--packages=${packageConfig.path}',
];
final StreamController<List<int>> streamController =
@@ -2269,10 +2267,9 @@
test('compile to JavaScript with metadata', () async {
var file = File('${tempDir.path}/foo.dart')..createSync();
file.writeAsStringSync("main() {\n\n}\n");
- var package_config =
- File('${tempDir.path}/.dart_tool/package_config.json')
- ..createSync(recursive: true)
- ..writeAsStringSync('''
+ var packageConfig = File('${tempDir.path}/.dart_tool/package_config.json')
+ ..createSync(recursive: true)
+ ..writeAsStringSync('''
{
"configVersion": 2,
"packages": [
@@ -2307,7 +2304,7 @@
'--platform=${ddcPlatformKernel.path}',
'--output-dill=${dillFile.path}',
'--target=dartdevc',
- '--packages=${package_config.path}',
+ '--packages=${packageConfig.path}',
'--experimental-emit-debug-metadata',
'--emit-debug-symbols',
];
@@ -2361,10 +2358,9 @@
var dillFile = File('${tempDir.path}/app.dill');
var sourceFile = File('${dillFile.path}.sources');
- var package_config =
- File('${tempDir.path}/.dart_tool/package_config.json')
- ..createSync(recursive: true)
- ..writeAsStringSync('''
+ var packageConfig = File('${tempDir.path}/.dart_tool/package_config.json')
+ ..createSync(recursive: true)
+ ..writeAsStringSync('''
{
"configVersion": 2,
"packages": [
@@ -2386,7 +2382,7 @@
'--platform=${ddcPlatformKernelWeak.path}',
'--output-dill=${dillFile.path}',
'--target=dartdevc',
- '--packages=${package_config.path}'
+ '--packages=${packageConfig.path}'
];
final StreamController<List<int>> streamController =
@@ -2444,10 +2440,9 @@
file = File('${tempDir.path}/bar.dart')..createSync();
file.writeAsStringSync("void Function(int) fn = (int i) => null;\n");
- var package_config =
- File('${tempDir.path}/.dart_tool/package_config.json')
- ..createSync(recursive: true)
- ..writeAsStringSync('''
+ var packageConfig = File('${tempDir.path}/.dart_tool/package_config.json')
+ ..createSync(recursive: true)
+ ..writeAsStringSync('''
{
"configVersion": 2,
"packages": [
@@ -2471,7 +2466,7 @@
'--platform=${ddcPlatformKernel.path}',
'--output-dill=${dillFile.path}',
'--target=dartdevc',
- '--packages=${package_config.path}',
+ '--packages=${packageConfig.path}',
];
final StreamController<List<int>> streamController =
@@ -2524,10 +2519,9 @@
test('compile expression to Javascript', () async {
var file = File('${tempDir.path}/foo.dart')..createSync();
file.writeAsStringSync("main() {\n}\n");
- var package_config =
- File('${tempDir.path}/.dart_tool/package_config.json')
- ..createSync(recursive: true)
- ..writeAsStringSync('''
+ var packageConfig = File('${tempDir.path}/.dart_tool/package_config.json')
+ ..createSync(recursive: true)
+ ..writeAsStringSync('''
{
"configVersion": 2,
"packages": [
@@ -2556,7 +2550,7 @@
'--platform=${ddcPlatformKernel.path}',
'--output-dill=${dillFile.path}',
'--target=dartdevc',
- '--packages=${package_config.path}',
+ '--packages=${packageConfig.path}',
];
final StreamController<List<int>> streamController =
@@ -2645,10 +2639,9 @@
var file = File('${tempDir.path}/foo.dart')..createSync();
file.writeAsStringSync(
"main() {print(const bool.fromEnvironment('dart.library.html'));}\n");
- var package_config =
- File('${tempDir.path}/.dart_tool/package_config.json')
- ..createSync(recursive: true)
- ..writeAsStringSync('''
+ var packageConfig = File('${tempDir.path}/.dart_tool/package_config.json')
+ ..createSync(recursive: true)
+ ..writeAsStringSync('''
{
"configVersion": 2,
"packages": [
@@ -2677,7 +2670,7 @@
'--platform=${ddcPlatformKernel.path}',
'--output-dill=${dillFile.path}',
'--target=dartdevc',
- '--packages=${package_config.path}',
+ '--packages=${packageConfig.path}',
];
final StreamController<List<int>> streamController =
@@ -2753,10 +2746,9 @@
test('mixed compile expression commands with web target', () async {
var file = File('${tempDir.path}/foo.dart')..createSync();
file.writeAsStringSync("main() {\n\n}\n");
- var package_config =
- File('${tempDir.path}/.dart_tool/package_config.json')
- ..createSync(recursive: true)
- ..writeAsStringSync('''
+ var packageConfig = File('${tempDir.path}/.dart_tool/package_config.json')
+ ..createSync(recursive: true)
+ ..writeAsStringSync('''
{
"configVersion": 2,
"packages": [
@@ -2784,7 +2776,7 @@
'--platform=${ddcPlatformKernel.path}',
'--output-dill=${dillFile.path}',
'--target=dartdevc',
- '--packages=${package_config.path}',
+ '--packages=${packageConfig.path}',
];
final StreamController<List<int>> streamController =
@@ -3124,7 +3116,7 @@
main() {}
method(int i) => i?.isEven;
""");
- var package_config =
+ var packageConfig =
File('${tempDir.path}/.dart_tool/package_config.json')
..createSync(recursive: true)
..writeAsStringSync('''
@@ -3148,7 +3140,7 @@
'--incremental',
'--platform=${ddcPlatformKernel.path}',
'--output-dill=${dillFile.path}',
- '--packages=${package_config.path}',
+ '--packages=${packageConfig.path}',
'--target=dartdevc',
if (hideWarnings) '--verbosity=error',
file.path,
diff --git a/pkg/frontend_server/test/src/javascript_bundle_test.dart b/pkg/frontend_server/test/src/javascript_bundle_test.dart
index 488e986..ae41252 100644
--- a/pkg/frontend_server/test/src/javascript_bundle_test.dart
+++ b/pkg/frontend_server/test/src/javascript_bundle_test.dart
@@ -145,7 +145,7 @@
test('converts package: uris into /packages/ uris', () async {
var importUri = Uri.parse('package:a/a.dart');
- var fileUri = await packageConfig.resolve(importUri);
+ var fileUri = packageConfig.resolve(importUri);
final library = Library(
importUri,
fileUri: fileUri,
diff --git a/pkg/smith/lib/configuration.dart b/pkg/smith/lib/configuration.dart
index 5cf0e02..f5a7d94 100644
--- a/pkg/smith/lib/configuration.dart
+++ b/pkg/smith/lib/configuration.dart
@@ -625,7 +625,6 @@
static const dart2js = Compiler._('dart2js');
static const dart2analyzer = Compiler._('dart2analyzer');
static const dart2wasm = Compiler._('dart2wasm');
- static const compareAnalyzerCfe = Compiler._('compare_analyzer_cfe');
static const dartdevc = Compiler._('dartdevc');
static const dartdevk = Compiler._('dartdevk');
static const appJitk = Compiler._('app_jitk');
@@ -641,7 +640,6 @@
dart2js,
dart2analyzer,
dart2wasm,
- compareAnalyzerCfe,
dartdevc,
dartdevk,
appJitk,
@@ -700,7 +698,6 @@
Runtime.chrome,
];
case Compiler.dart2analyzer:
- case Compiler.compareAnalyzerCfe:
return const [Runtime.none];
case Compiler.appJitk:
case Compiler.dartk:
@@ -730,7 +727,6 @@
case Compiler.dartdevk:
return Runtime.chrome;
case Compiler.dart2analyzer:
- case Compiler.compareAnalyzerCfe:
return Runtime.none;
case Compiler.appJitk:
case Compiler.dartk:
@@ -750,7 +746,6 @@
Mode get defaultMode {
switch (this) {
case Compiler.dart2analyzer:
- case Compiler.compareAnalyzerCfe:
case Compiler.dart2js:
case Compiler.dart2wasm:
case Compiler.dartdevc:
diff --git a/pkg/telemetry/analysis_options.yaml b/pkg/telemetry/analysis_options.yaml
index bb2ae44..d2e6c14 100644
--- a/pkg/telemetry/analysis_options.yaml
+++ b/pkg/telemetry/analysis_options.yaml
@@ -3,6 +3,7 @@
analyzer:
language:
strict-casts: true
+
linter:
rules:
- unawaited_futures
diff --git a/pkg/test_runner/analysis_options.yaml b/pkg/test_runner/analysis_options.yaml
index e6a5912..ff809b7 100644
--- a/pkg/test_runner/analysis_options.yaml
+++ b/pkg/test_runner/analysis_options.yaml
@@ -1,83 +1,27 @@
+include: package:lints/core.yaml
+
analyzer:
language:
strict-casts: true
+
linter:
rules:
- # TODO: Enable these once the existing violations have been fixed.
-# - annotate_overrides
-# - non_constant_identifier_names
-# - only_throw_errors
-# - prefer_interpolation_to_compose_strings
-# - prefer_single_quotes
- - avoid_bool_literals_in_conditional_expressions
- - avoid_empty_else
- - avoid_function_literals_in_foreach_calls
- - avoid_init_to_null
- - avoid_null_checks_in_equality_operators
- - avoid_relative_lib_imports
- - avoid_renaming_method_parameters
- - avoid_return_types_on_setters
- - avoid_returning_null
- - avoid_returning_null_for_void
- - avoid_shadowing_type_parameters
- - avoid_single_cascade_in_expression_statements
- - avoid_types_as_parameter_names
- - avoid_unused_constructor_parameters
- - await_only_futures
- - camel_case_types
- - cancel_subscriptions
- - comment_references
- - constant_identifier_names
- - control_flow_in_finally
- - curly_braces_in_flow_control_structures
- - directives_ordering
- - empty_catches
- - empty_constructor_bodies
- - empty_statements
- - file_names
- - hash_and_equals
- - implementation_imports
- - invariant_booleans
- - iterable_contains_unrelated_type
- - library_names
- - library_prefixes
- - list_remove_unrelated_type
- - no_duplicate_case_values
- - null_closures
- - omit_local_variable_types
- - overridden_fields
- - package_api_docs
- - package_names
- - package_prefixed_library_names
- - prefer_adjacent_string_concatenation
- - prefer_collection_literals
- - prefer_conditional_assignment
- - prefer_const_constructors
- - prefer_contains
- - prefer_equal_for_default_values
- - prefer_final_fields
- - prefer_generic_function_type_aliases
- - prefer_initializing_formals
- - prefer_is_empty
- - prefer_is_not_empty
- - prefer_null_aware_operators
- - prefer_typing_uninitialized_variables
- - recursive_getters
- - slash_for_doc_comments
- - throw_in_finally
- - type_init_formals
- - unnecessary_brace_in_string_interps
- - unnecessary_const
- - unnecessary_getters_setters
- - unnecessary_lambdas
- - unnecessary_new
- - unnecessary_null_aware_assignments
- - unnecessary_null_in_if_null_operators
- - unnecessary_parenthesis
- - unnecessary_statements
- - unnecessary_this
- - unnecessary_overrides
- - unrelated_type_equality_checks
- - use_rethrow_when_possible
- - valid_regexps
- - void_checks
+ avoid_bool_literals_in_conditional_expressions: true
+ avoid_returning_null: true
+ avoid_unused_constructor_parameters: true
+ cancel_subscriptions: true
+ comment_references: true
+ directives_ordering: true
+ invariant_booleans: true
+ omit_local_variable_types: true
+ package_api_docs: true
+ prefer_const_constructors: true
+ throw_in_finally: true
+ unnecessary_lambdas: true
+ unnecessary_parenthesis: true
+ unnecessary_statements: true
+
+ # Disabled due to existing violations.
+ non_constant_identifier_names: false
+ only_throw_errors: false
+ prefer_single_quotes: false
diff --git a/pkg/test_runner/lib/src/compiler_configuration.dart b/pkg/test_runner/lib/src/compiler_configuration.dart
index 85a8fc1..d59e07e 100644
--- a/pkg/test_runner/lib/src/compiler_configuration.dart
+++ b/pkg/test_runner/lib/src/compiler_configuration.dart
@@ -80,9 +80,6 @@
case Compiler.dart2analyzer:
return AnalyzerCompilerConfiguration(configuration);
- case Compiler.compareAnalyzerCfe:
- return CompareAnalyzerCfeCompilerConfiguration(configuration);
-
case Compiler.dart2js:
return Dart2jsCompilerConfiguration(configuration);
@@ -1249,41 +1246,6 @@
}
}
-/// Configuration for compareAnalyzerCfe.
-class CompareAnalyzerCfeCompilerConfiguration extends CompilerConfiguration {
- CompareAnalyzerCfeCompilerConfiguration(TestConfiguration configuration)
- : super._subclass(configuration);
-
- int get timeoutMultiplier => 4;
-
- String computeCompilerPath() {
- if (_useSdk) {
- throw "--use-sdk cannot be used with compiler compare_analyzer_cfe";
- }
- return 'pkg/analyzer_fe_comparison/bin/'
- 'compare_sdk_tests$shellScriptExtension';
- }
-
- CommandArtifact computeCompilationArtifact(String tempDir,
- List<String> arguments, Map<String, String> environmentOverrides) {
- // Since this is not a real compilation, no artifacts are produced.
- return CommandArtifact([
- CompareAnalyzerCfeCommand(
- computeCompilerPath(), arguments.toList(), environmentOverrides)
- ], arguments.singleWhere((argument) => argument.endsWith('.dart')),
- 'application/vnd.dart');
- }
-
- List<String> computeRuntimeArguments(
- RuntimeConfiguration runtimeConfiguration,
- TestFile testFile,
- List<String> vmOptions,
- List<String> originalArguments,
- CommandArtifact? artifact) {
- return [];
- }
-}
-
/// Configuration for spec_parser.
class SpecParserCompilerConfiguration extends CompilerConfiguration {
SpecParserCompilerConfiguration(TestConfiguration configuration)
diff --git a/pkg/test_runner/pubspec.yaml b/pkg/test_runner/pubspec.yaml
index 119ef05..c7b9622 100644
--- a/pkg/test_runner/pubspec.yaml
+++ b/pkg/test_runner/pubspec.yaml
@@ -26,3 +26,4 @@
analyzer: any
expect: any
glob: any
+ lints: any
diff --git a/pkg/vm/analysis_options.yaml b/pkg/vm/analysis_options.yaml
index 4aaf9c5..6d3c447 100644
--- a/pkg/vm/analysis_options.yaml
+++ b/pkg/vm/analysis_options.yaml
@@ -2,6 +2,4 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
-analyzer:
- exclude:
- - tool/**
+include: package:lints/core.yaml
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index ef6b991..f619484 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -511,7 +511,7 @@
Future _processExpressionCompilationRequest(request) async {
final SendPort port = request[1];
final int isolateGroupId = request[2];
- final dynamic dart_platform_kernel = request[3];
+ final dynamic dartPlatformKernel = request[3];
final String expression = request[4];
final List<String> definitions = request[5].cast<String>();
final List<String> definitionTypes = request[6].cast<String>();
@@ -576,8 +576,8 @@
}
if (!foundDartCore) {
List<int> platformKernel;
- if (dart_platform_kernel is List<int>) {
- platformKernel = dart_platform_kernel;
+ if (dartPlatformKernel is List<int>) {
+ platformKernel = dartPlatformKernel;
} else {
final Uri platformUri = computePlatformBinariesLocation()
.resolve('vm_platform_strong.dill');
@@ -983,7 +983,7 @@
String? multirootFilepaths, String? multirootScheme) {
FileSystem fileSystem = new HttpAwareFileSystem(StandardFileSystem.instance);
- if (!sourceFiles.isEmpty || platformKernel != null) {
+ if (sourceFiles.isNotEmpty || platformKernel != null) {
MemoryFileSystem memoryFileSystem =
new MemoryFileSystem(Uri.parse('file:///'));
for (int i = 0; i < sourceFiles.length ~/ 2; i++) {
@@ -1143,17 +1143,17 @@
}
class _CompilationNullSafety extends CompilationResult {
- final bool _null_safety;
+ final bool _nullSafety;
- _CompilationNullSafety(this._null_safety) : super._() {}
+ _CompilationNullSafety(this._nullSafety) : super._() {}
@override
Status get status => Status.ok;
@override
- get payload => _null_safety;
+ get payload => _nullSafety;
- String toString() => "_CompilationNullSafety($_null_safety)";
+ String toString() => "_CompilationNullSafety($_nullSafety)";
}
abstract class _CompilationFail extends CompilationResult {
@@ -1198,9 +1198,13 @@
}
Future<T> runWithPrintToStderr<T>(Future<T> f()) {
- return runZoned(() => new Future<T>(f),
- zoneSpecification: new ZoneSpecification(
- print: (_1, _2, _3, String line) => stderr.writeln(line)));
+ return runZoned(
+ () => new Future<T>(f),
+ zoneSpecification: new ZoneSpecification(
+ // ignore: non_constant_identifier_names
+ print: (_1, _2, _3, String line) => stderr.writeln(line),
+ ),
+ );
}
int _debugDumpCounter = 0;
diff --git a/pkg/vm/lib/target/vm.dart b/pkg/vm/lib/target/vm.dart
index a74b718..b706bd5 100644
--- a/pkg/vm/lib/target/vm.dart
+++ b/pkg/vm/lib/target/vm.dart
@@ -248,7 +248,7 @@
arg.value)
..fileOffset = arg.fileOffset;
})), keyType: coreTypes.symbolLegacyRawType)
- ..isConst = (arguments.named.length == 0)
+ ..isConst = (arguments.named.isEmpty)
..fileOffset = arguments.fileOffset
], types: [
coreTypes.symbolLegacyRawType,
@@ -392,7 +392,7 @@
// handling, the current approach seems sufficient.
// The 0-element list must be exactly 'const[]'.
- if (elements.length == 0) {
+ if (elements.isEmpty) {
return new ListLiteral([], typeArgument: typeArgument)..isConst = true;
}
diff --git a/pkg/vm/lib/testing/il_matchers.dart b/pkg/vm/lib/testing/il_matchers.dart
index 1c2f883..8aec633 100644
--- a/pkg/vm/lib/testing/il_matchers.dart
+++ b/pkg/vm/lib/testing/il_matchers.dart
@@ -394,11 +394,13 @@
final _AnyMatcher any = const _AnyMatcher();
+ // ignore: non_constant_identifier_names
InstructionMatcher Goto(String dest) =>
InstructionMatcher._(op: 'Goto', matchers: {
's': _ListMatcher([_blockRef(dest)])
});
+ // ignore: non_constant_identifier_names
InstructionMatcher Branch(InstructionMatcher compare,
{String? ifTrue, String? ifFalse}) =>
InstructionMatcher._(op: 'Branch', matchers: {
diff --git a/pkg/vm/lib/transformations/async.dart b/pkg/vm/lib/transformations/async.dart
index ecdec2e..6a6628b 100644
--- a/pkg/vm/lib/transformations/async.dart
+++ b/pkg/vm/lib/transformations/async.dart
@@ -433,7 +433,8 @@
new EqualsCall(expr.right, new BoolLiteral(true),
interfaceTarget: objectEquals,
functionType: objectEquals.getterType as FunctionType))));
- var then, otherwise;
+ Statement then;
+ Statement? otherwise;
if (expr.operatorEnum == LogicalExpressionOperator.AND) {
then = rightBody;
otherwise = null;
diff --git a/pkg/vm/lib/transformations/continuation.dart b/pkg/vm/lib/transformations/continuation.dart
index 9241252..d23954f 100644
--- a/pkg/vm/lib/transformations/continuation.dart
+++ b/pkg/vm/lib/transformations/continuation.dart
@@ -399,7 +399,7 @@
static DartType elementTypeFrom(Class containerClass, DartType type) {
if (type is InterfaceType) {
if (type.classNode == containerClass) {
- if (type.typeArguments.length == 0) {
+ if (type.typeArguments.isEmpty) {
return const DynamicType();
} else if (type.typeArguments.length == 1) {
return type.typeArguments[0];
diff --git a/pkg/vm/lib/transformations/ffi/common.dart b/pkg/vm/lib/transformations/ffi/common.dart
index 3b3a837..c99635a 100644
--- a/pkg/vm/lib/transformations/ffi/common.dart
+++ b/pkg/vm/lib/transformations/ffi/common.dart
@@ -585,7 +585,7 @@
if (fun.positionalParameters.length != fun.requiredParameterCount) {
return null;
}
- if (fun.typeParameters.length != 0) return null;
+ if (fun.typeParameters.isNotEmpty) return null;
final DartType? returnType = convertNativeTypeToDartType(fun.returnType,
allowCompounds: true, allowHandle: true);
diff --git a/pkg/vm/lib/transformations/ffi/definitions.dart b/pkg/vm/lib/transformations/ffi/definitions.dart
index e859a61..50b4ca9 100644
--- a/pkg/vm/lib/transformations/ffi/definitions.dart
+++ b/pkg/vm/lib/transformations/ffi/definitions.dart
@@ -260,15 +260,15 @@
final nativeTypeCfe = NativeTypeCfe(
this, node.getThisType(coreTypes, Nullability.nonNullable))
as AbiSpecificNativeTypeCfe;
- if (nativeTypeCfe.abiSpecificTypes.length == 0) {
+ if (nativeTypeCfe.abiSpecificTypes.isEmpty) {
// Annotation missing, multiple annotations, or invalid mapping.
diagnosticReporter.report(messageFfiAbiSpecificIntegerMappingInvalid,
node.fileOffset, node.name.length, node.location!.file);
}
- if (node.typeParameters.length != 0 ||
- node.procedures.where((Procedure e) => !e.isSynthetic).length != 0 ||
- node.fields.length != 0 ||
- node.redirectingFactories.length != 0 ||
+ if (node.typeParameters.isNotEmpty ||
+ node.procedures.where((Procedure e) => !e.isSynthetic).isNotEmpty ||
+ node.fields.isNotEmpty ||
+ node.redirectingFactories.isNotEmpty ||
node.constructors.length != 1 ||
!node.constructors.single.isConst) {
// We want exactly one constructor, no other members and no type arguments.
@@ -306,7 +306,7 @@
/// Returns packing if any.
int? _checkCompoundClass(Class node) {
- if (node.typeParameters.length > 0) {
+ if (node.typeParameters.isNotEmpty) {
diagnosticReporter.report(
templateFfiStructGeneric.withArguments(
node.superclass!.name, node.name),
@@ -430,7 +430,7 @@
} else if (isPointerType(type) ||
isCompoundSubtype(type) ||
isArrayType(type)) {
- if (nativeTypeAnnos.length != 0) {
+ if (nativeTypeAnnos.isNotEmpty) {
diagnosticReporter.report(
templateFfiFieldNoAnnotation.withArguments(f.name.text),
f.fileOffset,
@@ -632,7 +632,7 @@
final packingAnnotations = _getPackedAnnotations(node);
final packing =
- (!packingAnnotations.isEmpty) ? packingAnnotations.first : null;
+ (packingAnnotations.isNotEmpty) ? packingAnnotations.first : null;
final compoundType = () {
if (types.whereType<InvalidNativeTypeCfe>().isNotEmpty) {
diff --git a/pkg/vm/lib/transformations/ffi/native.dart b/pkg/vm/lib/transformations/ffi/native.dart
index fedd286..bc63d3a 100644
--- a/pkg/vm/lib/transformations/ffi/native.dart
+++ b/pkg/vm/lib/transformations/ffi/native.dart
@@ -346,7 +346,7 @@
// annotation matches.
bool _verifySignatures(Procedure node, FunctionType dartFunctionType,
FunctionType ffiFunctionType, int annotationOffset) {
- if (ffiFunctionType.namedParameters.length > 0) {
+ if (ffiFunctionType.namedParameters.isNotEmpty) {
diagnosticReporter.report(
templateCantHaveNamedParameters.withArguments('FfiNative'),
annotationOffset,
diff --git a/pkg/vm/lib/transformations/ffi/native_type_cfe.dart b/pkg/vm/lib/transformations/ffi/native_type_cfe.dart
index 4a19480..871313c 100644
--- a/pkg/vm/lib/transformations/ffi/native_type_cfe.dart
+++ b/pkg/vm/lib/transformations/ffi/native_type_cfe.dart
@@ -38,7 +38,7 @@
if (arrayDimensions == null) {
throw "Must have array dimensions for ArrayType.";
}
- if (arrayDimensions.length == 0) {
+ if (arrayDimensions.isEmpty) {
throw "Must have a size for this array dimension.";
}
final elementType = transformer.arraySingleElementType(dartType);
diff --git a/pkg/vm/lib/transformations/specializer/list_factory_specializer.dart b/pkg/vm/lib/transformations/specializer/list_factory_specializer.dart
index 1a3f10f..c088b62 100644
--- a/pkg/vm/lib/transformations/specializer/list_factory_specializer.dart
+++ b/pkg/vm/lib/transformations/specializer/list_factory_specializer.dart
@@ -94,7 +94,7 @@
TreeNode transformListEmptyFactory(StaticInvocation node) {
final args = node.arguments;
- assert(args.positional.length == 0);
+ assert(args.positional.isEmpty);
final bool? growable =
_getConstantOptionalArgument(args, 'growable', false);
if (growable == null) {
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index bae97d9..6ccde60 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -1865,7 +1865,7 @@
node.members.length = writeIndex;
// We only retain the extension if at least one member is retained.
- assert(node.members.length > 0);
+ assert(node.members.isNotEmpty);
return node;
}
return removalSentinel!;
diff --git a/pkg/vm/lib/transformations/type_flow/utils.dart b/pkg/vm/lib/transformations/type_flow/utils.dart
index 42f54c0..ad6ce30 100644
--- a/pkg/vm/lib/transformations/type_flow/utils.dart
+++ b/pkg/vm/lib/transformations/type_flow/utils.dart
@@ -319,7 +319,7 @@
// Returns the smallest index 'i' such that 'list.skip(i)' is a prefix of
// 'sublist'.
int findOverlap(List list, List sublist) {
- for (int i = 0; i < list.length; ++i)
+ for (int i = 0; i < list.length; ++i) {
outer:
{
for (int j = 0; j < sublist.length && i + j < list.length; ++j) {
@@ -327,6 +327,7 @@
}
return i;
}
+ }
return list.length;
}
diff --git a/pkg/vm/pubspec.yaml b/pkg/vm/pubspec.yaml
index 009cfeba..52c44fb 100644
--- a/pkg/vm/pubspec.yaml
+++ b/pkg/vm/pubspec.yaml
@@ -20,6 +20,7 @@
dev_dependencies:
expect: any
json_rpc_2: any
+ lints: any
path: any
test: any
web_socket_channel: any
diff --git a/pkg/vm/test/incremental_compiler_test.dart b/pkg/vm/test/incremental_compiler_test.dart
index 8bfa4e40..83974c9 100644
--- a/pkg/vm/test/incremental_compiler_test.dart
+++ b/pkg/vm/test/incremental_compiler_test.dart
@@ -250,9 +250,13 @@
hits.add(pos);
}
}
- for (int pos in coverage["misses"]) positions.add(pos);
+ for (int pos in coverage["misses"]) {
+ positions.add(pos);
+ }
if (range["possibleBreakpoints"] != null) {
- for (int pos in range["possibleBreakpoints"]) positions.add(pos);
+ for (int pos in range["possibleBreakpoints"]) {
+ positions.add(pos);
+ }
}
Map script = scriptIndexToScript[range["scriptIndex"]]!;
Set<int> knownPositions = new Set<int>();
diff --git a/pkg/vm/test/transformations/ffi_test.dart b/pkg/vm/test/transformations/ffi_test.dart
index 8d4f639..3f6dd75 100644
--- a/pkg/vm/test/transformations/ffi_test.dart
+++ b/pkg/vm/test/transformations/ffi_test.dart
@@ -49,9 +49,9 @@
}
void main(List<String> args) {
- assert(args.length == 0 || args.length == 1);
+ assert(args.isEmpty || args.length == 1);
String? filter;
- if (args.length > 0) {
+ if (args.isNotEmpty) {
filter = args.first;
}
diff --git a/pkg/vm/test/transformations/type_flow/transformer_test.dart b/pkg/vm/test/transformations/type_flow/transformer_test.dart
index 0dc138f..2b80881 100644
--- a/pkg/vm/test/transformations/type_flow/transformer_test.dart
+++ b/pkg/vm/test/transformations/type_flow/transformer_test.dart
@@ -68,7 +68,7 @@
}
String? argsTestName(List<String> args) {
- if (args.length > 0) {
+ if (args.isNotEmpty) {
return args.last;
}
return null;
diff --git a/pkg/wasm_builder/analysis_options.yaml b/pkg/wasm_builder/analysis_options.yaml
new file mode 100644
index 0000000..c36c2c5
--- /dev/null
+++ b/pkg/wasm_builder/analysis_options.yaml
@@ -0,0 +1 @@
+include: package:lints/core.yaml
diff --git a/pkg/wasm_builder/lib/src/instructions.dart b/pkg/wasm_builder/lib/src/instructions.dart
index f91b26f..beb2411 100644
--- a/pkg/wasm_builder/lib/src/instructions.dart
+++ b/pkg/wasm_builder/lib/src/instructions.dart
@@ -2,6 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+// ignore_for_file: non_constant_identifier_names
+
import 'module.dart';
import 'serialize.dart';
import 'types.dart';
diff --git a/pkg/wasm_builder/lib/src/module.dart b/pkg/wasm_builder/lib/src/module.dart
index 592b304..3c0a55a 100644
--- a/pkg/wasm_builder/lib/src/module.dart
+++ b/pkg/wasm_builder/lib/src/module.dart
@@ -24,7 +24,7 @@
final List<DataSegment> dataSegments = [];
final List<Global> globals = [];
final List<Export> exports = [];
- BaseFunction? startFunction = null;
+ BaseFunction? startFunction;
bool anyFunctionsDefined = false;
bool anyTablesDefined = false;
@@ -277,7 +277,7 @@
}
/// Serialize the module to its binary representation.
- Uint8List encode({bool emitNameSection: true}) {
+ Uint8List encode({bool emitNameSection = true}) {
// Wasm module preamble: magic number, version 1.
writeBytes(const [0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00]);
TypeSection(this).serialize(this);
@@ -918,7 +918,7 @@
// each stretch as an element.
List<_Element> elements = [];
for (DefinedTable table in module.definedTables) {
- _Element? current = null;
+ _Element? current;
for (int i = 0; i < table.elements.length; i++) {
BaseFunction? function = table.elements[i];
if (function != null) {
diff --git a/pkg/wasm_builder/lib/src/serialize.dart b/pkg/wasm_builder/lib/src/serialize.dart
index 007b6e1..3e6047a 100644
--- a/pkg/wasm_builder/lib/src/serialize.dart
+++ b/pkg/wasm_builder/lib/src/serialize.dart
@@ -40,7 +40,9 @@
// Ensure space for at least `size` additional bytes.
if (_data.length < _index + size) {
int newLength = _data.length * 2;
- while (newLength < _index + size) newLength *= 2;
+ while (newLength < _index + size) {
+ newLength *= 2;
+ }
_data = Uint8List(newLength)..setRange(0, _data.length, _data);
}
}
@@ -107,7 +109,9 @@
void writeList(List<Serializable> objects) {
writeUnsigned(objects.length);
- for (int i = 0; i < objects.length; i++) write(objects[i]);
+ for (int i = 0; i < objects.length; i++) {
+ write(objects[i]);
+ }
}
void writeData(Serializer chunk, [List<int>? watchPoints]) {
diff --git a/pkg/wasm_builder/lib/src/types.dart b/pkg/wasm_builder/lib/src/types.dart
index 8ed1f68..d867dc6 100644
--- a/pkg/wasm_builder/lib/src/types.dart
+++ b/pkg/wasm_builder/lib/src/types.dart
@@ -230,7 +230,7 @@
@override
String toString() {
if (nullable == heapType.nullableByDefault) return "${heapType}ref";
- return "ref${nullable ? " null " : " "}${heapType}";
+ return "ref${nullable ? " null " : " "}$heapType";
}
@override
@@ -553,10 +553,10 @@
FieldType(super.type, {super.mutable = true});
/// The `i8` storage type as a field type.
- FieldType.i8({bool mutable: true}) : this(PackedType.i8, mutable: mutable);
+ FieldType.i8({bool mutable = true}) : this(PackedType.i8, mutable: mutable);
/// The `i16` storage type as a field type.
- FieldType.i16({bool mutable: true}) : this(PackedType.i16, mutable: mutable);
+ FieldType.i16({bool mutable = true}) : this(PackedType.i16, mutable: mutable);
bool isSubtypeOf(FieldType other) {
if (mutable != other.mutable) return false;
diff --git a/pkg/wasm_builder/pubspec.yaml b/pkg/wasm_builder/pubspec.yaml
index 3d59b5a..05ece99 100644
--- a/pkg/wasm_builder/pubspec.yaml
+++ b/pkg/wasm_builder/pubspec.yaml
@@ -5,3 +5,7 @@
environment:
sdk: '>=2.17.0'
+
+# Use 'any' constraints here; we get our versions from the DEPS file.
+dev_dependency:
+ lints: any
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.cc b/runtime/vm/compiler/assembler/assembler_arm64.cc
index f904733..64576491 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64.cc
@@ -482,13 +482,6 @@
return false;
}
- // TODO(zra, kmillikin): Also load other large immediates from the object
- // pool
- if (target::IsSmi(object)) {
- // If the raw smi does not fit into a 32-bit signed int, then we'll keep
- // the raw value in the object pool.
- return !Utils::IsInt(32, target::ToRawSmi(object));
- }
ASSERT(IsNotTemporaryScopedHandle(object));
ASSERT(IsInOldSpace(object));
return true;
@@ -535,18 +528,18 @@
ldr(dst, Address(THR, offset));
return;
}
+ if (target::IsSmi(object)) {
+ LoadImmediate(dst, target::ToRawSmi(object));
+ return;
+ }
}
- if (CanLoadFromObjectPool(object)) {
- const intptr_t index =
- is_unique ? object_pool_builder().AddObject(
- object, ObjectPoolBuilderEntry::kPatchable)
- : object_pool_builder().FindObject(
- object, ObjectPoolBuilderEntry::kNotPatchable);
- LoadWordFromPoolIndex(dst, index);
- return;
- }
- ASSERT(target::IsSmi(object));
- LoadImmediate(dst, target::ToRawSmi(object));
+ RELEASE_ASSERT(CanLoadFromObjectPool(object));
+ const intptr_t index =
+ is_unique ? object_pool_builder().AddObject(
+ object, ObjectPoolBuilderEntry::kPatchable)
+ : object_pool_builder().FindObject(
+ object, ObjectPoolBuilderEntry::kNotPatchable);
+ LoadWordFromPoolIndex(dst, index);
}
void Assembler::LoadObject(Register dst, const Object& object) {
diff --git a/runtime/vm/compiler/assembler/assembler_riscv.cc b/runtime/vm/compiler/assembler/assembler_riscv.cc
index 862bf92..10beeac 100644
--- a/runtime/vm/compiler/assembler/assembler_riscv.cc
+++ b/runtime/vm/compiler/assembler/assembler_riscv.cc
@@ -4336,28 +4336,17 @@
return;
}
if (target::IsSmi(object)) {
- intx_t raw_smi = target::ToRawSmi(object);
- if (IsITypeImm(raw_smi)) {
- li(dst, raw_smi);
- return;
- }
- if (IsUTypeImm(raw_smi)) {
- lui(dst, raw_smi);
- return;
- }
+ LoadImmediate(dst, target::ToRawSmi(object));
+ return;
}
}
- if (CanLoadFromObjectPool(object)) {
- const intptr_t index =
- is_unique ? object_pool_builder().AddObject(
- object, ObjectPoolBuilderEntry::kPatchable)
- : object_pool_builder().FindObject(
- object, ObjectPoolBuilderEntry::kNotPatchable);
- LoadWordFromPoolIndex(dst, index);
- return;
- }
- ASSERT(target::IsSmi(object));
- LoadImmediate(dst, target::ToRawSmi(object));
+ RELEASE_ASSERT(CanLoadFromObjectPool(object));
+ const intptr_t index =
+ is_unique ? object_pool_builder().AddObject(
+ object, ObjectPoolBuilderEntry::kPatchable)
+ : object_pool_builder().FindObject(
+ object, ObjectPoolBuilderEntry::kNotPatchable);
+ LoadWordFromPoolIndex(dst, index);
}
void Assembler::AddImmediateBranchOverflow(Register rd,
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index 8cd8bf6..f2a874a 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -1267,11 +1267,6 @@
return false;
}
- if (target::IsSmi(object)) {
- // If the raw smi does not fit into a 32-bit signed int, then we'll keep
- // the raw value in the object pool.
- return !Utils::IsInt(32, target::ToRawSmi(object));
- }
ASSERT(IsNotTemporaryScopedHandle(object));
ASSERT(IsInOldSpace(object));
return true;
@@ -1311,18 +1306,18 @@
movq(dst, Address(THR, offset));
return;
}
+ if (target::IsSmi(object)) {
+ LoadImmediate(dst, Immediate(target::ToRawSmi(object)));
+ return;
+ }
}
- if (CanLoadFromObjectPool(object)) {
- const intptr_t index =
- is_unique ? object_pool_builder().AddObject(
- object, ObjectPoolBuilderEntry::kPatchable)
- : object_pool_builder().FindObject(
- object, ObjectPoolBuilderEntry::kNotPatchable);
- LoadWordFromPoolIndex(dst, index);
- return;
- }
- ASSERT(target::IsSmi(object));
- LoadImmediate(dst, Immediate(target::ToRawSmi(object)));
+ RELEASE_ASSERT(CanLoadFromObjectPool(object));
+ const intptr_t index =
+ is_unique ? object_pool_builder().AddObject(
+ object, ObjectPoolBuilderEntry::kPatchable)
+ : object_pool_builder().FindObject(
+ object, ObjectPoolBuilderEntry::kNotPatchable);
+ LoadWordFromPoolIndex(dst, index);
}
void Assembler::LoadObject(Register dst, const Object& object) {
@@ -1340,12 +1335,11 @@
if (target::CanLoadFromThread(object, &offset_from_thread)) {
movq(TMP, Address(THR, offset_from_thread));
movq(dst, TMP);
- } else if (CanLoadFromObjectPool(object)) {
+ } else if (target::IsSmi(object)) {
+ MoveImmediate(dst, Immediate(target::ToRawSmi(object)));
+ } else {
LoadObject(TMP, object);
movq(dst, TMP);
- } else {
- ASSERT(target::IsSmi(object));
- MoveImmediate(dst, Immediate(target::ToRawSmi(object)));
}
}
@@ -1355,12 +1349,11 @@
intptr_t offset_from_thread;
if (target::CanLoadFromThread(object, &offset_from_thread)) {
pushq(Address(THR, offset_from_thread));
- } else if (CanLoadFromObjectPool(object)) {
+ } else if (target::IsSmi(object)) {
+ PushImmediate(Immediate(target::ToRawSmi(object)));
+ } else {
LoadObject(TMP, object);
pushq(TMP);
- } else {
- ASSERT(target::IsSmi(object));
- PushImmediate(Immediate(target::ToRawSmi(object)));
}
}
@@ -1370,14 +1363,14 @@
intptr_t offset_from_thread;
if (target::CanLoadFromThread(object, &offset_from_thread)) {
OBJ(cmp)(reg, Address(THR, offset_from_thread));
- } else if (CanLoadFromObjectPool(object)) {
+ } else if (target::IsSmi(object)) {
+ CompareImmediate(reg, Immediate(target::ToRawSmi(object)), kObjectBytes);
+ } else {
+ RELEASE_ASSERT(CanLoadFromObjectPool(object));
const intptr_t idx = object_pool_builder().FindObject(
object, ObjectPoolBuilderEntry::kNotPatchable);
const int32_t offset = target::ObjectPool::element_offset(idx);
OBJ(cmp)(reg, Address(PP, offset - kHeapObjectTag));
- } else {
- ASSERT(target::IsSmi(object));
- CompareImmediate(reg, Immediate(target::ToRawSmi(object)), kObjectBytes);
}
}
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index 2490c68..e666f59 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -924,7 +924,7 @@
word ToRawSmi(const dart::Object& a) {
RELEASE_ASSERT(IsSmi(a));
- return static_cast<word>(static_cast<intptr_t>(a.ptr()));
+ return static_cast<compressed_word>(static_cast<intptr_t>(a.ptr()));
}
word ToRawSmi(intptr_t value) {
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index c2fc343..daba5cf 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -606,6 +606,7 @@
// C++ ABI call registers.
const RegList kAbiArgumentCpuRegs =
(1 << R0) | (1 << R1) | (1 << R2) | (1 << R3);
+const RegList kAbiVolatileCpuRegs = kAbiArgumentCpuRegs | (1 << IP) | (1 << LR);
#if defined(DART_TARGET_OS_MACOS) || defined(DART_TARGET_OS_MACOS_IOS)
const RegList kAbiPreservedCpuRegs =
(1 << R4) | (1 << R5) | (1 << R6) | (1 << R8) | (1 << R10) | (1 << R11);
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index a6cfa13..92ca4a1 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -451,9 +451,9 @@
// C++ ABI call registers.
const RegList kAbiArgumentCpuRegs =
R(R0) | R(R1) | R(R2) | R(R3) | R(R4) | R(R5) | R(R6) | R(R7);
-const RegList kAbiVolatileCpuRegs =
- kAbiArgumentCpuRegs | R(R8) | R(R9) | R(R10) | R(R11) | R(R12) | R(R13) |
- R(R14) | R(R15) | R(R16) | R(R17);
+const RegList kAbiVolatileCpuRegs = kAbiArgumentCpuRegs | R(R8) | R(R9) |
+ R(R10) | R(R11) | R(R12) | R(R13) | R(R14) |
+ R(R15) | R(R16) | R(R17) | R(LR);
#if defined(DART_TARGET_OS_FUCHSIA)
// We rely on R18 not being touched by Dart generated assembly or stubs at all.
// We rely on that any calls into C++ also preserve R18.
diff --git a/runtime/vm/constants_riscv.h b/runtime/vm/constants_riscv.h
index 8ccc529..3fcfa47 100644
--- a/runtime/vm/constants_riscv.h
+++ b/runtime/vm/constants_riscv.h
@@ -449,8 +449,9 @@
constexpr RegList kAbiArgumentCpuRegs =
R(A0) | R(A1) | R(A2) | R(A3) | R(A4) | R(A5) | R(A6) | R(A7);
-constexpr RegList kAbiVolatileCpuRegs =
- kAbiArgumentCpuRegs | R(T0) | R(T1) | R(T2) | R(T3) | R(T4) | R(T5) | R(T6);
+constexpr RegList kAbiVolatileCpuRegs = kAbiArgumentCpuRegs | R(T0) | R(T1) |
+ R(T2) | R(T3) | R(T4) | R(T5) | R(T6) |
+ R(RA);
constexpr RegList kAbiPreservedCpuRegs = R(S1) | R(S2) | R(S3) | R(S4) | R(S5) |
R(S6) | R(S7) | R(S8) | R(S9) |
R(S10) | R(S11);
diff --git a/runtime/vm/globals.h b/runtime/vm/globals.h
index 559dc44..ac91f20 100644
--- a/runtime/vm/globals.h
+++ b/runtime/vm/globals.h
@@ -37,10 +37,12 @@
static constexpr int kCompressedWordSize = kInt32Size;
static constexpr int kCompressedWordSizeLog2 = kInt32SizeLog2;
typedef uint32_t compressed_uword;
+typedef int32_t compressed_word;
#else
static constexpr int kCompressedWordSize = kWordSize;
static constexpr int kCompressedWordSizeLog2 = kWordSizeLog2;
typedef uintptr_t compressed_uword;
+typedef intptr_t compressed_word;
#endif
const int kMaxAddrSpaceMB = (kWordSize <= 4) ? 4096 : kMaxInt;
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index e6381eb..4a04149 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -1428,8 +1428,7 @@
SimulatorRuntimeCall target =
reinterpret_cast<SimulatorRuntimeCall>(external);
target(arguments);
- set_register(R0, icount_); // Zap result register from void function.
- set_register(R1, icount_);
+ ClobberVolatileRegisters();
} else if (redirection->call_kind() == kLeafRuntimeCall) {
ASSERT((0 <= redirection->argument_count()) &&
(redirection->argument_count() <= 5));
@@ -1441,8 +1440,8 @@
SimulatorLeafRuntimeCall target =
reinterpret_cast<SimulatorLeafRuntimeCall>(external);
r0 = InvokeLeafRuntime(target, r0, r1, r2, r3, r4);
+ ClobberVolatileRegisters();
set_register(R0, r0); // Set returned result from function.
- set_register(R1, icount_); // Zap unused result register.
} else if (redirection->call_kind() == kLeafFloatRuntimeCall) {
ASSERT((0 <= redirection->argument_count()) &&
(redirection->argument_count() <= 2));
@@ -1454,6 +1453,7 @@
double d0 = get_dregister(D0);
double d1 = get_dregister(D1);
d0 = InvokeFloatLeafRuntime(target, d0, d1);
+ ClobberVolatileRegisters();
set_dregister(D0, d0);
} else {
// If we're not doing "hardfp", we must be doing "soft" or "softfp",
@@ -1467,6 +1467,7 @@
double d0 = bit_cast<double, int64_t>(a0);
double d1 = bit_cast<double, int64_t>(a1);
d0 = InvokeFloatLeafRuntime(target, d0, d1);
+ ClobberVolatileRegisters();
a0 = bit_cast<int64_t, double>(d0);
r0 = Utils::Low32Bits(a0);
r1 = Utils::High32Bits(a0);
@@ -1482,29 +1483,9 @@
Dart_NativeFunction target_func =
reinterpret_cast<Dart_NativeFunction>(get_register(R1));
wrapper(arguments, target_func);
- set_register(R0, icount_); // Zap result register from void function.
- set_register(R1, icount_);
+ ClobberVolatileRegisters();
}
- // Zap caller-saved registers, since the actual runtime call could have
- // used them.
- set_register(R2, icount_);
- set_register(R3, icount_);
- set_register(IP, icount_);
- set_register(LR, icount_);
- double zap_dvalue = static_cast<double>(icount_);
- // Do not zap D0, as it may contain a float result.
- for (int i = D1; i <= D7; i++) {
- set_dregister(static_cast<DRegister>(i), zap_dvalue);
- }
-// The above loop also zaps overlapping registers S2-S15.
-// Registers D8-D15 (overlapping with S16-S31) are preserved.
-#if defined(VFPv3_D32)
- for (int i = D16; i <= D31; i++) {
- set_dregister(static_cast<DRegister>(i), zap_dvalue);
- }
-#endif
-
// Return.
set_pc(saved_lr);
} else {
@@ -1525,6 +1506,29 @@
}
}
+void Simulator::ClobberVolatileRegisters() {
+ // Clear atomic reservation.
+ exclusive_access_addr_ = exclusive_access_value_ = 0;
+
+ for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
+ if ((kAbiVolatileCpuRegs & (1 << i)) != 0) {
+ registers_[i] = icount_;
+ }
+ }
+
+ double zap_dvalue = static_cast<double>(icount_);
+ for (int i = D0; i <= D7; i++) {
+ set_dregister(static_cast<DRegister>(i), zap_dvalue);
+ }
+ // The above loop also zaps overlapping registers S2-S15.
+ // Registers D8-D15 (overlapping with S16-S31) are preserved.
+#if defined(VFPv3_D32)
+ for (int i = D16; i <= D31; i++) {
+ set_dregister(static_cast<DRegister>(i), zap_dvalue);
+ }
+#endif
+}
+
// Handle execution based on instruction types.
// Instruction types 0 and 1 are both rolled into one function because they
diff --git a/runtime/vm/simulator_arm.h b/runtime/vm/simulator_arm.h
index 8851f6f..7e106a3 100644
--- a/runtime/vm/simulator_arm.h
+++ b/runtime/vm/simulator_arm.h
@@ -233,6 +233,8 @@
// Executes ARM instructions until the PC reaches kEndSimulatingPC.
void Execute();
+ void ClobberVolatileRegisters();
+
// Returns true if tracing of executed instructions is enabled.
bool IsTracingExecution() const;
diff --git a/runtime/vm/simulator_arm64.cc b/runtime/vm/simulator_arm64.cc
index fbb9df4..c512153 100644
--- a/runtime/vm/simulator_arm64.cc
+++ b/runtime/vm/simulator_arm64.cc
@@ -1711,9 +1711,7 @@
SimulatorRuntimeCall target =
reinterpret_cast<SimulatorRuntimeCall>(external);
target(*arguments);
- // Zap result register from void function.
- set_register(instr, R0, icount_);
- set_register(instr, R1, icount_);
+ ClobberVolatileRegisters();
} else if (redirection->call_kind() == kLeafRuntimeCall) {
ASSERT((0 <= redirection->argument_count()) &&
(redirection->argument_count() <= 8));
@@ -1729,8 +1727,8 @@
const int64_t r7 = get_register(R7);
const int64_t res =
InvokeLeafRuntime(target, r0, r1, r2, r3, r4, r5, r6, r7);
+ ClobberVolatileRegisters();
set_register(instr, R0, res); // Set returned result from function.
- set_register(instr, R1, icount_); // Zap unused result register.
} else if (redirection->call_kind() == kLeafFloatRuntimeCall) {
ASSERT((0 <= redirection->argument_count()) &&
(redirection->argument_count() <= 8));
@@ -1746,6 +1744,7 @@
const double d7 = bit_cast<double, int64_t>(get_vregisterd(V7, 0));
const double res =
InvokeFloatLeafRuntime(target, d0, d1, d2, d3, d4, d5, d6, d7);
+ ClobberVolatileRegisters();
set_vregisterd(V0, 0, bit_cast<int64_t, double>(res));
set_vregisterd(V0, 1, 0);
} else {
@@ -1757,34 +1756,9 @@
Dart_NativeFunction target =
reinterpret_cast<Dart_NativeFunction>(get_register(R1));
wrapper(arguments, target);
- // Zap result register from void function.
- set_register(instr, R0, icount_);
- set_register(instr, R1, icount_);
+ ClobberVolatileRegisters();
}
- // Zap caller-saved registers, since the actual runtime call could have
- // used them.
- set_register(NULL, R2, icount_);
- set_register(NULL, R3, icount_);
- set_register(NULL, R4, icount_);
- set_register(NULL, R5, icount_);
- set_register(NULL, R6, icount_);
- set_register(NULL, R7, icount_);
- set_register(NULL, R8, icount_);
- set_register(NULL, R9, icount_);
- set_register(NULL, R10, icount_);
- set_register(NULL, R11, icount_);
- set_register(NULL, R12, icount_);
- set_register(NULL, R13, icount_);
- set_register(NULL, R14, icount_);
- set_register(NULL, R15, icount_);
- set_register(NULL, IP0, icount_);
- set_register(NULL, IP1, icount_);
- set_register(NULL, R18, icount_);
- set_register(NULL, LR, icount_);
-
- // TODO(zra): Zap caller-saved fpu registers.
-
// Return.
set_pc(saved_lr);
} else {
@@ -1792,6 +1766,24 @@
}
}
+void Simulator::ClobberVolatileRegisters() {
+ // Clear atomic reservation.
+ exclusive_access_addr_ = exclusive_access_value_ = 0;
+
+ for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
+ if ((kAbiVolatileCpuRegs & (1 << i)) != 0) {
+ registers_[i] = icount_;
+ }
+ }
+
+ for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
+ if ((kAbiVolatileFpuRegs & (1 << i)) != 0) {
+ vregisters_[i].bits.i64[0] = icount_;
+ vregisters_[i].bits.i64[1] = icount_;
+ }
+ }
+}
+
void Simulator::DecodeExceptionGen(Instr* instr) {
if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) &&
(instr->Bits(21, 3) == 0)) {
diff --git a/runtime/vm/simulator_arm64.h b/runtime/vm/simulator_arm64.h
index be20b2b..0c0e49c3 100644
--- a/runtime/vm/simulator_arm64.h
+++ b/runtime/vm/simulator_arm64.h
@@ -240,6 +240,8 @@
// Executes ARM64 instructions until the PC reaches kEndSimulatingPC.
void Execute();
+ void ClobberVolatileRegisters();
+
// Returns true if tracing of executed instructions is enabled.
bool IsTracingExecution() const;
diff --git a/tools/VERSION b/tools/VERSION
index 45baf3f..c5351ee 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 18
PATCH 0
-PRERELEASE 263
+PRERELEASE 264
PRERELEASE_PATCH 0
\ No newline at end of file