Version 2.13.0-8.0.dev
Merge commit '2e3ac0cf154ab0387fc6b8859480a0a27a67fcb3' into 'dev'
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index bfaf1df..ef388b7 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -213,6 +213,34 @@
return []
+def _CheckPackageConfigUpToDate(input_api, output_api):
+ """Checks that .dart_tool/package_config.json is up to date."""
+ # Run only if DEPS file or package_config.json have been modified.
+ if not any(p == 'DEPS' or p == '.dart_tool/package_config.json' or
+ p.endswith('pubspec.yaml') for p in input_api.LocalPaths()):
+ return []
+ local_root = input_api.change.RepositoryRoot()
+ utils = imp.load_source('utils',
+ os.path.join(local_root, 'tools', 'utils.py'))
+
+ dart = utils.CheckedInSdkExecutable()
+ generate = os.path.join(local_root, 'tools', 'generate_package_config.dart')
+ cmd = [dart, generate, '--check']
+ pipe = subprocess.Popen(cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ shell=utils.IsWindows())
+ output = pipe.communicate()
+ if pipe.returncode != 0:
+ return [
+ output_api.PresubmitError(
+ 'File .dart_tool/package_config.json is out of date.\n'
+ 'Fix these issues with:\n'
+ '%s tools/generate_package_config.dart' % (dart))
+ ]
+ return []
+
+
def _CheckValidHostsInDEPS(input_api, output_api):
"""Checks that DEPS file deps are from allowed_hosts."""
# Run only if DEPS file has been modified to annoy fewer bystanders.
@@ -333,6 +361,7 @@
results.extend(_CheckLayering(input_api, output_api))
results.extend(_CheckClangTidy(input_api, output_api))
results.extend(_CheckTestMatrixValid(input_api, output_api))
+ results.extend(_CheckPackageConfigUpToDate(input_api, output_api))
results.extend(
input_api.canned_checks.CheckPatchFormatted(input_api, output_api))
return results
diff --git a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
index 327b003..ba9b171 100644
--- a/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/flow_analysis/flow_analysis.dart
@@ -1716,7 +1716,7 @@
info.discardPromotionsAndMarkNotUnassigned();
if (!identical(info, newInfo)) {
(newVariableInfo ??=
- new Map<Variable?, VariableModel<Variable, Type>>.from(
+ new Map<Variable?, VariableModel<Variable, Type>>.of(
variableInfo))[variable] = newInfo;
}
}
@@ -1725,7 +1725,7 @@
VariableModel<Variable, Type>? info = variableInfo[variable];
if (info == null) {
(newVariableInfo ??=
- new Map<Variable, VariableModel<Variable, Type>>.from(
+ new Map<Variable?, VariableModel<Variable, Type>>.of(
variableInfo))[variable] = new VariableModel<Variable, Type>(
promotedTypes: null,
tested: const [],
@@ -1734,7 +1734,7 @@
ssaNode: null);
} else if (!info.writeCaptured) {
(newVariableInfo ??=
- new Map<Variable, VariableModel<Variable, Type>>.from(
+ new Map<Variable?, VariableModel<Variable, Type>>.of(
variableInfo))[variable] = info.writeCapture();
}
}
@@ -2194,7 +2194,7 @@
{Reachability? reachable}) {
reachable ??= this.reachable;
Map<Variable?, VariableModel<Variable, Type>> newVariableInfo =
- new Map<Variable?, VariableModel<Variable, Type>>.from(variableInfo);
+ new Map<Variable?, VariableModel<Variable, Type>>.of(variableInfo);
reference.storeInfo(newVariableInfo, model);
return new FlowModel<Variable, Type>.withInfo(reachable, newVariableInfo);
}
@@ -3274,7 +3274,7 @@
Type newType,
TypeOperations<Variable, Type> typeOperations) {
if (_typeListContains(typeOperations, types, newType)) return types;
- return new List<Type>.from(types)..add(newType);
+ return new List<Type>.of(types)..add(newType);
}
/// Creates a new [VariableModel] object, unless it is equivalent to either
@@ -4732,7 +4732,7 @@
_assignedVariables._anywhere._written.contains(entry.key)) {
continue;
}
- (newKnownTypes ??= new Map<Variable, Type>.from(_knownTypes))[entry.key] =
+ (newKnownTypes ??= new Map<Variable, Type>.of(_knownTypes))[entry.key] =
entry.value;
}
if (newKnownTypes != null) _knownTypes = newKnownTypes;
@@ -4877,8 +4877,8 @@
_assignedVariables._anywhere._written.contains(entry.key)) {
continue;
}
- (newKnownTypes ??=
- new Map<Variable, Type>.from(_knownTypes))[entry.key] = entry.value;
+ (newKnownTypes ??= new Map<Variable, Type>.of(_knownTypes))[entry.key] =
+ entry.value;
}
if (newKnownTypes != null) _knownTypes = newKnownTypes;
}
@@ -5012,7 +5012,7 @@
VariableModel<Variable, Type> variableModel) {
VariableModel<Variable, Type> targetInfo = target.getInfo(variableInfo);
Map<String, VariableModel<Variable, Type>> newProperties =
- new Map<String, VariableModel<Variable, Type>>.from(
+ new Map<String, VariableModel<Variable, Type>>.of(
targetInfo.properties);
newProperties[propertyName] = variableModel;
target.storeInfo(variableInfo, targetInfo.setProperties(newProperties));
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
index f205135..ecac3e6 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
@@ -517,7 +517,7 @@
if (offset <= argument.offset) {
return typeOfIndexPositionalParameter();
}
- if (argument.contains(offset)) {
+ if (argument.contains(offset) && offset >= argument.name.end) {
return argument.staticParameterElement?.type;
}
return null;
diff --git a/pkg/analysis_server/test/src/services/completion/dart/feature_computer_test.dart b/pkg/analysis_server/test/src/services/completion/dart/feature_computer_test.dart
index 03c9c87..d6746b3 100644
--- a/pkg/analysis_server/test/src/services/completion/dart/feature_computer_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/dart/feature_computer_test.dart
@@ -3,7 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/services/completion/dart/feature_computer.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -11,29 +11,18 @@
void main() {
defineReflectiveSuite(() {
- defineReflectiveTests(FeatureComputerTest);
+ defineReflectiveTests(ContextTypeTest);
});
}
@reflectiveTest
-class FeatureComputerTest extends AbstractSingleUnitTest {
- @override
- bool verifyNoTestUnitErrors = false;
-
+class ContextTypeTest extends FeatureComputerTest {
Future<void> assertContextType(String content, String expectedType) async {
- var index = content.indexOf('^');
- if (index < 0) {
- fail('Missing node offset marker (^) in content');
- }
- content = content.substring(0, index) + content.substring(index + 1);
- await resolveTestCode(content);
- // TODO(jwren) Consider changing this from the NodeLocator to the optype
- // node finding logic to be more consistent with what the user behavior
- // here will be.
- var node = NodeLocator(index).searchWithin(testUnit);
+ await completeIn(content);
var computer = FeatureComputer(
testAnalysisResult.typeSystem, testAnalysisResult.typeProvider);
- var type = computer.computeContextType(node, index);
+ var type = computer.computeContextType(
+ completionTarget.containingNode, cursorIndex);
if (expectedType == null) {
expect(type, null);
@@ -687,3 +676,23 @@
''', null);
}
}
+
+abstract class FeatureComputerTest extends AbstractSingleUnitTest {
+ int cursorIndex = 0;
+
+ CompletionTarget completionTarget;
+
+ @override
+ bool verifyNoTestUnitErrors = false;
+
+ Future<void> completeIn(String content) async {
+ cursorIndex = content.indexOf('^');
+ if (cursorIndex < 0) {
+ fail('Missing node offset marker (^) in content');
+ }
+ content =
+ content.substring(0, cursorIndex) + content.substring(cursorIndex + 1);
+ await resolveTestCode(content);
+ completionTarget = CompletionTarget.forOffset(testUnit, cursorIndex);
+ }
+}
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 80c8339..4219495 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -4684,7 +4684,7 @@
/// rawStringLiteral ::=
/// 'r' basicStringLiteral
///
-/// simpleStringLiteral ::=
+/// basicStringLiteral ::=
/// multiLineStringLiteral
/// | singleLineStringLiteral
///
diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart
index b79502d..3fa2aa1 100644
--- a/pkg/analyzer/lib/src/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_system.dart
@@ -1795,8 +1795,6 @@
var numTypeQuestion = typeProvider.numTypeQuestion;
if (isSubtypeOf(t1, numTypeQuestion) && !t2.isBottom && !t3.isBottom) {
assert(!t1.isBottom);
- assert(isSubtypeOf(t2, numTypeQuestion));
- assert(isSubtypeOf(t3, numTypeQuestion));
// Then:
// - If T1, T2 and T3 are all subtypes of int, the static type of e is
// int.
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index 9f75b54..1c32c5c 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -35,7 +35,6 @@
import 'package:analyzer/src/workspace/workspace.dart';
import 'package:meta/meta.dart';
import 'package:meta/meta_meta.dart';
-import 'package:path/path.dart' as path;
/// Instances of the class `BestPracticesVerifier` traverse an AST structure
/// looking for violations of Dart best practices.
@@ -128,6 +127,7 @@
analysisOptions,
_workspacePackage,
);
+ _invalidAccessVerifier._inTestDirectory = _linterContext.inTestDir(unit);
}
bool get _inPublicPackageApi {
@@ -1684,12 +1684,6 @@
class _InvalidAccessVerifier {
static final _templateExtension = '.template';
- static final _testDirectories = [
- '${path.separator}test${path.separator}',
- '${path.separator}integration_test${path.separator}',
- '${path.separator}test_driver${path.separator}',
- '${path.separator}testing${path.separator}',
- ];
final ErrorReporter _errorReporter;
final LibraryElement _library;
@@ -1704,7 +1698,6 @@
this._errorReporter, this._library, this._workspacePackage) {
var path = _library.source.fullName;
_inTemplateSource = path.contains(_templateExtension);
- _inTestDirectory = _testDirectories.any(path.contains);
}
/// Produces a hint if [identifier] is accessed from an invalid location.
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart
index 59a0a74..fd04724 100644
--- a/pkg/analyzer/lib/src/lint/linter.dart
+++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -269,6 +269,9 @@
/// Return the result of evaluating the given expression.
LinterConstantEvaluationResult evaluateConstant(Expression node);
+ /// Return `true` if the given [unit] is in a test directory.
+ bool inTestDir(CompilationUnit unit);
+
/// Return `true` if the [feature] is enabled in the library being linted.
bool isEnabled(Feature feature);
@@ -281,6 +284,13 @@
/// Implementation of [LinterContext]
class LinterContextImpl implements LinterContext {
+ static final _testDirectories = [
+ '${p.separator}test${p.separator}',
+ '${p.separator}integration_test${p.separator}',
+ '${p.separator}test_driver${p.separator}',
+ '${p.separator}testing${p.separator}',
+ ];
+
@override
final List<LinterContextUnit> allUnits;
@@ -369,6 +379,12 @@
}
@override
+ bool inTestDir(CompilationUnit unit) {
+ var path = unit.declaredElement?.source.fullName;
+ return path != null && _testDirectories.any(path.contains);
+ }
+
+ @override
bool isEnabled(Feature feature) {
var unitElement = currentUnit.unit.declaredElement!;
return unitElement.library.featureSet.isEnabled(feature);
diff --git a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
index 9393416..e493bde8 100644
--- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
@@ -189,6 +189,21 @@
expectedType: 'num');
}
+ test_clamp_int_double_dynamic() async {
+ await assertNoErrorsInCode('''
+f(int a, double b, dynamic c) {
+ a.clamp(b, c);
+}
+''');
+
+ assertMethodInvocation(
+ findNode.methodInvocation('clamp'),
+ elementMatcher(numElement.getMethod('clamp'),
+ isLegacy: isNullSafetySdkAndLegacyLibrary),
+ 'num Function(num, num)',
+ expectedType: 'num');
+ }
+
test_clamp_int_double_int() async {
await assertNoErrorsInCode('''
f(int a, double b, int c) {
@@ -204,6 +219,36 @@
expectedType: 'num');
}
+ test_clamp_int_dynamic_double() async {
+ await assertNoErrorsInCode('''
+f(int a, dynamic b, double c) {
+ a.clamp(b, c);
+}
+''');
+
+ assertMethodInvocation(
+ findNode.methodInvocation('clamp'),
+ elementMatcher(numElement.getMethod('clamp'),
+ isLegacy: isNullSafetySdkAndLegacyLibrary),
+ 'num Function(num, num)',
+ expectedType: 'num');
+ }
+
+ test_clamp_int_dynamic_int() async {
+ await assertNoErrorsInCode('''
+f(int a, dynamic b, int c) {
+ a.clamp(b, c);
+}
+''');
+
+ assertMethodInvocation(
+ findNode.methodInvocation('clamp'),
+ elementMatcher(numElement.getMethod('clamp'),
+ isLegacy: isNullSafetySdkAndLegacyLibrary),
+ 'num Function(num, num)',
+ expectedType: 'num');
+ }
+
test_clamp_int_int_double() async {
await assertNoErrorsInCode('''
f(int a, int b, double c) {
@@ -219,6 +264,21 @@
expectedType: 'num');
}
+ test_clamp_int_int_dynamic() async {
+ await assertNoErrorsInCode('''
+f(int a, int b, dynamic c) {
+ a.clamp(b, c);
+}
+''');
+
+ assertMethodInvocation(
+ findNode.methodInvocation('clamp'),
+ elementMatcher(numElement.getMethod('clamp'),
+ isLegacy: isNullSafetySdkAndLegacyLibrary),
+ 'num Function(num, num)',
+ expectedType: 'num');
+ }
+
test_clamp_int_int_int() async {
await assertNoErrorsInCode('''
f(int a, int b, int c) {
diff --git a/pkg/compiler/lib/src/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index b1d2000..d4a9558 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -234,9 +234,22 @@
passThrough(argument);
}
- void addInEnvironment(String argument) {
+ void addInEnvironment(Iterator<String> arguments) {
+ final isDefine = arguments.current.startsWith('--define');
+ String argument;
+ if (arguments.current == '--define') {
+ arguments.moveNext();
+ argument = arguments.current;
+ } else {
+ argument = arguments.current.substring(isDefine ? '--define='.length : 2);
+ }
+ // Allow for ' ' or '=' after --define
int eqIndex = argument.indexOf('=');
- String name = argument.substring(2, eqIndex);
+ if (eqIndex <= 0) {
+ helpAndFail('Invalid value for --define: $argument');
+ return;
+ }
+ String name = argument.substring(0, eqIndex);
String value = argument.substring(eqIndex + 1);
environment[name] = value;
}
@@ -564,7 +577,8 @@
new OptionHandler('${Flags.mergeFragmentsThreshold}=.+', passThrough),
// The following three options must come last.
- new OptionHandler('-D.+=.*', addInEnvironment),
+ new OptionHandler('-D.+=.*|--define=.+=.*|--define', addInEnvironment,
+ multipleArguments: true),
new OptionHandler('-.*', (String argument) {
helpAndFail("Unknown option '$argument'.");
}),
@@ -1030,7 +1044,7 @@
-v, --verbose
Display verbose information.
- -D<name>=<value>
+ -D<name>=<value>, --define=<name>=<value>
Define an environment declaration.
--version
diff --git a/pkg/dartdev/lib/src/commands/compile.dart b/pkg/dartdev/lib/src/commands/compile.dart
index affa10d..2e6da52 100644
--- a/pkg/dartdev/lib/src/commands/compile.dart
+++ b/pkg/dartdev/lib/src/commands/compile.dart
@@ -88,7 +88,11 @@
help: 'Generate minified output.',
abbr: 'm',
negatable: false,
- );
+ )
+ ..addMultiOption('define', abbr: 'D', valueHelp: 'key=value', help: '''
+Define an environment declaration. To specify multiple declarations, use multiple options or use commas to separate key-value pairs.
+For example: dart compile $cmdName -Da=1,b=2 main.dart''');
+
addExperimentalFlags(argParser, verbose);
}
@@ -120,6 +124,24 @@
if (!checkFile(sourcePath)) {
return 1;
}
+ final args = <String>[
+ '--libraries-spec=$librariesPath',
+ if (argResults.enabledExperiments.isNotEmpty)
+ "--enable-experiment=${argResults.enabledExperiments.join(',')}",
+ if (argResults.wasParsed(commonOptions['outputFile'].flag))
+ "-o${argResults[commonOptions['outputFile'].flag]}",
+ if (argResults.wasParsed('minified')) '-m',
+ ];
+
+ if (argResults.wasParsed('define')) {
+ for (final define in argResults['define']) {
+ args.add('-D$define');
+ }
+ }
+
+ // Add any args that weren't parsed to the end. This will likely only ever
+ // be the script name.
+ args.addAll(argResults.rest);
VmInteropHandler.run(
sdk.dart2jsSnapshot,
diff --git a/pkg/dartdev/lib/src/commands/run.dart b/pkg/dartdev/lib/src/commands/run.dart
index 2825b49..45bfd1e 100644
--- a/pkg/dartdev/lib/src/commands/run.dart
+++ b/pkg/dartdev/lib/src/commands/run.dart
@@ -109,8 +109,12 @@
);
}
argParser
- ..addMultiOption('define',
- abbr: 'D', help: 'Defines an environment variable', hide: true)
+ ..addMultiOption(
+ 'define',
+ abbr: 'D',
+ valueHelp: 'key=value',
+ help: 'Define an environment declaration.',
+ )
..addFlag(
'disable-service-auth-codes',
hide: !verbose,
diff --git a/pkg/dartdev/test/commands/compile_test.dart b/pkg/dartdev/test/commands/compile_test.dart
index 458fb39..17cc1a8 100644
--- a/pkg/dartdev/test/commands/compile_test.dart
+++ b/pkg/dartdev/test/commands/compile_test.dart
@@ -187,7 +187,11 @@
});
test('Compile JS', () {
- final p = project(mainSrc: "void main() { print('Hello from JS'); }");
+ final p = project(mainSrc: '''
+ void main() {
+ print('1: ' + const String.fromEnvironment('foo'));
+ print('2: ' + const String.fromEnvironment('bar'));
+ }''');
final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
final outFile = path.canonicalize(path.join(p.dirPath, 'main.js'));
@@ -195,6 +199,8 @@
'compile',
'js',
'-m',
+ '-Dfoo=bar',
+ '--define=bar=foo',
'-o',
outFile,
'-v',
@@ -202,8 +208,14 @@
]);
expect(result.stderr, isEmpty);
expect(result.exitCode, 0);
- expect(File(outFile).existsSync(), true,
- reason: 'File not found: $outFile');
+ final file = File(outFile);
+ expect(file.existsSync(), true, reason: 'File not found: $outFile');
+
+ // Ensure the -D and --define arguments were processed correctly.
+ final contents = file.readAsStringSync();
+ print(contents);
+ expect(contents.contains('1: bar'), true);
+ expect(contents.contains('2: foo'), true);
});
test('Compile exe with error', () {
diff --git a/pkg/dartdev/test/commands/run_test.dart b/pkg/dartdev/test/commands/run_test.dart
index 12c07d3..b8cc5e8 100644
--- a/pkg/dartdev/test/commands/run_test.dart
+++ b/pkg/dartdev/test/commands/run_test.dart
@@ -181,6 +181,7 @@
'--no-pause-isolates-on-exit',
'--no-pause-isolates-on-unhandled-exceptions',
'-Dfoo=bar',
+ '--define=bar=foo',
p.relativeFilePath,
]);
expect(
@@ -202,6 +203,7 @@
'--no-pause-isolates-on-unhandled-exceptions',
'--disable-service-auth-codes',
'-Dfoo=bar',
+ '--define=bar=foo',
p.relativeFilePath,
]);
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index 8085f69..550c6e1 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -730,8 +730,19 @@
var declaredVariables = <String, String>{};
for (var i = 0; i < args.length;) {
var arg = args[i];
+ String rest;
+ const defineFlag = '--define';
if (arg.startsWith('-D') && arg.length > 2) {
- var rest = arg.substring(2);
+ rest = arg.substring(2);
+ } else if (arg.startsWith('$defineFlag=') &&
+ arg.length > defineFlag.length + 1) {
+ rest = arg.substring(defineFlag.length + 1);
+ } else if (arg == defineFlag) {
+ i++;
+ rest = args[i];
+ }
+
+ if (rest != null) {
var eq = rest.indexOf('=');
if (eq <= 0) {
var kind = eq == 0 ? 'name' : 'value';
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index bfa8f4b..433c88a 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -203,6 +203,7 @@
Flags.noDeps: const BoolValue(false),
Flags.invocationModes: const StringValue(),
"-D": const DefineValue(),
+ "--define": const AliasValue("-D"),
"-h": const AliasValue(Flags.help),
"--out": const AliasValue(Flags.output),
"-o": const AliasValue(Flags.output),
diff --git a/pkg/test_runner/lib/src/compiler_configuration.dart b/pkg/test_runner/lib/src/compiler_configuration.dart
index 0ec7acd..9ef37d0 100644
--- a/pkg/test_runner/lib/src/compiler_configuration.dart
+++ b/pkg/test_runner/lib/src/compiler_configuration.dart
@@ -1197,6 +1197,7 @@
arguments.where((name) => name.endsWith('.dart')).single,
...arguments.where((name) =>
name.startsWith('-D') ||
+ name.startsWith('--define') ||
name.startsWith('--packages=') ||
name.startsWith('--enable-experiment=')),
'-Ddart.vm.product=$isProductMode',
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index 517029d..1bc116d 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -147,6 +147,9 @@
" all VM options).\n"
"--packages=<path>\n"
" Where to find a package spec file.\n"
+"--define=<key>=<value> or -D<key>=<value>\n"
+" Define an environment declaration. To specify multiple declarations,\n"
+" use multiple instances of this option.\n"
"--observe[=<port>[/<bind-address>]]\n"
" The observe flag is a convenience flag used to run a program with a\n"
" set of options which are often useful for debugging under Observatory.\n"
@@ -180,6 +183,9 @@
" all VM options).\n"
"--packages=<path>\n"
" Where to find a package spec file.\n"
+"--define=<key>=<value> or -D<key>=<value>\n"
+" Define an environment declaration. To specify multiple declarations,\n"
+" use multiple instances of this option.\n"
"--observe[=<port>[/<bind-address>]]\n"
" The observe flag is a convenience flag used to run a program with a\n"
" set of options which are often useful for debugging under Observatory.\n"
@@ -546,7 +552,8 @@
while (tmp_i < argc) {
// Check if this flag is a potentially valid VM flag. If not, we've likely
// hit a script name and are done parsing VM flags.
- if (!OptionProcessor::IsValidFlag(argv[tmp_i])) {
+ if (!OptionProcessor::IsValidFlag(argv[tmp_i]) &&
+ !OptionProcessor::IsValidShortFlag(argv[tmp_i])) {
break;
}
OptionProcessor::TryProcess(argv[tmp_i], vm_options);
diff --git a/runtime/bin/options.cc b/runtime/bin/options.cc
index 7ad5d20..d32ca5f 100644
--- a/runtime/bin/options.cc
+++ b/runtime/bin/options.cc
@@ -41,22 +41,35 @@
return false;
}
+static bool IsPrefix(const char* prefix, size_t prefix_len, const char* str) {
+ ASSERT(prefix != nullptr);
+ ASSERT(str != nullptr);
+ const size_t str_len = strlen(str);
+ if (str_len < prefix_len) {
+ return false;
+ }
+ return strncmp(prefix, str, prefix_len) == 0;
+}
+
bool OptionProcessor::ProcessEnvironmentOption(
const char* arg,
CommandLineOptions* vm_options,
dart::SimpleHashMap** environment) {
ASSERT(arg != NULL);
ASSERT(environment != NULL);
- if (*arg == '\0') {
+ const char* kShortPrefix = "-D";
+ const char* kLongPrefix = "--define=";
+ const int kShortPrefixLen = strlen(kShortPrefix);
+ const int kLongPrefixLen = strlen(kLongPrefix);
+ const bool is_short_form = IsPrefix(kShortPrefix, kShortPrefixLen, arg);
+ const bool is_long_form = IsPrefix(kLongPrefix, kLongPrefixLen, arg);
+ if (is_short_form) {
+ arg = arg + kShortPrefixLen;
+ } else if (is_long_form) {
+ arg = arg + kLongPrefixLen;
+ } else {
return false;
}
- if (*arg != '-') {
- return false;
- }
- if (*(arg + 1) != 'D') {
- return false;
- }
- arg = arg + 2;
if (*arg == '\0') {
return true;
}
@@ -69,12 +82,20 @@
const char* equals_pos = strchr(arg, '=');
if (equals_pos == NULL) {
// No equal sign (name without value) currently not supported.
- Syslog::PrintErr("No value given to -D option\n");
+ if (is_short_form) {
+ Syslog::PrintErr("No value given to -D option\n");
+ } else {
+ Syslog::PrintErr("No value given to --define option\n");
+ }
return true;
}
int name_len = equals_pos - arg;
if (name_len == 0) {
- Syslog::PrintErr("No name given to -D option\n");
+ if (is_short_form) {
+ Syslog::PrintErr("No name given to -D option\n");
+ } else {
+ Syslog::PrintErr("No name given to --define option\n");
+ }
return true;
}
// Split name=value into name and value.
diff --git a/tests/corelib/string_from_environment_test.dart b/tests/corelib/string_from_environment_test.dart
index 2134e44..974e89e 100644
--- a/tests/corelib/string_from_environment_test.dart
+++ b/tests/corelib/string_from_environment_test.dart
@@ -1,7 +1,7 @@
// Copyright (c) 2013, 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.
-// SharedOptions=-Da=a -Db=bb -Dc=ccc -Dd=
+// SharedOptions=-Da=a -Db=bb -Dc=ccc -Dd= --define=e=eeee
import "package:expect/expect.dart";
@@ -10,4 +10,5 @@
Expect.equals('bb', const String.fromEnvironment('b'));
Expect.equals('ccc', const String.fromEnvironment('c'));
Expect.equals('', const String.fromEnvironment('d'));
+ Expect.equals('eeee', const String.fromEnvironment('e'));
}
diff --git a/tests/corelib_2/string_from_environment_test.dart b/tests/corelib_2/string_from_environment_test.dart
index 2134e44..974e89e 100644
--- a/tests/corelib_2/string_from_environment_test.dart
+++ b/tests/corelib_2/string_from_environment_test.dart
@@ -1,7 +1,7 @@
// Copyright (c) 2013, 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.
-// SharedOptions=-Da=a -Db=bb -Dc=ccc -Dd=
+// SharedOptions=-Da=a -Db=bb -Dc=ccc -Dd= --define=e=eeee
import "package:expect/expect.dart";
@@ -10,4 +10,5 @@
Expect.equals('bb', const String.fromEnvironment('b'));
Expect.equals('ccc', const String.fromEnvironment('c'));
Expect.equals('', const String.fromEnvironment('d'));
+ Expect.equals('eeee', const String.fromEnvironment('e'));
}
diff --git a/tools/VERSION b/tools/VERSION
index 5f9771b..7ebd6a0 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 13
PATCH 0
-PRERELEASE 7
+PRERELEASE 8
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/generate_package_config.dart b/tools/generate_package_config.dart
index 516dcf7..f5868ff 100644
--- a/tools/generate_package_config.dart
+++ b/tools/generate_package_config.dart
@@ -7,14 +7,43 @@
import 'dart:convert';
import 'dart:io';
+import 'package:args/args.dart';
import 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';
import 'package:yaml/yaml.dart';
+bool _parseOptions(List<String> args) {
+ const usage = "Usage: dart generate_package_config.dart [flags...]";
+
+ var parser = ArgParser();
+
+ parser.addFlag("help", abbr: "h");
+
+ parser.addFlag("check",
+ abbr: "c",
+ help: "Return with a non-zero exit code if not up-to-date",
+ negatable: false);
+
+ var results = parser.parse(args);
+
+ if (results["help"] as bool) {
+ print("Regenerate the .dart_tool/package_config.json file.");
+ print("");
+ print(usage);
+ print("");
+ print(parser.usage);
+ exit(0);
+ }
+
+ return results["check"] as bool;
+}
+
final repoRoot = p.dirname(p.dirname(p.fromUri(Platform.script)));
final configFilePath = p.join(repoRoot, '.dart_tool/package_config.json');
void main(List<String> args) {
+ bool checkOnly = _parseOptions(args);
+
var packageDirs = [
...listSubdirectories('pkg'),
...listSubdirectories('third_party/pkg'),
@@ -60,6 +89,24 @@
];
packages.sort((a, b) => a["name"].compareTo(b["name"]));
+ var configFile = File(p.join(repoRoot, '.dart_tool', 'package_config.json'));
+
+ // Validate the packages entry only, to avoid spurious failures from changes
+ // in the dates embedded in the other entries.
+ if (checkOnly) {
+ var json =
+ jsonDecode(configFile.readAsStringSync()) as Map<dynamic, dynamic>;
+ var oldPackages = json['packages'] as List<dynamic>;
+ if (jsonEncode(packages) == jsonEncode(oldPackages)) {
+ print("Package config up to date");
+ exit(0);
+ } else {
+ print("Package config out of date");
+ print("Run `dart tools/generate_package_config.dart` to update");
+ exit(1);
+ }
+ }
+
var year = DateTime.now().year;
var config = <String, dynamic>{
'copyright': [
@@ -81,8 +128,7 @@
// TODO(rnystrom): Consider using package_config_v2 to generate this instead.
var json = JsonEncoder.withIndent(' ').convert(config);
- File(p.join(repoRoot, '.dart_tool', 'package_config.json'))
- .writeAsStringSync(json);
+ configFile.writeAsStringSync(json);
print('Generated .dart_tool/package_config.dart containing '
'${packages.length} packages.');
}