Version 2.14.0-323.0.dev
Merge commit 'c3faa95568a2419e9c22510890923c78cec6b995' into 'dev'
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index f63580d..2e13ba2 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -4770,13 +4770,13 @@
The one-based index of the column containing the first character of
the range.
</p>
- </dd><dt class="field"><b>endLine: int</b></dt><dd>
+ </dd><dt class="field"><b>endLine: int<span style="color:#999999"> (optional)</span></b></dt><dd>
<p>
The one-based index of the line containing the character immediately
following the range.
</p>
- </dd><dt class="field"><b>endColumn: int</b></dt><dd>
+ </dd><dt class="field"><b>endColumn: int<span style="color:#999999"> (optional)</span></b></dt><dd>
<p>
The one-based index of the column containing the character immediately
diff --git a/pkg/analysis_server/lib/src/computer/computer_outline.dart b/pkg/analysis_server/lib/src/computer/computer_outline.dart
index 46408c8..c4247be 100644
--- a/pkg/analysis_server/lib/src/computer/computer_outline.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_outline.dart
@@ -85,8 +85,8 @@
var endLocation = resolvedUnit.lineInfo.getLocation(offset + length);
var endLine = endLocation.lineNumber;
var endColumn = endLocation.columnNumber;
- return Location(
- path, offset, length, startLine, startColumn, endLine, endColumn);
+ return Location(path, offset, length, startLine, startColumn,
+ endLine: endLine, endColumn: endColumn);
}
Outline _newClassOutline(ClassDeclaration node, List<Outline> classContents) {
diff --git a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
index d618f66..54ffabf 100644
--- a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
+++ b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
@@ -261,8 +261,8 @@
0, // length
declaration.locationStartLine,
declaration.locationStartColumn,
- declaration.locationStartLine, // endLine
- declaration.locationStartColumn, // endColumn
+ endLine: declaration.locationStartLine,
+ endColumn: declaration.locationStartColumn,
),
parameters: declaration.parameters,
returnType: declaration.returnType,
diff --git a/pkg/analysis_server/lib/src/protocol_server.dart b/pkg/analysis_server/lib/src/protocol_server.dart
index 5283798..7ad36bd 100644
--- a/pkg/analysis_server/lib/src/protocol_server.dart
+++ b/pkg/analysis_server/lib/src/protocol_server.dart
@@ -126,8 +126,8 @@
var endLine = endLocation.lineNumber;
var endColumn = endLocation.columnNumber;
- location = Location(
- file, offset, length, startLine, startColumn, endLine, endColumn);
+ location = Location(file, offset, length, startLine, startColumn,
+ endLine: endLine, endColumn: endColumn);
}
// Default to the error's severity if none is specified.
@@ -171,8 +171,8 @@
return DiagnosticMessage(
message.messageText(includeUrl: true),
- Location(
- file, offset, length, startLine, startColumn, endLine, endColumn));
+ Location(file, offset, length, startLine, startColumn,
+ endLine: endLine, endColumn: endColumn));
}
/// Create a Location based on an [engine.Element].
@@ -317,5 +317,6 @@
// should be able to throw an exception. Try removing the try statement.
}
return Location(unitElement.source.fullName, range.offset, range.length,
- startLine, startColumn, endLine, endColumn);
+ startLine, startColumn,
+ endLine: endLine, endColumn: endColumn);
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
index 8812c24..26a1a94 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/utilities.dart
@@ -158,7 +158,8 @@
bool isDeprecated = false}) {
var name = id.name;
// TODO(danrubel) use lineInfo to determine startLine and startColumn
- var location = Location(source.fullName, id.offset, id.length, 0, 0, 0, 0);
+ var location = Location(source.fullName, id.offset, id.length, 0, 0,
+ endLine: 0, endColumn: 0);
var flags = protocol.Element.makeFlags(
isAbstract: isAbstract,
isDeprecated: isDeprecated,
diff --git a/pkg/analysis_server/test/edit/fixes_test.dart b/pkg/analysis_server/test/edit/fixes_test.dart
index 53ba68b..ff64169 100644
--- a/pkg/analysis_server/test/edit/fixes_test.dart
+++ b/pkg/analysis_server/test/edit/fixes_test.dart
@@ -73,7 +73,7 @@
var fixes = plugin.AnalysisErrorFixes(AnalysisError(
AnalysisErrorSeverity.ERROR,
AnalysisErrorType.HINT,
- Location('', 0, 0, 0, 0, 0, 0),
+ Location('', 0, 0, 0, 0, endLine: 0, endColumn: 0),
'message',
'code'));
var result = plugin.EditGetFixesResult(<plugin.AnalysisErrorFixes>[fixes]);
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 3c0e282..3c3eecb 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -1104,15 +1104,16 @@
/// "length": int
/// "startLine": int
/// "startColumn": int
-/// "endLine": int
-/// "endColumn": int
+/// "endLine": optional int
+/// "endColumn": optional int
/// }
final Matcher isLocation = LazyMatcher(() => MatchesJsonObject('Location', {
'file': isFilePath,
'offset': isInt,
'length': isInt,
'startLine': isInt,
- 'startColumn': isInt,
+ 'startColumn': isInt
+ }, optionalFields: {
'endLine': isInt,
'endColumn': isInt
}));
diff --git a/pkg/analysis_server/test/lsp/diagnostic_test.dart b/pkg/analysis_server/test/lsp/diagnostic_test.dart
index 0f7ecf1..96c7f5a 100644
--- a/pkg/analysis_server/test/lsp/diagnostic_test.dart
+++ b/pkg/analysis_server/test/lsp/diagnostic_test.dart
@@ -30,12 +30,15 @@
final pluginError = plugin.AnalysisError(
plugin.AnalysisErrorSeverity.ERROR,
plugin.AnalysisErrorType.STATIC_TYPE_WARNING,
- plugin.Location(pluginAnalyzedFilePath, 0, 6, 0, 0, 0, 6),
+ plugin.Location(pluginAnalyzedFilePath, 0, 6, 0, 0,
+ endLine: 0, endColumn: 6),
'Test error from plugin',
'ERR1',
contextMessages: [
- plugin.DiagnosticMessage('Related error',
- plugin.Location(pluginAnalyzedFilePath, 31, 4, 1, 12, 1, 16))
+ plugin.DiagnosticMessage(
+ 'Related error',
+ plugin.Location(pluginAnalyzedFilePath, 31, 4, 1, 12,
+ endLine: 1, endColumn: 16))
],
);
final pluginResult =
@@ -317,7 +320,7 @@
final pluginError = plugin.AnalysisError(
plugin.AnalysisErrorSeverity.ERROR,
plugin.AnalysisErrorType.STATIC_TYPE_WARNING,
- plugin.Location(mainFilePath, 0, 1, 0, 0, 0, 1),
+ plugin.Location(mainFilePath, 0, 1, 0, 0, endLine: 0, endColumn: 1),
pluginErrorMessage,
'ERR1',
);
diff --git a/pkg/analysis_server/test/services/correction/status_test.dart b/pkg/analysis_server/test/services/correction/status_test.dart
index 41c0eec..055c0e4 100644
--- a/pkg/analysis_server/test/services/correction/status_test.dart
+++ b/pkg/analysis_server/test/services/correction/status_test.dart
@@ -98,7 +98,7 @@
}
void test_addFatalError_withLocation() {
- var location = Location('/test.dart', 1, 2, 3, 4, 5, 6);
+ var location = Location('/test.dart', 1, 2, 3, 4, endLine: 5, endColumn: 6);
var refactoringStatus = RefactoringStatus();
// initial state
expect(refactoringStatus.severity, null);
@@ -210,7 +210,7 @@
}
void test_newError() {
- var location = Location('/test.dart', 1, 2, 3, 4, 5, 6);
+ var location = Location('/test.dart', 1, 2, 3, 4, endLine: 5, endColumn: 6);
var refactoringStatus = RefactoringStatus.error('msg', location);
var problem = refactoringStatus.problem!;
var problemLocation = problem.location!;
diff --git a/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart b/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart
index 631dcac..4ad6049 100644
--- a/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart
+++ b/pkg/analysis_server/test/src/plugin/protocol_test_utilities.dart
@@ -79,7 +79,8 @@
Element element(int stringIndex, int intIndex, {ElementKind? kind}) =>
Element(kind ?? ElementKind.CLASS, strings[stringIndex++], intIndex++,
location: Location(fileName(stringIndex++), intIndex++, intIndex++,
- intIndex++, intIndex++, intIndex++, intIndex++),
+ intIndex++, intIndex++,
+ endLine: intIndex++, endColumn: intIndex++),
parameters: strings[stringIndex++],
returnType: strings[stringIndex++],
typeParameters: strings[stringIndex++]);
@@ -99,8 +100,8 @@
intIndex++,
intIndex++,
intIndex++,
- intIndex++,
- intIndex++);
+ endLine: intIndex++,
+ endColumn: intIndex++);
/// On return, increment [stringIndex] by 5 and [intIndex] by 7.
Occurrences occurrences(int stringIndex, int intIndex) {
diff --git a/pkg/analysis_server/test/src/plugin/result_merger_test.dart b/pkg/analysis_server/test/src/plugin/result_merger_test.dart
index 934e335..9affdc3 100644
--- a/pkg/analysis_server/test/src/plugin/result_merger_test.dart
+++ b/pkg/analysis_server/test/src/plugin/result_merger_test.dart
@@ -29,7 +29,8 @@
AnalysisError createError(int offset) {
var severity = AnalysisErrorSeverity.ERROR;
var type = AnalysisErrorType.HINT;
- var location = Location('test.dart', offset, 2, 3, 4, 5, 6);
+ var location =
+ Location('test.dart', offset, 2, 3, 4, endLine: 5, endColumn: 6);
return AnalysisError(severity, type, location, '', '');
}
@@ -68,7 +69,8 @@
AnalysisError createError(int offset) {
var severity = AnalysisErrorSeverity.ERROR;
var type = AnalysisErrorType.HINT;
- var location = Location('test.dart', offset, 2, 3, 4, 5, 6);
+ var location =
+ Location('test.dart', offset, 2, 3, 4, endLine: 5, endColumn: 6);
return AnalysisError(severity, type, location, '', '');
}
@@ -265,7 +267,7 @@
void test_mergeOutline() {
Element element(ElementKind kind, int offset) {
- var location = Location('', offset, 0, 0, 0, 0, 0);
+ var location = Location('', offset, 0, 0, 0, endLine: 0, endColumn: 0);
return Element(kind, '', 0, location: location);
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test.dart
index e2c4988..e983738 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/data_driven_test.dart
@@ -6,7 +6,6 @@
import 'package:analysis_server/src/services/correction/dart/data_driven.dart';
import 'package:analysis_server/src/services/correction/fix/data_driven/transform_set_manager.dart';
import 'package:analysis_server/src/services/correction/fix_internal.dart';
-import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/Location.java b/pkg/analysis_server/tool/spec/generated/java/types/Location.java
index 1df7d78..13e14bd 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/Location.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/Location.java
@@ -63,17 +63,17 @@
/**
* The one-based index of the line containing the character immediately following the range.
*/
- private final int endLine;
+ private final Integer endLine;
/**
* The one-based index of the column containing the character immediately following the range.
*/
- private final int endColumn;
+ private final Integer endColumn;
/**
* Constructor for {@link Location}.
*/
- public Location(String file, int offset, int length, int startLine, int startColumn, int endLine, int endColumn) {
+ public Location(String file, int offset, int length, int startLine, int startColumn, Integer endLine, Integer endColumn) {
this.file = file;
this.offset = offset;
this.length = length;
@@ -93,8 +93,8 @@
other.length == length &&
other.startLine == startLine &&
other.startColumn == startColumn &&
- other.endLine == endLine &&
- other.endColumn == endColumn;
+ ObjectUtilities.equals(other.endLine, endLine) &&
+ ObjectUtilities.equals(other.endColumn, endColumn);
}
return false;
}
@@ -105,8 +105,8 @@
int length = jsonObject.get("length").getAsInt();
int startLine = jsonObject.get("startLine").getAsInt();
int startColumn = jsonObject.get("startColumn").getAsInt();
- int endLine = jsonObject.get("endLine").getAsInt();
- int endColumn = jsonObject.get("endColumn").getAsInt();
+ Integer endLine = jsonObject.get("endLine") == null ? null : jsonObject.get("endLine").getAsInt();
+ Integer endColumn = jsonObject.get("endColumn") == null ? null : jsonObject.get("endColumn").getAsInt();
return new Location(file, offset, length, startLine, startColumn, endLine, endColumn);
}
@@ -125,14 +125,14 @@
/**
* The one-based index of the column containing the character immediately following the range.
*/
- public int getEndColumn() {
+ public Integer getEndColumn() {
return endColumn;
}
/**
* The one-based index of the line containing the character immediately following the range.
*/
- public int getEndLine() {
+ public Integer getEndLine() {
return endLine;
}
@@ -191,8 +191,12 @@
jsonObject.addProperty("length", length);
jsonObject.addProperty("startLine", startLine);
jsonObject.addProperty("startColumn", startColumn);
- jsonObject.addProperty("endLine", endLine);
- jsonObject.addProperty("endColumn", endColumn);
+ if (endLine != null) {
+ jsonObject.addProperty("endLine", endLine);
+ }
+ if (endColumn != null) {
+ jsonObject.addProperty("endColumn", endColumn);
+ }
return jsonObject;
}
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
index dfbd44c..76b7a2c 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
@@ -2884,8 +2884,8 @@
/// "length": int
/// "startLine": int
/// "startColumn": int
-/// "endLine": int
-/// "endColumn": int
+/// "endLine": optional int
+/// "endColumn": optional int
/// }
///
/// Clients may not extend, implement or mix-in this class.
@@ -2909,14 +2909,15 @@
/// The one-based index of the line containing the character immediately
/// following the range.
- int endLine;
+ int? endLine;
/// The one-based index of the column containing the character immediately
/// following the range.
- int endColumn;
+ int? endColumn;
- Location(this.file, this.offset, this.length, this.startLine,
- this.startColumn, this.endLine, this.endColumn);
+ Location(
+ this.file, this.offset, this.length, this.startLine, this.startColumn,
+ {this.endLine, this.endColumn});
factory Location.fromJson(
JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -2954,21 +2955,17 @@
} else {
throw jsonDecoder.mismatch(jsonPath, 'startColumn');
}
- int endLine;
+ int? endLine;
if (json.containsKey('endLine')) {
endLine = jsonDecoder.decodeInt(jsonPath + '.endLine', json['endLine']);
- } else {
- throw jsonDecoder.mismatch(jsonPath, 'endLine');
}
- int endColumn;
+ int? endColumn;
if (json.containsKey('endColumn')) {
endColumn =
jsonDecoder.decodeInt(jsonPath + '.endColumn', json['endColumn']);
- } else {
- throw jsonDecoder.mismatch(jsonPath, 'endColumn');
}
- return Location(
- file, offset, length, startLine, startColumn, endLine, endColumn);
+ return Location(file, offset, length, startLine, startColumn,
+ endLine: endLine, endColumn: endColumn);
} else {
throw jsonDecoder.mismatch(jsonPath, 'Location', json);
}
@@ -2982,8 +2979,14 @@
result['length'] = length;
result['startLine'] = startLine;
result['startColumn'] = startColumn;
- result['endLine'] = endLine;
- result['endColumn'] = endColumn;
+ var endLine = this.endLine;
+ if (endLine != null) {
+ result['endLine'] = endLine;
+ }
+ var endColumn = this.endColumn;
+ if (endColumn != null) {
+ result['endColumn'] = endColumn;
+ }
return result;
}
diff --git a/pkg/analyzer_plugin/doc/api.html b/pkg/analyzer_plugin/doc/api.html
index dbe9f26..96c8505 100644
--- a/pkg/analyzer_plugin/doc/api.html
+++ b/pkg/analyzer_plugin/doc/api.html
@@ -1579,13 +1579,13 @@
The one-based index of the column containing the first character of
the range.
</p>
- </dd><dt class="field"><b>endLine: int</b></dt><dd>
+ </dd><dt class="field"><b>endLine: int<span style="color:#999999"> (optional)</span></b></dt><dd>
<p>
The one-based index of the line containing the character immediately
following the range.
</p>
- </dd><dt class="field"><b>endColumn: int</b></dt><dd>
+ </dd><dt class="field"><b>endColumn: int<span style="color:#999999"> (optional)</span></b></dt><dd>
<p>
The one-based index of the column containing the character immediately
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index 691c48d..e437a89 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -2884,8 +2884,8 @@
/// "length": int
/// "startLine": int
/// "startColumn": int
-/// "endLine": int
-/// "endColumn": int
+/// "endLine": optional int
+/// "endColumn": optional int
/// }
///
/// Clients may not extend, implement or mix-in this class.
@@ -2909,14 +2909,15 @@
/// The one-based index of the line containing the character immediately
/// following the range.
- int endLine;
+ int? endLine;
/// The one-based index of the column containing the character immediately
/// following the range.
- int endColumn;
+ int? endColumn;
- Location(this.file, this.offset, this.length, this.startLine,
- this.startColumn, this.endLine, this.endColumn);
+ Location(
+ this.file, this.offset, this.length, this.startLine, this.startColumn,
+ {this.endLine, this.endColumn});
factory Location.fromJson(
JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -2954,21 +2955,17 @@
} else {
throw jsonDecoder.mismatch(jsonPath, 'startColumn');
}
- int endLine;
+ int? endLine;
if (json.containsKey('endLine')) {
endLine = jsonDecoder.decodeInt(jsonPath + '.endLine', json['endLine']);
- } else {
- throw jsonDecoder.mismatch(jsonPath, 'endLine');
}
- int endColumn;
+ int? endColumn;
if (json.containsKey('endColumn')) {
endColumn =
jsonDecoder.decodeInt(jsonPath + '.endColumn', json['endColumn']);
- } else {
- throw jsonDecoder.mismatch(jsonPath, 'endColumn');
}
- return Location(
- file, offset, length, startLine, startColumn, endLine, endColumn);
+ return Location(file, offset, length, startLine, startColumn,
+ endLine: endLine, endColumn: endColumn);
} else {
throw jsonDecoder.mismatch(jsonPath, 'Location', json);
}
@@ -2982,8 +2979,14 @@
result['length'] = length;
result['startLine'] = startLine;
result['startColumn'] = startColumn;
- result['endLine'] = endLine;
- result['endColumn'] = endColumn;
+ var endLine = this.endLine;
+ if (endLine != null) {
+ result['endLine'] = endLine;
+ }
+ var endColumn = this.endColumn;
+ if (endColumn != null) {
+ result['endColumn'] = endColumn;
+ }
return result;
}
diff --git a/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart b/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart
index 87af1a3..575cd5b 100644
--- a/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart
+++ b/pkg/analyzer_plugin/lib/utilities/analyzer_converter.dart
@@ -48,8 +48,9 @@
return plugin.AnalysisError(
convertErrorSeverity(severity),
convertErrorType(errorCode.type),
- plugin.Location(error.source.fullName, offset, error.length, startLine,
- startColumn, endLine, endColumn),
+ plugin.Location(
+ error.source.fullName, offset, error.length, startLine, startColumn,
+ endLine: endLine, endColumn: endColumn),
error.message,
errorCode.name.toLowerCase(),
contextMessages: contextMessages,
@@ -107,8 +108,8 @@
}
return plugin.DiagnosticMessage(
message.messageText(includeUrl: true),
- plugin.Location(
- file, offset, length, startLine, startColumn, endLine, endColumn));
+ plugin.Location(file, offset, length, startLine, startColumn,
+ endLine: endLine, endColumn: endColumn));
}
/// Convert the given [element] from the 'analyzer' package to an element
@@ -407,6 +408,7 @@
// Ignore exceptions
}
return plugin.Location(unitElement.source.fullName, range.offset,
- range.length, startLine, startColumn, endLine, endColumn);
+ range.length, startLine, startColumn,
+ endLine: endLine, endColumn: endColumn);
}
}
diff --git a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
index 19d5b1e..c161993 100644
--- a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
@@ -261,7 +261,8 @@
uriNode.offset,
uriNode.length,
protocol.ElementKind.LIBRARY,
- protocol.Location(source.fullName, 0, 0, 0, 0, 0, 0));
+ protocol.Location(source.fullName, 0, 0, 0, 0,
+ endLine: 0, endColumn: 0));
}
}
}
diff --git a/pkg/analyzer_plugin/pubspec.yaml b/pkg/analyzer_plugin/pubspec.yaml
index 1ee70fe..2b5441c 100644
--- a/pkg/analyzer_plugin/pubspec.yaml
+++ b/pkg/analyzer_plugin/pubspec.yaml
@@ -1,6 +1,6 @@
name: analyzer_plugin
description: A framework and support code for building plugins for the analysis server.
-version: 0.6.0
+version: 0.7.0-dev
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_plugin
environment:
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index 5c52f19..4ed7683 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -591,15 +591,16 @@
/// "length": int
/// "startLine": int
/// "startColumn": int
-/// "endLine": int
-/// "endColumn": int
+/// "endLine": optional int
+/// "endColumn": optional int
/// }
final Matcher isLocation = LazyMatcher(() => MatchesJsonObject('Location', {
'file': isFilePath,
'offset': isInt,
'length': isInt,
'startLine': isInt,
- 'startColumn': isInt,
+ 'startColumn': isInt
+ }, optionalFields: {
'endLine': isInt,
'endColumn': isInt
}));
diff --git a/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart b/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart
index 2c3dcfd..3c29dfb 100644
--- a/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart
+++ b/pkg/analyzer_plugin/test/plugin/navigation_mixin_test.dart
@@ -80,8 +80,8 @@
void computeNavigation(
NavigationRequest request, NavigationCollector collector) {
for (var i = 0; i < regionCount; i++) {
- collector.addRegion(
- i, 5, ElementKind.METHOD, Location('a', 5, 5, 1, 5, 1, 10));
+ collector.addRegion(i, 5, ElementKind.METHOD,
+ Location('a', 5, 5, 1, 5, endLine: 1, endColumn: 10));
}
}
}
diff --git a/pkg/analyzer_plugin/test/src/utilities/navigation/navigation_test.dart b/pkg/analyzer_plugin/test/src/utilities/navigation/navigation_test.dart
index 45179b0..5a76e0f 100644
--- a/pkg/analyzer_plugin/test/src/utilities/navigation/navigation_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/navigation/navigation_test.dart
@@ -24,14 +24,16 @@
var targetStartColumnA1 = 4;
var targetKindA1 = ElementKind.CLASS;
var targetLocationA1 = Location(fileA, targetOffsetA1, targetLengthA1,
- targetStartLineA1, targetStartColumnA1, 0, 0);
+ targetStartLineA1, targetStartColumnA1,
+ endLine: 0, endColumn: 0);
var targetOffsetA2 = 5;
var targetLengthA2 = 6;
var targetStartLineA2 = 7;
var targetStartColumnA2 = 8;
var targetKindA2 = ElementKind.FUNCTION;
var targetLocationA2 = Location(fileA, targetOffsetA2, targetLengthA2,
- targetStartLineA2, targetStartColumnA2, 0, 0);
+ targetStartLineA2, targetStartColumnA2,
+ endLine: 0, endColumn: 0);
var fileB = 'b.dart';
var targetOffsetB1 = 9;
@@ -40,14 +42,16 @@
var targetStartColumnB1 = 12;
var targetKindB1 = ElementKind.ENUM;
var targetLocationB1 = Location(fileB, targetOffsetB1, targetLengthB1,
- targetStartLineB1, targetStartColumnB1, 0, 0);
+ targetStartLineB1, targetStartColumnB1,
+ endLine: 0, endColumn: 0);
var targetOffsetB2 = 13;
var targetLengthB2 = 14;
var targetStartLineB2 = 15;
var targetStartColumnB2 = 16;
var targetKindB2 = ElementKind.METHOD;
var targetLocationB2 = Location(fileB, targetOffsetB2, targetLengthB2,
- targetStartLineB2, targetStartColumnB2, 0, 0);
+ targetStartLineB2, targetStartColumnB2,
+ endLine: 0, endColumn: 0);
// Six regions targeting a1, b1, a2, b1, a1, b2
var regionOffsets = <int>[17, 18, 19, 20, 21, 22];
@@ -112,7 +116,8 @@
var targetStartLine = 5;
var targetStartColumn = 1;
var targetLocation = Location(targetFile, targetOffset, targetLength,
- targetStartLine, targetStartColumn, 0, 0);
+ targetStartLine, targetStartColumn,
+ endLine: 0, endColumn: 0);
collector.addRegion(regionOffset, regionLength, targetKind, targetLocation);
collector.createRegions();
expect(collector.files, [targetFile]);
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index 1ec7a90..412fcb7 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -1057,14 +1057,14 @@
the range.
</p>
</field>
- <field name="endLine">
+ <field name="endLine" optional="true">
<ref>int</ref>
<p>
The one-based index of the line containing the character immediately
following the range.
</p>
</field>
- <field name="endColumn">
+ <field name="endColumn" optional="true">
<ref>int</ref>
<p>
The one-based index of the column containing the character immediately
diff --git a/pkg/compiler/lib/src/elements/types.dart b/pkg/compiler/lib/src/elements/types.dart
index 41e58eb..7b34a8a 100644
--- a/pkg/compiler/lib/src/elements/types.dart
+++ b/pkg/compiler/lib/src/elements/types.dart
@@ -911,86 +911,29 @@
R visit(covariant DartType type, A argument) => type.accept(this, argument);
- R visitLegacyType(covariant LegacyType type, A argument) => null;
+ R visitLegacyType(covariant LegacyType type, A argument);
- R visitNullableType(covariant NullableType type, A argument) => null;
+ R visitNullableType(covariant NullableType type, A argument);
- R visitNeverType(covariant NeverType type, A argument) => null;
+ R visitNeverType(covariant NeverType type, A argument);
- R visitVoidType(covariant VoidType type, A argument) => null;
+ R visitVoidType(covariant VoidType type, A argument);
- R visitTypeVariableType(covariant TypeVariableType type, A argument) => null;
+ R visitTypeVariableType(covariant TypeVariableType type, A argument);
- R visitFunctionTypeVariable(
- covariant FunctionTypeVariable type, A argument) =>
- null;
+ R visitFunctionTypeVariable(covariant FunctionTypeVariable type, A argument);
- R visitFunctionType(covariant FunctionType type, A argument) => null;
+ R visitFunctionType(covariant FunctionType type, A argument);
- R visitInterfaceType(covariant InterfaceType type, A argument) => null;
+ R visitInterfaceType(covariant InterfaceType type, A argument);
- R visitDynamicType(covariant DynamicType type, A argument) => null;
+ R visitDynamicType(covariant DynamicType type, A argument);
- R visitErasedType(covariant ErasedType type, A argument) => null;
+ R visitErasedType(covariant ErasedType type, A argument);
- R visitAnyType(covariant AnyType type, A argument) => null;
+ R visitAnyType(covariant AnyType type, A argument);
- R visitFutureOrType(covariant FutureOrType type, A argument) => null;
-}
-
-abstract class BaseDartTypeVisitor<R, A> extends DartTypeVisitor<R, A> {
- const BaseDartTypeVisitor();
-
- R visitType(covariant DartType type, A argument);
-
- @override
- R visitLegacyType(covariant LegacyType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitNullableType(covariant NullableType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitNeverType(covariant NeverType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitVoidType(covariant VoidType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitTypeVariableType(covariant TypeVariableType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitFunctionTypeVariable(
- covariant FunctionTypeVariable type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitFunctionType(covariant FunctionType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitInterfaceType(covariant InterfaceType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitDynamicType(covariant DynamicType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitErasedType(covariant ErasedType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitAnyType(covariant AnyType type, A argument) =>
- visitType(type, argument);
-
- @override
- R visitFutureOrType(covariant FutureOrType type, A argument) =>
- visitType(type, argument);
+ R visitFutureOrType(covariant FutureOrType type, A argument);
}
class _LegacyErasureVisitor extends DartTypeVisitor<DartType, Null> {
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index e8b00b7..3544fa3 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -557,9 +557,12 @@
/// key into maps.
final Map<LibraryEntity, String> _libraryKeys = {};
+ _TypeConstantRepresentationVisitor _typeConstantRepresenter;
+
Namer(this._closedWorld, this.fixedNames) {
_literalGetterPrefix = new StringBackedName(fixedNames.getterPrefix);
_literalSetterPrefix = new StringBackedName(fixedNames.setterPrefix);
+ _typeConstantRepresenter = _TypeConstantRepresentationVisitor(this);
}
JElementEnvironment get _elementEnvironment =>
@@ -1460,32 +1463,79 @@
}
}
- String getTypeRepresentationForTypeConstant(DartType type) {
- type = type.withoutNullability;
- if (type is DynamicType) return "dynamic";
- if (type is NeverType) return "Never";
- if (type is FutureOrType) {
- return "FutureOr<dynamic>";
- }
- if (type is FunctionType) {
- // TODO(johnniwinther): Add naming scheme for function type literals.
- // These currently only occur from kernel.
- return '()->';
- }
- InterfaceType interface = type;
- String name = uniqueNameForTypeConstantElement(
- interface.element.library, interface.element);
+ String getTypeRepresentationForTypeConstant(DartType type) =>
+ _typeConstantRepresenter.visit(type, null);
+}
+
+class _TypeConstantRepresentationVisitor extends DartTypeVisitor<String, Null> {
+ final Namer _namer;
+
+ _TypeConstantRepresentationVisitor(this._namer);
+
+ String _represent(DartType type) => visit(type, null);
+
+ @override
+ String visitLegacyType(LegacyType type, _) => '${_represent(type.baseType)}*';
+
+ @override
+ String visitNullableType(NullableType type, _) =>
+ '${_represent(type.baseType)}?';
+
+ @override
+ String visitNeverType(NeverType type, _) => 'Never';
+
+ @override
+ String visitVoidType(VoidType type, _) => 'void';
+
+ @override
+ String visitTypeVariableType(TypeVariableType type, _) {
+ throw StateError('Unexpected TypeVariableType $type');
+ }
+
+ @override
+ String visitFunctionTypeVariable(FunctionTypeVariable type, _) {
+ throw StateError('Unexpected FunctionTypeVariable $type');
+ }
+
+ @override
+ String visitFunctionType(FunctionType type, _) {
+ // TODO(johnniwinther): Add naming scheme for function type literals.
+ // These currently only occur from kernel.
+ return '()->';
+ }
+
+ @override
+ String visitInterfaceType(InterfaceType type, _) {
+ String name = _namer.uniqueNameForTypeConstantElement(
+ type.element.library, type.element);
// Type constants can currently only be raw types, so there is no point
// adding ground-term type parameters, as they would just be 'dynamic'.
// TODO(sra): Since the result string is used only in constructing constant
// names, it would result in more readable names if the final string was a
// legal JavaScript identifier.
- if (interface.typeArguments.isEmpty) return name;
+ if (type.typeArguments.isEmpty) return name;
String arguments =
- new List.filled(interface.typeArguments.length, 'dynamic').join(', ');
+ new List.filled(type.typeArguments.length, 'dynamic').join(', ');
return '$name<$arguments>';
}
+
+ @override
+ String visitDynamicType(DynamicType type, _) => 'dynamic';
+
+ @override
+ String visitErasedType(ErasedType type, _) {
+ throw StateError('Unexpected ErasedType $type');
+ }
+
+ @override
+ String visitAnyType(AnyType type, _) {
+ throw StateError('Unexpected AnyType $type');
+ }
+
+ @override
+ String visitFutureOrType(FutureOrType type, _) =>
+ 'FutureOr<${_represent(type.typeArgument)}>';
}
/// Returns a unique suffix for an intercepted accesses to [classes]. This is
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index e7113df..90b7b7c 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -829,8 +829,23 @@
}
@override
- void visitFutureOrType(FutureOrType type, _) {
- collect(type.typeArgument);
+ void visitNeverType(NeverType type, _) {}
+
+ @override
+ void visitVoidType(VoidType type, _) {}
+
+ @override
+ void visitTypeVariableType(TypeVariableType type, _) {}
+
+ @override
+ void visitFunctionTypeVariable(FunctionTypeVariable type, _) {}
+
+ @override
+ void visitFunctionType(FunctionType type, _) {
+ collect(type.returnType);
+ collectAll(type.parameterTypes);
+ collectAll(type.optionalParameterTypes);
+ collectAll(type.namedParameterTypes);
}
@override
@@ -840,11 +855,17 @@
}
@override
- void visitFunctionType(FunctionType type, _) {
- collect(type.returnType);
- collectAll(type.parameterTypes);
- collectAll(type.optionalParameterTypes);
- collectAll(type.namedParameterTypes);
+ void visitDynamicType(DynamicType type, _) {}
+
+ @override
+ void visitErasedType(ErasedType type, _) {}
+
+ @override
+ void visitAnyType(AnyType type, _) {}
+
+ @override
+ void visitFutureOrType(FutureOrType type, _) {
+ collect(type.typeArgument);
}
}
@@ -913,8 +934,10 @@
visitType(type.baseType, state);
@override
- void visitFutureOrType(FutureOrType type, TypeVisitorState state) =>
- visitType(type.typeArgument, state);
+ void visitNeverType(NeverType type, TypeVisitorState state) {}
+
+ @override
+ void visitVoidType(VoidType type, TypeVisitorState state) {}
@override
void visitTypeVariableType(TypeVariableType type, TypeVisitorState state) {
@@ -924,15 +947,14 @@
}
@override
- visitInterfaceType(InterfaceType type, TypeVisitorState state) {
- if (onClass != null) {
- onClass(type.element, state: state);
+ visitFunctionTypeVariable(FunctionTypeVariable type, TypeVisitorState state) {
+ if (_visitedFunctionTypeVariables.add(type)) {
+ visitType(type.bound, state);
}
- visitTypes(type.typeArguments, covariantArgument(state));
}
@override
- visitFunctionType(FunctionType type, TypeVisitorState state) {
+ void visitFunctionType(FunctionType type, TypeVisitorState state) {
if (onFunctionType != null) {
onFunctionType(type, state: state);
}
@@ -946,11 +968,25 @@
}
@override
- visitFunctionTypeVariable(FunctionTypeVariable type, TypeVisitorState state) {
- if (_visitedFunctionTypeVariables.add(type)) {
- visitType(type.bound, state);
+ void visitInterfaceType(InterfaceType type, TypeVisitorState state) {
+ if (onClass != null) {
+ onClass(type.element, state: state);
}
+ visitTypes(type.typeArguments, covariantArgument(state));
}
+
+ @override
+ void visitDynamicType(DynamicType type, TypeVisitorState state) {}
+
+ @override
+ void visitErasedType(ErasedType type, TypeVisitorState state) {}
+
+ @override
+ void visitAnyType(AnyType type, TypeVisitorState state) {}
+
+ @override
+ void visitFutureOrType(FutureOrType type, TypeVisitorState state) =>
+ visitType(type.typeArgument, state);
}
/// Runtime type usage for a class.
diff --git a/pkg/compiler/test/rti/rti_need_test_helper.dart b/pkg/compiler/test/rti/rti_need_test_helper.dart
index 4206006..5b15bb6 100644
--- a/pkg/compiler/test/rti/rti_need_test_helper.dart
+++ b/pkg/compiler/test/rti/rti_need_test_helper.dart
@@ -187,14 +187,16 @@
}
/// Visitor that determines whether a type refers to [entity].
-class FindTypeVisitor extends BaseDartTypeVisitor<bool, Null> {
+class FindTypeVisitor extends DartTypeVisitor<bool, Null> {
final Entity entity;
FindTypeVisitor(this.entity);
- bool visitTypes(List<DartType> types) {
+ bool check(DartType type) => visit(type, null);
+
+ bool checkList(List<DartType> types) {
for (DartType type in types) {
- if (type.accept(this, null)) {
+ if (check(type)) {
return true;
}
}
@@ -202,39 +204,47 @@
}
@override
- bool visitType(DartType type, _) => false;
-
- @override
bool visitLegacyType(LegacyType type, _) => visit(type.baseType, _);
@override
bool visitNullableType(NullableType type, _) => visit(type.baseType, _);
@override
- bool visitInterfaceType(InterfaceType type, _) {
- if (type.element == entity) return true;
- return visitTypes(type.typeArguments);
- }
+ bool visitNeverType(NeverType type, _) => false;
@override
- bool visitFunctionType(FunctionType type, _) {
- if (type.returnType.accept(this, null)) return true;
- if (visitTypes(type.typeVariables)) return true;
- if (visitTypes(type.parameterTypes)) return true;
- if (visitTypes(type.optionalParameterTypes)) return true;
- if (visitTypes(type.namedParameterTypes)) return true;
- return false;
- }
+ bool visitVoidType(VoidType type, _) => false;
@override
- bool visitTypeVariableType(TypeVariableType type, _) {
- return type.element.typeDeclaration == entity;
- }
+ bool visitTypeVariableType(TypeVariableType type, _) =>
+ type.element.typeDeclaration == entity;
@override
- bool visitFutureOrType(FutureOrType type, _) {
- return type.typeArgument.accept(this, null);
- }
+ bool visitFunctionTypeVariable(FunctionTypeVariable type, _) => false;
+
+ @override
+ bool visitFunctionType(FunctionType type, _) =>
+ type.returnType.accept(this, null) ||
+ checkList(type.typeVariables) ||
+ checkList(type.parameterTypes) ||
+ checkList(type.optionalParameterTypes) ||
+ checkList(type.namedParameterTypes);
+
+ @override
+ bool visitInterfaceType(InterfaceType type, _) =>
+ type.element == entity || checkList(type.typeArguments);
+
+ @override
+ bool visitDynamicType(DynamicType type, _) => false;
+
+ @override
+ bool visitErasedType(ErasedType type, _) => false;
+
+ @override
+ bool visitAnyType(AnyType type, _) => false;
+
+ @override
+ bool visitFutureOrType(FutureOrType type, _) => check(type.typeArgument);
}
class RtiNeedDataComputer extends DataComputer<String> {
diff --git a/pkg/dev_compiler/test/shared_test_options.dart b/pkg/dev_compiler/test/shared_test_options.dart
index 53d8879..88013a3 100644
--- a/pkg/dev_compiler/test/shared_test_options.dart
+++ b/pkg/dev_compiler/test/shared_test_options.dart
@@ -6,7 +6,6 @@
import 'package:cli_util/cli_util.dart';
import 'package:dev_compiler/dev_compiler.dart';
-import 'package:dev_compiler/src/compiler/module_builder.dart';
import 'package:front_end/src/api_unstable/ddc.dart';
import 'package:front_end/src/compute_platform_binaries_location.dart';
import 'package:front_end/src/fasta/incremental_serializer.dart';
diff --git a/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.transformed.expect b/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.transformed.expect
index f92bdce..a821c4b 100644
--- a/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/aot/enum_from_lib_used_as_type/main.dart.strong.transformed.expect
@@ -9,7 +9,10 @@
static method main() → dynamic {
core::List<dynamic> list = core::_GrowableList::•<dynamic>(0);
if(list.{core::Iterable::isNotEmpty}{core::bool}) {
- let dynamic #t1 = new mai::Class::•() in let dynamic #t2 = _in::unsafeCast<dynamic>(null) as{TypeError,ForDynamic,ForNonNullableByDefault} mai::Enum in throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+ block {
+ new mai::Class::•();
+ _in::unsafeCast<dynamic>(null) as{TypeError,ForDynamic,ForNonNullableByDefault} mai::Enum;
+ } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
}
}
diff --git a/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.transformed.expect b/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.transformed.expect
index 077bd72..0aaa3a0 100644
--- a/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/aot/tree_shake/main.dart.strong.transformed.expect
@@ -35,7 +35,10 @@
#C3;
core::List<self::UnusedEnum> list = core::_GrowableList::•<self::UnusedEnum>(0);
if(list.{core::Iterable::isNotEmpty}{core::bool}) {
- let dynamic #t2 = new mai::ConstClass::•() in let dynamic #t3 = _in::unsafeCast<dynamic>(null) as{TypeError,ForDynamic,ForNonNullableByDefault} mai::ConstEnum in throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+ block {
+ new mai::ConstClass::•();
+ _in::unsafeCast<dynamic>(null) as{TypeError,ForDynamic,ForNonNullableByDefault} mai::ConstEnum;
+ } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
}
}
diff --git a/pkg/nnbd_migration/lib/nnbd_migration.dart b/pkg/nnbd_migration/lib/nnbd_migration.dart
index e79df1f..aaa17c7 100644
--- a/pkg/nnbd_migration/lib/nnbd_migration.dart
+++ b/pkg/nnbd_migration/lib/nnbd_migration.dart
@@ -175,6 +175,12 @@
'Removed a null-aware assignment, because the target cannot be null',
kind: NullabilityFixKind.removeDeadCode);
+ /// A built_value `@nullable` annotation has been discarded.
+ static const removeNullableAnnotation = NullabilityFixDescription._(
+ appliedMessage: 'Discarded a use of the built_value annotation @nullable',
+ kind: NullabilityFixKind.removeNullableAnnotation,
+ );
+
/// A message used to indicate a fix has been applied.
final String appliedMessage;
@@ -293,6 +299,7 @@
removeAs,
removeDeadCode,
removeLanguageVersionComment,
+ removeNullableAnnotation,
replaceVar,
typeNotMadeNullable,
typeNotMadeNullableDueToHint,
diff --git a/pkg/nnbd_migration/lib/src/edge_builder.dart b/pkg/nnbd_migration/lib/src/edge_builder.dart
index 381a783..d155843 100644
--- a/pkg/nnbd_migration/lib/src/edge_builder.dart
+++ b/pkg/nnbd_migration/lib/src/edge_builder.dart
@@ -895,18 +895,20 @@
_dispatch(node.parameters);
var parameterElement = node.declaredElement as FieldFormalParameterElement;
var parameterType = _variables!.decoratedElementType(parameterElement);
- var field = parameterElement.field!;
- _fieldsNotInitializedByConstructor!.remove(field);
- var fieldType = _variables!.decoratedElementType(field);
- var origin = FieldFormalParameterOrigin(source, node);
- if (node.type == null) {
- _linkDecoratedTypes(parameterType, fieldType, origin, isUnion: false);
- _checkAssignment(origin, FixReasonTarget.root,
- source: fieldType, destination: parameterType, hard: false);
- } else {
- _dispatch(node.type);
- _checkAssignment(origin, FixReasonTarget.root,
- source: parameterType, destination: fieldType, hard: true);
+ var field = parameterElement.field;
+ if (field != null) {
+ _fieldsNotInitializedByConstructor!.remove(field);
+ var fieldType = _variables!.decoratedElementType(field);
+ var origin = FieldFormalParameterOrigin(source, node);
+ if (node.type == null) {
+ _linkDecoratedTypes(parameterType, fieldType, origin, isUnion: false);
+ _checkAssignment(origin, FixReasonTarget.root,
+ source: fieldType, destination: parameterType, hard: false);
+ } else {
+ _dispatch(node.type);
+ _checkAssignment(origin, FixReasonTarget.root,
+ source: parameterType, destination: fieldType, hard: true);
+ }
}
return null;
@@ -2083,7 +2085,10 @@
var result = <PropertyAccessorElement, FieldFormalParameterElement>{};
for (var parameter in constructorElement.parameters) {
if (parameter is FieldFormalParameterElement) {
- result[parameter.field!.getter!] = parameter;
+ var getter = parameter.field?.getter;
+ if (getter != null) {
+ result[getter] = parameter;
+ }
}
}
return result;
diff --git a/pkg/nnbd_migration/lib/src/edit_plan.dart b/pkg/nnbd_migration/lib/src/edit_plan.dart
index 1487963..b0e55fc 100644
--- a/pkg/nnbd_migration/lib/src/edit_plan.dart
+++ b/pkg/nnbd_migration/lib/src/edit_plan.dart
@@ -838,6 +838,8 @@
return node.members;
} else if (node is CompilationUnit) {
return [...node.directives, ...node.declarations];
+ } else if (node is MethodDeclaration) {
+ return node.metadata;
} else {
return null;
}
@@ -1542,7 +1544,8 @@
if (parent is Block ||
parent is ClassDeclaration ||
parent is CompilationUnit ||
- parent is FormalParameter) {
+ parent is FormalParameter ||
+ parent is MethodDeclaration) {
// These parent types don't use separators.
return null;
} else {
diff --git a/pkg/nnbd_migration/lib/src/fix_aggregator.dart b/pkg/nnbd_migration/lib/src/fix_aggregator.dart
index 7e74f7e..ddf1bb4 100644
--- a/pkg/nnbd_migration/lib/src/fix_aggregator.dart
+++ b/pkg/nnbd_migration/lib/src/fix_aggregator.dart
@@ -911,6 +911,34 @@
}
/// Implementation of [NodeChange] specialized for operating on
+/// [MethodDeclaration] nodes.
+class NodeChangeForMethodDeclaration extends NodeChange<MethodDeclaration> {
+ /// If non-null, indicates a `@nullable` annotation which should be removed
+ /// from this node.
+ Annotation? annotationToRemove;
+
+ /// If [annotationToRemove] is non-null, the information that should be
+ /// contained in the edit.
+ AtomicEditInfo? removeAnnotationInfo;
+
+ NodeChangeForMethodDeclaration() : super._();
+
+ @override
+ Iterable<String> get _toStringParts =>
+ [if (annotationToRemove != null) 'annotationToRemove'];
+
+ @override
+ EditPlan _apply(MethodDeclaration node, FixAggregator aggregator) {
+ return aggregator.planner.passThrough(node, innerPlans: [
+ if (annotationToRemove != null)
+ aggregator.planner
+ .removeNode(annotationToRemove!, info: removeAnnotationInfo),
+ ...aggregator.innerPlansForNode(node),
+ ]);
+ }
+}
+
+/// Implementation of [NodeChange] specialized for operating on
/// [MethodInvocation] nodes.
class NodeChangeForMethodInvocation
extends NodeChangeForExpression<MethodInvocation>
@@ -1423,6 +1451,10 @@
NodeChange visitIfStatement(IfStatement node) => NodeChangeForIfStatement();
@override
+ NodeChange visitMethodDeclaration(MethodDeclaration node) =>
+ NodeChangeForMethodDeclaration();
+
+ @override
NodeChange visitMethodInvocation(MethodInvocation node) =>
NodeChangeForMethodInvocation();
diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart
index 77fc0d3..3e08d2f 100644
--- a/pkg/nnbd_migration/lib/src/fix_builder.dart
+++ b/pkg/nnbd_migration/lib/src/fix_builder.dart
@@ -1147,15 +1147,18 @@
// Potentially add an explicit type to a field formal parameter.
var decl = node.declaredElement as FieldFormalParameterElement;
var decoratedType = _fixBuilder._variables!.decoratedElementType(decl);
- var decoratedFieldType =
- _fixBuilder._variables!.decoratedElementType(decl.field!);
- var typeToAdd = _fixBuilder._variables!.toFinalType(decoratedType);
- var fieldFinalType =
- _fixBuilder._variables!.toFinalType(decoratedFieldType);
- if (typeToAdd is InterfaceType &&
- !_fixBuilder._typeSystem.isSubtypeOf(fieldFinalType, typeToAdd)) {
- (_fixBuilder._getChange(node) as NodeChangeForFieldFormalParameter)
- .addExplicitType = typeToAdd;
+ var field = decl.field;
+ if (field != null) {
+ var decoratedFieldType =
+ _fixBuilder._variables!.decoratedElementType(field);
+ var typeToAdd = _fixBuilder._variables!.toFinalType(decoratedType);
+ var fieldFinalType =
+ _fixBuilder._variables!.toFinalType(decoratedFieldType);
+ if (typeToAdd is InterfaceType &&
+ !_fixBuilder._typeSystem.isSubtypeOf(fieldFinalType, typeToAdd)) {
+ (_fixBuilder._getChange(node) as NodeChangeForFieldFormalParameter)
+ .addExplicitType = typeToAdd;
+ }
}
} else if (node.parameters != null) {
// Handle function-typed field formal parameters.
@@ -1198,6 +1201,31 @@
}
@override
+ void visitMethodDeclaration(MethodDeclaration node) {
+ if (node.isGetter && node.isAbstract) {
+ for (var annotation in node.metadata) {
+ if (annotation.arguments == null) {
+ var element = annotation.element;
+ if (element is PropertyAccessorElement &&
+ element.name == 'nullable') {
+ if (element.enclosingElement is CompilationUnitElement) {
+ if (element.library.source.uri.toString() ==
+ 'package:built_value/built_value.dart') {
+ var info = AtomicEditInfo(
+ NullabilityFixDescription.removeNullableAnnotation, {});
+ (_fixBuilder._getChange(node) as NodeChangeForMethodDeclaration)
+ ..annotationToRemove = annotation
+ ..removeAnnotationInfo = info;
+ }
+ }
+ }
+ }
+ }
+ }
+ super.visitMethodDeclaration(node);
+ }
+
+ @override
void visitTypeName(TypeName node) {
var decoratedType = _fixBuilder._variables!
.decoratedTypeAnnotation(_fixBuilder.source, node);
diff --git a/pkg/nnbd_migration/lib/src/front_end/info_builder.dart b/pkg/nnbd_migration/lib/src/front_end/info_builder.dart
index b471651..c6f4bb7 100644
--- a/pkg/nnbd_migration/lib/src/front_end/info_builder.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/info_builder.dart
@@ -265,6 +265,10 @@
case NullabilityFixKind.addThen:
// We don't offer any edits around addition of `.then` to a future.
break;
+ case NullabilityFixKind.removeNullableAnnotation:
+ // We don't offer any edits around removal of built_value `@nullable`
+ // annotations.
+ break;
}
return edits;
}
diff --git a/pkg/nnbd_migration/lib/src/front_end/migration_summary.dart b/pkg/nnbd_migration/lib/src/front_end/migration_summary.dart
index 7a72ee6..90adae8 100644
--- a/pkg/nnbd_migration/lib/src/front_end/migration_summary.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/migration_summary.dart
@@ -113,6 +113,8 @@
return 'typeNotMadeNullable';
case NullabilityFixKind.typeNotMadeNullableDueToHint:
return 'typeNotMadeNullableDueToHint';
+ case NullabilityFixKind.removeNullableAnnotation:
+ return 'removeNullableAnnotation';
}
}
}
diff --git a/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart b/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart
index bed1a35..fea31af 100644
--- a/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/non_nullable_fix.dart
@@ -277,8 +277,8 @@
var edit = SourceEdit(offset, configText.length, newText);
listener.addSourceFileEdit(
'enable Null Safety language feature',
- Location(
- packageConfigFile.path, offset, newText.length, line, 0, 0, 0),
+ Location(packageConfigFile.path, offset, newText.length, line, 0,
+ endLine: 0, endColumn: 0),
SourceFileEdit(packageConfigFile.path, 0, edits: [edit]));
}
} on FormatException catch (e) {
@@ -599,7 +599,8 @@
var edit = SourceEdit(offset, 0, content);
listener.addSourceFileEdit(
'enable Null Safety language feature',
- Location(path, offset, content.length, line, 0, 0, 0),
+ Location(path, offset, content.length, line, 0,
+ endLine: 0, endColumn: 0),
SourceFileEdit(path, 0, edits: [edit]));
}
@@ -609,7 +610,8 @@
var edit = SourceEdit(offset, span.length, content);
listener.addSourceFileEdit(
'enable Null Safety language feature',
- Location(path, offset, content.length, line, 0, 0, 0),
+ Location(path, offset, content.length, line, 0,
+ endLine: 0, endColumn: 0),
SourceFileEdit(path, 0, edits: [edit]));
}
diff --git a/pkg/nnbd_migration/lib/src/front_end/unit_renderer.dart b/pkg/nnbd_migration/lib/src/front_end/unit_renderer.dart
index c5f8ef3..6b6257cc 100644
--- a/pkg/nnbd_migration/lib/src/front_end/unit_renderer.dart
+++ b/pkg/nnbd_migration/lib/src/front_end/unit_renderer.dart
@@ -43,6 +43,7 @@
NullabilityFixKind.removeAs,
NullabilityFixKind.addLate,
NullabilityFixKind.addLateDueToTestSetup,
+ NullabilityFixKind.removeNullableAnnotation,
NullabilityFixKind.addLateDueToHint,
NullabilityFixKind.addLateFinalDueToHint,
NullabilityFixKind.checkExpressionDueToHint,
@@ -337,6 +338,8 @@
return '$count type$s not made nullable';
case NullabilityFixKind.typeNotMadeNullableDueToHint:
return '$count type$s not made nullable due to hint$s';
+ case NullabilityFixKind.removeNullableAnnotation:
+ return '$count @nullable annotation$s removed';
}
}
diff --git a/pkg/nnbd_migration/lib/src/node_builder.dart b/pkg/nnbd_migration/lib/src/node_builder.dart
index 14fd871..b50bed1 100644
--- a/pkg/nnbd_migration/lib/src/node_builder.dart
+++ b/pkg/nnbd_migration/lib/src/node_builder.dart
@@ -446,9 +446,10 @@
@override
DecoratedType? visitMethodDeclaration(MethodDeclaration node) {
- _handleExecutableDeclaration(
+ var declaredElement = node.declaredElement;
+ var decoratedType = _handleExecutableDeclaration(
node,
- node.declaredElement!,
+ declaredElement!,
node.metadata,
node.returnType,
node.typeParameters,
@@ -456,6 +457,19 @@
null,
node.body,
null);
+ if (declaredElement is PropertyAccessorElement) {
+ // Store a decorated type for the synthetic field so that in case we try
+ // to access it later we won't crash (this could happen due to errors in
+ // the source code).
+ if (declaredElement.isGetter) {
+ _variables!.recordDecoratedElementType(
+ declaredElement.variable, decoratedType.returnType);
+ } else {
+ _variables!.recordDecoratedElementType(
+ declaredElement.variable, decoratedType.positionalParameters![0],
+ soft: true);
+ }
+ }
return null;
}
@@ -675,7 +689,7 @@
}
/// Common handling of function and method declarations.
- void _handleExecutableDeclaration(
+ DecoratedType _handleExecutableDeclaration(
AstNode node,
ExecutableElement declaredElement,
NodeList<Annotation>? metadata,
@@ -726,6 +740,7 @@
}
_variables!
.recordDecoratedElementType(declaredElement, decoratedFunctionType);
+ return decoratedFunctionType;
}
DecoratedType? _handleFormalParameter(
diff --git a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
index be547dc..f22569b 100644
--- a/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
+++ b/pkg/nnbd_migration/lib/src/nullability_migration_impl.dart
@@ -270,8 +270,8 @@
edit.length,
startLocation.lineNumber,
startLocation.columnNumber,
- endLocation.lineNumber,
- endLocation.columnNumber,
+ endLine: endLocation.lineNumber,
+ endColumn: endLocation.columnNumber,
);
return location;
}
diff --git a/pkg/nnbd_migration/lib/src/variables.dart b/pkg/nnbd_migration/lib/src/variables.dart
index 44d0475..7222753 100644
--- a/pkg/nnbd_migration/lib/src/variables.dart
+++ b/pkg/nnbd_migration/lib/src/variables.dart
@@ -214,7 +214,8 @@
}
/// Associates decorated type information with the given [element].
- void recordDecoratedElementType(Element? element, DecoratedType? type) {
+ void recordDecoratedElementType(Element? element, DecoratedType? type,
+ {bool soft = false}) {
assert(() {
assert(element is! TypeParameterElement,
'Use recordDecoratedTypeParameterBound instead');
@@ -227,6 +228,9 @@
}
return true;
}());
+ if (soft && _decoratedElementTypes.containsKey(element)) {
+ return;
+ }
_decoratedElementTypes[element] = type;
}
diff --git a/pkg/nnbd_migration/test/api_test.dart b/pkg/nnbd_migration/test/api_test.dart
index df8afb3..cc1bc01 100644
--- a/pkg/nnbd_migration/test/api_test.dart
+++ b/pkg/nnbd_migration/test/api_test.dart
@@ -116,7 +116,7 @@
///
/// Optional parameter [removeViaComments] indicates whether dead code should
/// be removed in its entirety (the default) or removed by commenting it out.
- Future<void> _checkSingleFileChanges(String content, String expected,
+ Future<void> _checkSingleFileChanges(String content, dynamic expected,
{Map<String, String> migratedInput = const {},
bool removeViaComments = false,
bool warnOnWeakCode = false,
@@ -548,6 +548,58 @@
{path1: file1, path2: file2}, {path1: expected1, path2: anything});
}
+ Future<void> test_built_value_nullable_getter() async {
+ addBuiltValuePackage();
+ var root = '$projectPath/lib';
+ var path1 = convertPath('$root/lib.dart');
+ var file1 = r'''
+import 'package:built_value/built_value.dart';
+
+part 'lib.g.dart';
+
+abstract class Foo implements Built<Foo, FooBuilder> {
+ @nullable
+ int get value;
+ Foo._();
+ factory Foo([void Function(FooBuilder) updates]) = _$Foo;
+}
+''';
+ var expected1 = r'''
+import 'package:built_value/built_value.dart';
+
+part 'lib.g.dart';
+
+abstract class Foo implements Built<Foo, FooBuilder> {
+ int? get value;
+ Foo._();
+ factory Foo([void Function(FooBuilder) updates]) = _$Foo;
+}
+''';
+ // Note: in a real-world scenario the generated file would be in a different
+ // directory but we don't need to simulate that detail for this test. Also,
+ // the generated file would have a lot more code in it, but we don't need to
+ // simulate all the details of what is generated.
+ var path2 = convertPath('$root/lib.g.dart');
+ var file2 = r'''
+part of 'lib.dart';
+
+class _$Foo extends Foo {
+ @override
+ final int value;
+
+ factory _$Foo([void Function(FooBuilder) updates]) => throw '';
+
+ _$Foo._({this.value}) : super._();
+}
+
+class FooBuilder implements Builder<Foo, FooBuilder> {
+ int get value => throw '';
+}
+''';
+ await _checkMultipleFileChanges(
+ {path1: file1, path2: file2}, {path1: expected1, path2: anything});
+ }
+
Future<void> test_call_already_migrated_extension() async {
var content = '''
import 'already_migrated.dart';
@@ -1164,6 +1216,41 @@
await _checkSingleFileChanges(content, expected);
}
+ Future<void> test_constructor_field_formal_resolves_to_getter() async {
+ var content = '''
+class C {
+ int get i => 0;
+ C(this.i);
+}
+''';
+ // It doesn't matter what the migration produces; we just want to make sure
+ // there isn't a crash.
+ await _checkSingleFileChanges(content, anything, allowErrors: true);
+ }
+
+ Future<void> test_constructor_field_formal_resolves_to_setter() async {
+ var content = '''
+class C {
+ set i(int value) {}
+ C(this.i);
+}
+''';
+ // It doesn't matter what the migration produces; we just want to make sure
+ // there isn't a crash.
+ await _checkSingleFileChanges(content, anything, allowErrors: true);
+ }
+
+ Future<void> test_constructor_field_formal_unresolved() async {
+ var content = '''
+class C {
+ C(this.i);
+}
+''';
+ // It doesn't matter what the migration produces; we just want to make sure
+ // there isn't a crash.
+ await _checkSingleFileChanges(content, anything, allowErrors: true);
+ }
+
Future<void> test_constructor_optional_param_factory() async {
var content = '''
class C {
diff --git a/pkg/nnbd_migration/test/edit_plan_test.dart b/pkg/nnbd_migration/test/edit_plan_test.dart
index 3cf4039..135ec47 100644
--- a/pkg/nnbd_migration/test/edit_plan_test.dart
+++ b/pkg/nnbd_migration/test/edit_plan_test.dart
@@ -903,6 +903,24 @@
int? x}) {}''');
}
+ Future<void> test_remove_metadata_from_method_declaration() async {
+ await analyze('''
+class C {
+ @deprecated
+ f() {}
+}
+''');
+ var deprecated = findNode.annotation('@deprecated');
+ checkPlan(
+ planner!.passThrough(deprecated.parent,
+ innerPlans: [planner!.removeNode(deprecated)]),
+ '''
+class C {
+ f() {}
+}
+''');
+ }
+
Future<void> test_remove_parameter() async {
await analyze('f(int x, int y, int z) => null;');
var parameter = findNode.simple('y').parent!;
diff --git a/pkg/nnbd_migration/test/preview/preview_site_test.dart b/pkg/nnbd_migration/test/preview/preview_site_test.dart
index aeee9da..872d4d0 100644
--- a/pkg/nnbd_migration/test/preview/preview_site_test.dart
+++ b/pkg/nnbd_migration/test/preview/preview_site_test.dart
@@ -65,7 +65,7 @@
// Add a source change for analysis_options, which has no UnitInfo.
dartfixListener!.addSourceFileEdit(
'enable experiment',
- Location(analysisOptionsPath, 9, 0, 1, 9, 1, 9),
+ Location(analysisOptionsPath, 9, 0, 1, 9, endLine: 1, endColumn: 9),
SourceFileEdit(analysisOptionsPath, 0, edits: [
SourceEdit(9, 0, '\n enable-experiment:\n - non-nullable')
]));
@@ -100,7 +100,7 @@
file.writeAsStringSync(currentContent);
dartfixListener!.addSourceFileEdit(
'test change',
- Location(path, 10, 0, 1, 10, 1, 10),
+ Location(path, 10, 0, 1, 10, endLine: 1, endColumn: 10),
SourceFileEdit(path, 0, edits: [SourceEdit(10, 0, 'List args')]));
expect(() => site.performApply([]), throwsA(isA<StateError>()));
expect(file.readAsStringSync(), currentContent);
@@ -115,7 +115,7 @@
site.unitInfoMap[path] = UnitInfo(path)..diskContent = content;
dartfixListener!.addSourceFileEdit(
'test change',
- Location(path, 10, 0, 1, 10, 1, 10),
+ Location(path, 10, 0, 1, 10, endLine: 1, endColumn: 10),
SourceFileEdit(path, 0, edits: [
SourceEdit(10, 0, 'List args'),
SourceEdit(13, 0, '\n print(args);\n')
@@ -136,7 +136,7 @@
site.unitInfoMap[path] = UnitInfo(path)..diskContent = content;
dartfixListener!.addSourceFileEdit(
'test change',
- Location(path, 10, 0, 1, 10, 1, 10),
+ Location(path, 10, 0, 1, 10, endLine: 1, endColumn: 10),
SourceFileEdit(path, 0, edits: [SourceEdit(10, 0, 'List args')]));
site.performApply([]);
expect(file.readAsStringSync(), 'void main(List args) {}');
@@ -430,7 +430,7 @@
..wasExplicitlyOptedOut = true;
dartfixListener!.addSourceFileEdit(
'remove DLV comment',
- Location(path, 0, 14, 1, 1, 3, 1),
+ Location(path, 0, 14, 1, 1, endLine: 3, endColumn: 1),
SourceFileEdit(path, 0, edits: [SourceEdit(0, 14, '')]));
var navigationTree =
NavigationTreeRenderer(migrationInfo, state!.pathMapper).render();
@@ -471,7 +471,7 @@
..wasExplicitlyOptedOut = false;
dartfixListener!.addSourceFileEdit(
'test change',
- Location(path, 10, 0, 1, 10, 1, 10),
+ Location(path, 10, 0, 1, 10, endLine: 1, endColumn: 10),
SourceFileEdit(path, 0, edits: [SourceEdit(10, 0, 'List args')]));
var navigationTree =
NavigationTreeRenderer(migrationInfo, state!.pathMapper).render();
@@ -525,11 +525,11 @@
..wasExplicitlyOptedOut = false;
dartfixListener!.addSourceFileEdit(
'test change',
- Location(pathA, 10, 0, 1, 10, 1, 10),
+ Location(pathA, 10, 0, 1, 10, endLine: 1, endColumn: 10),
SourceFileEdit(pathA, 0, edits: [SourceEdit(10, 0, 'List args')]));
dartfixListener!.addSourceFileEdit(
'test change',
- Location(pathB, 10, 0, 1, 10, 1, 10),
+ Location(pathB, 10, 0, 1, 10, endLine: 1, endColumn: 10),
SourceFileEdit(pathB, 0, edits: [SourceEdit(10, 0, 'List args')]));
var navigationTree =
NavigationTreeRenderer(migrationInfo, state!.pathMapper).render();
@@ -563,7 +563,7 @@
..wasExplicitlyOptedOut = true;
dartfixListener!.addSourceFileEdit(
'remove DLV comment',
- Location(path, 0, 14, 1, 1, 3, 1),
+ Location(path, 0, 14, 1, 1, endLine: 3, endColumn: 1),
SourceFileEdit(path, 0, edits: [SourceEdit(0, 14, '')]));
var navigationTree =
NavigationTreeRenderer(migrationInfo, state!.pathMapper).render();
diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart
index e84e660..7271f50 100644
--- a/pkg/vm/lib/transformations/ffi_definitions.dart
+++ b/pkg/vm/lib/transformations/ffi_definitions.dart
@@ -846,8 +846,8 @@
isStatic: true)
..fileOffset = compound.fileOffset
..isNonNullableByDefault = true
- ..addAnnotation(ConstantExpression(InstanceConstant(pragmaClass.reference,
- /*type_arguments=*/ [], {
+ ..addAnnotation(ConstantExpression(
+ InstanceConstant(pragmaClass.reference, /*type_arguments=*/ [], {
pragmaName.getterReference: StringConstant("vm:prefer-inline"),
pragmaOptions.getterReference: NullConstant(),
})));
diff --git a/pkg/vm/lib/transformations/type_flow/signature_shaking.dart b/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
index 2d16a7b..f24d9af 100644
--- a/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
+++ b/pkg/vm/lib/transformations/type_flow/signature_shaking.dart
@@ -402,7 +402,7 @@
// as required positional parameters, alphabetically by name.
final List<VariableDeclaration> sortedNamed = function.namedParameters
.toList()
- ..sort((var1, var2) => var1.name.compareTo(var2.name));
+ ..sort((var1, var2) => var1.name.compareTo(var2.name));
for (VariableDeclaration variable in sortedNamed) {
final _ParameterInfo param = info.named[variable.name];
if (param.isAlwaysPassed) {
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index e9473dd..285990d 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -9,6 +9,7 @@
import 'package:kernel/target/targets.dart';
import 'package:kernel/ast.dart' hide Statement, StatementVisitor;
+import 'package:kernel/ast.dart' as ast show Statement;
import 'package:kernel/clone.dart' show CloneVisitorNotMembers;
import 'package:kernel/core_types.dart' show CoreTypes;
import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
@@ -1030,20 +1031,35 @@
}
bool _isThrowExpression(Expression expr) {
- while (expr is Let) {
- expr = (expr as Let).body;
+ for (;;) {
+ if (expr is Let) {
+ expr = (expr as Let).body;
+ } else if (expr is BlockExpression) {
+ expr = (expr as BlockExpression).value;
+ } else {
+ break;
+ }
}
return expr is Throw;
}
- TreeNode _evaluateArguments(List<Expression> args, Expression result) {
- Expression node = result;
- for (var arg in args.reversed) {
+ Expression _evaluateArguments(List<Expression> args, Expression result) {
+ final List<ast.Statement> statements = <ast.Statement>[];
+ for (var arg in args) {
if (mayHaveSideEffects(arg)) {
- node = Let(VariableDeclaration(null, initializer: arg), node);
+ statements.add(ExpressionStatement(arg));
}
}
- return node;
+ if (statements.isEmpty) {
+ return result;
+ }
+ // Merge nested BlockExpression nodes.
+ Expression value = result;
+ if (result is BlockExpression) {
+ statements.addAll(result.body.statements);
+ value = result.value;
+ }
+ return BlockExpression(Block(statements), value);
}
TreeNode _makeUnreachableCall(List<Expression> args) {
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
index 92746ce..599ca03 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/bench_vector.dart.expect
@@ -15,7 +15,10 @@
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasTearOffUses:false,methodOrSetterSelectorId:4] [@vm.unboxing-info.metadata=(b)->d] operator []([@vm.inferred-type.metadata=!] core::int* i) → core::double*
return [@vm.direct-call.metadata=dart.typed_data::_Float64List.[]] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.direct-call.metadata=#lib::_Vector._elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}{core::List<core::double*>*}.{core::List::[]}([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}([@vm.direct-call.metadata=#lib::_Vector._offset] [@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] this.{self::_Vector::_offset}{core::int*}){(core::num*) →* core::int*}){(core::int*) →* core::double*};
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5] operator []=([@vm.inferred-type.metadata=dart.core::_OneByteString] core::int* i, core::double* value) → void {
- let dynamic #t1 = [@vm.direct-call.metadata=#lib::_Vector._elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}{core::List<core::double*>*} in let dynamic #t2 = [@vm.direct-call.metadata=#lib::_Vector._offset] [@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] this.{self::_Vector::_offset}{core::int*} in throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
+ block {
+ [@vm.direct-call.metadata=#lib::_Vector._elements] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}{core::List<core::double*>*};
+ [@vm.direct-call.metadata=#lib::_Vector._offset] [@vm.inferred-type.metadata=dart.core::_Smi (value: 0)] this.{self::_Vector::_offset}{core::int*};
+ } =>throw "Attempt to execute code removed by Dart AOT compiler (TFA)";
}
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6] [@vm.unboxing-info.metadata=(b)->d] operator *([@vm.inferred-type.metadata=#lib::_Vector?] self::_Vector* a) → core::double* {
core::double* result = 0.0;
@@ -27,9 +30,9 @@
[@vm.inferred-type.metadata=#lib::_Vector?]static field self::_Vector* v = new self::_Vector::•();
[@vm.inferred-type.metadata=dart.core::_Double?]static field core::double* x = 0.0;
static method main(core::List<core::String*>* args) → dynamic {
- core::Stopwatch* timer = let final core::Stopwatch* #t3 = new core::Stopwatch::•() in block {
- [@vm.direct-call.metadata=dart.core::Stopwatch.start] [@vm.inferred-type.metadata=!? (skip check)] #t3.{core::Stopwatch::start}(){() →* void};
- } =>#t3;
+ core::Stopwatch* timer = let final core::Stopwatch* #t1 = new core::Stopwatch::•() in block {
+ [@vm.direct-call.metadata=dart.core::Stopwatch.start] [@vm.inferred-type.metadata=!? (skip check)] #t1.{core::Stopwatch::start}(){() →* void};
+ } =>#t1;
for (core::int* i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation.<] [@vm.inferred-type.metadata=dart.core::bool (skip check)] i.{core::num::<}(100000000){(core::num*) →* core::bool*}; i = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] i.{core::num::+}(1){(core::num*) →* core::int*}) {
self::x = [@vm.direct-call.metadata=dart.core::_Double.+??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.inferred-type.metadata=dart.core::_Double?] self::x.{core::double::+}([@vm.direct-call.metadata=#lib::_Vector.*??] [@vm.inferred-type.metadata=dart.core::_Double (skip check)] [@vm.inferred-type.metadata=#lib::_Vector?] self::v.{self::_Vector::*}([@vm.inferred-type.metadata=#lib::_Vector?] self::v){(self::_Vector*) →* core::double*}){(core::num*) →* core::double*};
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
index 7e7de62..2fa9807 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/null_test_elimination.dart.expect
@@ -13,7 +13,9 @@
}
[@vm.inferred-type.metadata=#lib::A?]static field self::A* staticField = new self::A::•("hi", "bye");
static method testNonNullableIf1([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
- if(let dynamic #t1 = [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*} in false) {
+ if( block {
+ [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*};
+ } =>false) {
core::print("null");
}
}
@@ -23,12 +25,16 @@
}
}
static method testAlwaysNullIf1([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
- if(let dynamic #t2 = [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*} in true) {
+ if( block {
+ [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*};
+ } =>true) {
core::print("null");
}
}
static method testNonNullableIf2([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
- if(!(let dynamic #t3 = [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*} in false) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
+ if(!( block {
+ [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*};
+ } =>false) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
core::print("not null");
}
}
@@ -38,16 +44,22 @@
}
}
static method testAlwaysNullIf2([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic {
- if(!(let dynamic #t4 = [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*} in true) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
+ if(!( block {
+ [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*};
+ } =>true) && _in::unsafeCast<core::bool*>([@vm.inferred-type.metadata=dart.core::bool] self::someCondition())) {
core::print("not null");
}
}
static method testNonNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
- return !(let dynamic #t5 = [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*} in false) ?{core::String*} "not null" : "null";
+ return !( block {
+ [@vm.direct-call.metadata=#lib::A.nonNullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString] a.{self::A::nonNullable}{core::String*};
+ } =>false) ?{core::String*} "not null" : "null";
static method testNullableCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
return !([@vm.direct-call.metadata=#lib::A.nullable??] [@vm.inferred-type.metadata=dart.core::_OneByteString?] a.{self::A::nullable}{core::String*} == null) ?{core::String*} "not null" : "null";
static method testAlwaysNullCondExpr([@vm.inferred-type.metadata=#lib::A?] self::A* a) → dynamic
- return !(let dynamic #t6 = [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*} in true) ?{core::String*} "not null" : "null";
+ return !( block {
+ [@vm.direct-call.metadata=#lib::A.alwaysNull??] [@vm.inferred-type.metadata=dart.core::Null? (value: null)] a.{self::A::alwaysNull}{core::String*};
+ } =>true) ?{core::String*} "not null" : "null";
static method someCondition() → dynamic
return [@vm.inferred-type.metadata=dart.core::bool] [@vm.inferred-type.metadata=int?] core::int::parse("1") =={core::num::==}{(core::Object*) →* core::bool*} 1;
static method main() → void {
diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md
index 4d071d5..3c1a964 100644
--- a/pkg/vm_service/CHANGELOG.md
+++ b/pkg/vm_service/CHANGELOG.md
@@ -1,8 +1,12 @@
# Changelog
## 7.1.1
-- Update to version `3.47` of the spec.
+- Update to version `3.48` of the spec.
- Added `shows` and `hides` properties to `LibraryDependency`.
+- Added `Profiler` stream, `UserTagChanged` event kind, and `updatedTag` and
+ `previousTag` properties to `Event`.
+- Fixed bug where a response without a type would cause a null type failure
+ (dart-lang/sdk#46559).
## 7.1.0
- Update to version `3.46` of the spec.
diff --git a/pkg/vm_service/lib/src/vm_service.dart b/pkg/vm_service/lib/src/vm_service.dart
index 903bb0c..70c6db8 100644
--- a/pkg/vm_service/lib/src/vm_service.dart
+++ b/pkg/vm_service/lib/src/vm_service.dart
@@ -44,7 +44,7 @@
if (json is List) {
return json.map((e) => createServiceObject(e, expectedTypes)).toList();
- } else if (json is Map) {
+ } else if (json is Map<String, dynamic>) {
String? type = json['type'];
// Not a Response type.
@@ -53,7 +53,7 @@
if (expectedTypes.length == 1) {
type = expectedTypes.first;
} else {
- return null;
+ return Response.parse(json);
}
} else if (_isNullInstance(json) &&
(!expectedTypes.contains('InstanceRef'))) {
@@ -824,8 +824,7 @@
/// returned.
Future<SourceReport> getSourceReport(
String isolateId,
- /*List<SourceReportKind>*/
- List<String> reports, {
+ /*List<SourceReportKind>*/ List<String> reports, {
String? scriptId,
int? tokenPos,
int? endTokenPos,
@@ -1923,8 +1922,7 @@
@override
Future<SourceReport> getSourceReport(
String isolateId,
- /*List<SourceReportKind>*/
- List<String> reports, {
+ /*List<SourceReportKind>*/ List<String> reports, {
String? scriptId,
int? tokenPos,
int? endTokenPos,
@@ -2196,7 +2194,7 @@
request.completeError(RPCError.parse(request.method, json['error']));
} else {
Map<String, dynamic> result = json['result'] as Map<String, dynamic>;
- String type = result['type'];
+ String? type = result['type'];
if (type == 'Sentinel') {
request.completeError(SentinelException.parse(request.method, result));
} else if (_typeFactories[type] == null) {
@@ -4307,8 +4305,7 @@
List<BoundVariable>? vars;
@optional
- /*FrameKind*/
- String? kind;
+ /*FrameKind*/ String? kind;
Frame({
required this.index,
@@ -5447,18 +5444,19 @@
'id: ${id}, number: ${number}, name: ${name}, isSystemIsolateGroup: ${isSystemIsolateGroup}]';
}
-/// An `Isolate` object provides information about one isolate in the VM.
+/// An `IsolateGroup` object provides information about an isolate group in the
+/// VM.
class IsolateGroup extends Response implements IsolateGroupRef {
static IsolateGroup? parse(Map<String, dynamic>? json) =>
json == null ? null : IsolateGroup._fromJson(json);
- /// The id which is passed to the getIsolate RPC to reload this isolate.
+ /// The id which is passed to the getIsolateGroup RPC to reload this isolate.
String? id;
/// A numeric id for this isolate, represented as a string. Unique.
String? number;
- /// A name identifying this isolate. Not guaranteed to be unique.
+ /// A name identifying this isolate group. Not guaranteed to be unique.
String? name;
/// Specifies whether the isolate group was spawned by the VM or embedder for
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index 9ea0b77..5aad6b6 100644
--- a/pkg/vm_service/pubspec.yaml
+++ b/pkg/vm_service/pubspec.yaml
@@ -3,7 +3,7 @@
A library to communicate with a service implementing the Dart VM
service protocol.
-version: 7.1.0
+version: 7.1.1
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/vm_service
diff --git a/pkg/vm_service/test/library_dependency_test.dart b/pkg/vm_service/test/library_dependency_test.dart
index 5f308ef..5745ca1 100644
--- a/pkg/vm_service/test/library_dependency_test.dart
+++ b/pkg/vm_service/test/library_dependency_test.dart
@@ -8,7 +8,6 @@
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';
-import 'common/service_test_common.dart';
import 'common/test_helper.dart';
export 'dart:io' show Socket hide SecureSocket;
diff --git a/pkg/vm_service/test/regress_46559_test.dart b/pkg/vm_service/test/regress_46559_test.dart
new file mode 100644
index 0000000..84fceae
--- /dev/null
+++ b/pkg/vm_service/test/regress_46559_test.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2021, 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:async';
+import 'dart:convert';
+import 'dart:developer';
+
+import 'package:vm_service/vm_service.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+Future<ServiceExtensionResponse> echo(
+ String method, Map<String, String> args) async {
+ print('In service extension');
+ return ServiceExtensionResponse.result(json.encode(args));
+}
+
+testMain() {
+ registerExtension('ext.foo', echo);
+ debugger();
+}
+
+final tests = <IsolateTest>[
+ hasStoppedAtBreakpoint,
+ resumeIsolate,
+ (VmService vm, IsolateRef isolateRef) async {
+ print('waiting for response');
+ final response = await vm.callServiceExtension(
+ 'ext.foo',
+ isolateId: isolateRef.id!,
+ args: {'foo': 'bar'},
+ );
+ print('got response');
+ print(response.json);
+ },
+];
+
+main([args = const <String>[]]) async => await runIsolateTests(
+ args,
+ tests,
+ 'regress_46559_test.dart',
+ testeeConcurrent: testMain,
+ );
diff --git a/pkg/vm_service/tool/dart/generate_dart.dart b/pkg/vm_service/tool/dart/generate_dart.dart
index 2cf8fd8..844b1ff 100644
--- a/pkg/vm_service/tool/dart/generate_dart.dart
+++ b/pkg/vm_service/tool/dart/generate_dart.dart
@@ -200,7 +200,7 @@
request.completeError(RPCError.parse(request.method, json['error']));
} else {
Map<String, dynamic> result = json['result'] as Map<String, dynamic>;
- String type = result['type'];
+ String? type = result['type'];
if (type == 'Sentinel') {
request.completeError(SentinelException.parse(request.method, result));
} else if (_typeFactories[type] == null) {
@@ -517,7 +517,7 @@
if (json is List) {
return json.map((e) => createServiceObject(e, expectedTypes)).toList();
- } else if (json is Map) {
+ } else if (json is Map<String, dynamic>) {
String? type = json['type'];
// Not a Response type.
@@ -526,7 +526,7 @@
if (expectedTypes.length == 1) {
type = expectedTypes.first;
} else {
- return null;
+ return Response.parse(json);
}
} else if (_isNullInstance(json) && (!expectedTypes.contains('InstanceRef'))) {
// Replace null instances with null when we don't expect an instance to
diff --git a/runtime/bin/dart_io_api_impl.cc b/runtime/bin/dart_io_api_impl.cc
index a890132..8ec2c1d 100644
--- a/runtime/bin/dart_io_api_impl.cc
+++ b/runtime/bin/dart_io_api_impl.cc
@@ -31,6 +31,7 @@
void CleanupDartIo() {
EventHandler::Stop();
+ Process::TerminateExitCodeHandler();
#if !defined(DART_IO_SECURE_SOCKET_DISABLED)
SSLFilter::Cleanup();
#endif
diff --git a/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc b/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
index 885c48f..adcdc07 100644
--- a/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
+++ b/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
@@ -1098,6 +1098,9 @@
if (strcmp(name, "ReturnIntPtr") == 0) {
return reinterpret_cast<void*>(ReturnIntPtr);
}
+ if (strcmp(name, "IsThreadInGenerated") == 0) {
+ return reinterpret_cast<void*>(IsThreadInGenerated);
+ }
// This should be unreachable in tests.
ENSURE(false);
}
diff --git a/runtime/bin/platform.cc b/runtime/bin/platform.cc
index 1b04cfc..3f9ff26 100644
--- a/runtime/bin/platform.cc
+++ b/runtime/bin/platform.cc
@@ -12,6 +12,8 @@
namespace dart {
namespace bin {
+AcqRelAtomic<const char*> Platform::resolved_executable_name_ = nullptr;
+
void FUNCTION_NAME(Platform_NumberOfProcessors)(Dart_NativeArguments args) {
Dart_SetReturnValue(args, Dart_NewInteger(Platform::NumberOfProcessors()));
}
diff --git a/runtime/bin/platform.h b/runtime/bin/platform.h
index bf2d6b1..a34db67 100644
--- a/runtime/bin/platform.h
+++ b/runtime/bin/platform.h
@@ -6,6 +6,8 @@
#define RUNTIME_BIN_PLATFORM_H_
#include "bin/builtin.h"
+
+#include "platform/atomic.h"
#include "platform/globals.h"
#include "platform/utils.h"
@@ -83,14 +85,19 @@
}
static const char* GetExecutableName();
static const char* GetResolvedExecutableName() {
- if (resolved_executable_name_ == NULL) {
+ if (resolved_executable_name_.load() == nullptr) {
// Try to resolve the executable path using platform specific APIs.
const char* resolved_name = Platform::ResolveExecutablePath();
- if (resolved_name != NULL) {
- resolved_executable_name_ = Utils::StrDup(resolved_name);
+ if (resolved_name != nullptr) {
+ char* resolved_name_copy = Utils::StrDup(resolved_name);
+ const char* expect_old_is_null = nullptr;
+ if (!resolved_executable_name_.compare_exchange_strong(
+ expect_old_is_null, resolved_name_copy)) {
+ free(resolved_name_copy);
+ }
}
}
- return resolved_executable_name_;
+ return resolved_executable_name_.load();
}
// Stores and gets the flags passed to the executable.
@@ -108,8 +115,12 @@
private:
// The path to the executable.
static const char* executable_name_;
+
// The path to the resolved executable.
- static char* resolved_executable_name_;
+ //
+ // We use require-release semantics to ensure initializing stores to the
+ // string are visible when the string becomes visible.
+ static AcqRelAtomic<const char*> resolved_executable_name_;
static int script_index_;
static char** argv_; // VM flags are argv_[1 ... script_index_ - 1]
diff --git a/runtime/bin/platform_android.cc b/runtime/bin/platform_android.cc
index 6e5a34a..a9a5cda 100644
--- a/runtime/bin/platform_android.cc
+++ b/runtime/bin/platform_android.cc
@@ -22,7 +22,6 @@
namespace bin {
const char* Platform::executable_name_ = NULL;
-char* Platform::resolved_executable_name_ = NULL;
int Platform::script_index_ = 1;
char** Platform::argv_ = NULL;
diff --git a/runtime/bin/platform_fuchsia.cc b/runtime/bin/platform_fuchsia.cc
index 5c23480..47c1907 100644
--- a/runtime/bin/platform_fuchsia.cc
+++ b/runtime/bin/platform_fuchsia.cc
@@ -23,7 +23,6 @@
namespace bin {
const char* Platform::executable_name_ = NULL;
-char* Platform::resolved_executable_name_ = NULL;
int Platform::script_index_ = 1;
char** Platform::argv_ = NULL;
diff --git a/runtime/bin/platform_linux.cc b/runtime/bin/platform_linux.cc
index d9443bb..adbfac1 100644
--- a/runtime/bin/platform_linux.cc
+++ b/runtime/bin/platform_linux.cc
@@ -21,7 +21,6 @@
namespace bin {
const char* Platform::executable_name_ = NULL;
-char* Platform::resolved_executable_name_ = NULL;
int Platform::script_index_ = 1;
char** Platform::argv_ = NULL;
diff --git a/runtime/bin/platform_macos.cc b/runtime/bin/platform_macos.cc
index 0479776..8083949 100644
--- a/runtime/bin/platform_macos.cc
+++ b/runtime/bin/platform_macos.cc
@@ -29,7 +29,6 @@
namespace bin {
const char* Platform::executable_name_ = NULL;
-char* Platform::resolved_executable_name_ = NULL;
int Platform::script_index_ = 1;
char** Platform::argv_ = NULL;
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc
index 59e1b74..515a569 100644
--- a/runtime/bin/platform_win.cc
+++ b/runtime/bin/platform_win.cc
@@ -25,7 +25,6 @@
namespace bin {
const char* Platform::executable_name_ = NULL;
-char* Platform::resolved_executable_name_ = NULL;
int Platform::script_index_ = 1;
char** Platform::argv_ = NULL;
diff --git a/runtime/vm/elf.cc b/runtime/vm/elf.cc
index a31f66b..12210a4 100644
--- a/runtime/vm/elf.cc
+++ b/runtime/vm/elf.cc
@@ -893,9 +893,6 @@
class NoteSection : public BitsContainer {
public:
- // While the build ID section does not need to be writable, the first load
- // segment in our ELF files is writable (see Elf::WriteProgramTable). Thus,
- // this ensures we can put it in that segment right after the program table.
NoteSection()
: BitsContainer(elf::SectionHeaderType::SHT_NOTE,
/*allocate=*/true,
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index b0b12d8..a663381 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -10768,7 +10768,9 @@
}
ASSERT(original.IsOriginal());
Field& clone = Field::Handle();
- clone ^= Object::Clone(*this, Heap::kOld);
+ // Using relaxed loading is fine because concurrent fields changes are all
+ // guarded, will be reconciled during optimized code installation.
+ clone ^= Object::Clone(*this, Heap::kOld, /*load_with_relaxed_atomics=*/true);
clone.SetOriginal(original);
clone.InheritKernelOffsetFrom(original);
return clone.ptr();
diff --git a/runtime/vm/object_graph_copy.cc b/runtime/vm/object_graph_copy.cc
index 96e6771..e22b3e6 100644
--- a/runtime/vm/object_graph_copy.cc
+++ b/runtime/vm/object_graph_copy.cc
@@ -182,8 +182,10 @@
if (cid == kExternalTwoByteStringCid) return false;
if (cid == kMintCid) return false;
if (cid == kDoubleCid) return false;
+ if (cid == kBoolCid) return false;
if (cid == kSendPortCid) return false;
if (cid == kCapabilityCid) return false;
+ if (cid == kNullCid) return false;
// These are shared and use identity hash codes. If they are used as a key in
// a map or a value in a set, they will already have the identity hash code
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index 333df32..b11e1a4 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -3666,30 +3666,29 @@
TRACE_RUNTIME_CALL("AllocateHandle returning %p", return_value);
return return_value;
}
+
DEFINE_RAW_LEAF_RUNTIME_ENTRY(
AllocateHandle,
1,
false /* is_float */,
reinterpret_cast<RuntimeFunction>(&DLRT_AllocateHandle));
+#if defined(USING_THREAD_SANITIZER)
+#define TSAN_ACQUIRE reinterpret_cast<RuntimeFunction>(&__tsan_acquire)
+#define TSAN_RELEASE reinterpret_cast<RuntimeFunction>(&__tsan_release)
+#else
+#define TSAN_ACQUIRE nullptr
+#define TSAN_RELEASE nullptr
+#endif
+
DEFINE_RAW_LEAF_RUNTIME_ENTRY(TsanLoadAcquire,
/*argument_count=*/1,
/*is_float=*/false,
-#if defined(USING_THREAD_SANITIZER)
- reinterpret_cast<RuntimeFunction>(&__tsan_acquire)
-#else
- nullptr
-#endif
-);
+ TSAN_ACQUIRE);
DEFINE_RAW_LEAF_RUNTIME_ENTRY(TsanStoreRelease,
/*argument_count=*/1,
/*is_float=*/false,
-#if defined(USING_THREAD_SANITIZER)
- reinterpret_cast<RuntimeFunction>(&__tsan_release)
-#else
- nullptr
-#endif
-);
+ TSAN_RELEASE);
} // namespace dart
diff --git a/tests/ffi/ffi_native_test.dart b/tests/ffi/ffi_native_test.dart
index 6997360..df21804 100644
--- a/tests/ffi/ffi_native_test.dart
+++ b/tests/ffi/ffi_native_test.dart
@@ -4,6 +4,9 @@
//
// SharedObjects=ffi_test_functions
+// NOTE: There is no `test/ffi_2/...` version of this test since annotations
+// with type arguments isn't supported in that version of Dart.
+
import 'dart:ffi';
import 'package:expect/expect.dart';
@@ -22,11 +25,32 @@
@FfiNative<IntPtr Function(IntPtr)>('ReturnIntPtr', isLeaf: true)
external int returnIntPtrLeaf(int x);
+@FfiNative<IntPtr Function()>('IsThreadInGenerated')
+external int isThreadInGenerated();
+
+@FfiNative<IntPtr Function()>('IsThreadInGenerated', isLeaf: true)
+external int isThreadInGeneratedLeaf();
+
+// Error: FFI leaf call must not have Handle return type.
+@FfiNative<Handle Function()>("foo", isLeaf: true) //# 01: compile-time error
+external Object foo(); //# 01: compile-time error
+
+// Error: FFI leaf call must not have Handle argument types.
+@FfiNative<Void Function(Handle)>("bar", isLeaf: true) //# 02: compile-time error
+external void bar(Object); //# 02: compile-time error
+
void main() {
// Register test resolver for top-level functions above.
final root_lib_url = getRootLibraryUrl();
setFfiNativeResolverForTest(root_lib_url);
+ // Test we can call FfiNative functions.
Expect.equals(123, returnIntPtr(123));
Expect.equals(123, returnIntPtrLeaf(123));
+
+ // Test FfiNative leaf calls remain in generated code.
+ // Regular calls should transition generated -> native.
+ Expect.equals(0, isThreadInGenerated());
+ // Leaf calls should remain in generated state.
+ Expect.equals(1, isThreadInGeneratedLeaf());
}
diff --git a/tests/web/regress/46589_test.dart b/tests/web/regress/46589_test.dart
new file mode 100644
index 0000000..c4070d5
--- /dev/null
+++ b/tests/web/regress/46589_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2021, 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:expect/expect.dart';
+
+typedef MyVoid = void;
+
+bool isVoid<X>() {
+ return X == MyVoid;
+}
+
+void main() {
+ Expect.isFalse(isVoid<int>());
+ Expect.isTrue(isVoid<void>());
+}
diff --git a/tests/web_2/regress/46589_test.dart b/tests/web_2/regress/46589_test.dart
new file mode 100644
index 0000000..c4070d5
--- /dev/null
+++ b/tests/web_2/regress/46589_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2021, 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:expect/expect.dart';
+
+typedef MyVoid = void;
+
+bool isVoid<X>() {
+ return X == MyVoid;
+}
+
+void main() {
+ Expect.isFalse(isVoid<int>());
+ Expect.isTrue(isVoid<void>());
+}
diff --git a/tools/VERSION b/tools/VERSION
index a4eae4a..10aac58 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 322
+PRERELEASE 323
PRERELEASE_PATCH 0
\ No newline at end of file