Version 2.11.0-273.0.dev
Merge commit '2fafb4061fefdd466bcdbef00e071a079e7f92d0' into 'dev'
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 30ed3d0..0ef80e5 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -16,6 +16,7 @@
import 'package:analyzer/src/generated/parser.dart' show ParserErrorCode;
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/manifest/manifest_warning_code.dart';
+import 'package:analyzer/src/pubspec/pubspec_warning_code.dart';
export 'package:_fe_analyzer_shared/src/base/errors.dart'
show ErrorCode, ErrorSeverity, ErrorType;
@@ -795,6 +796,9 @@
ParserErrorCode.WITH_BEFORE_EXTENDS,
ParserErrorCode.WRONG_SEPARATOR_FOR_POSITIONAL_PARAMETER,
ParserErrorCode.WRONG_TERMINATOR_FOR_PARAMETER_GROUP,
+ PubspecWarningCode.INVALID_DEPENDENCY,
+ PubspecWarningCode.PATH_DOES_NOT_EXIST,
+ PubspecWarningCode.PATH_PUBSPEC_DOES_NOT_EXIST,
ScannerErrorCode.EXPECTED_TOKEN,
ScannerErrorCode.ILLEGAL_CHARACTER,
ScannerErrorCode.MISSING_DIGIT,
diff --git a/pkg/analyzer/lib/src/dart/micro/libraries_log.dart b/pkg/analyzer/lib/src/dart/micro/libraries_log.dart
deleted file mode 100644
index a67988b..0000000
--- a/pkg/analyzer/lib/src/dart/micro/libraries_log.dart
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (c) 2020, 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:meta/meta.dart';
-
-class ChangeFileLoadEntry extends LibrariesLogEntry {
- /// The path of the file that was reported as changed.
- final String target;
-
- /// The files that depend transitively on the [target]. These files are
- /// removed from the state, and from the element factory.
- final List<LibrariesLogFile> removed = [];
-
- ChangeFileLoadEntry._(this.target);
-
- void addRemoved({
- @required String path,
- @required Uri uri,
- }) {
- removed.add(
- LibrariesLogFile._(path, uri),
- );
- }
-
- @override
- String toString() {
- return 'Change(target: $target, removed: $removed)';
- }
-}
-
-class LibrariesLog {
- final List<LibrariesLogEntry> entries = [];
-
- ChangeFileLoadEntry changeFile(String path) {
- var entry = ChangeFileLoadEntry._(path);
- entries.add(entry);
- return entry;
- }
-
- LoadLibrariesForTargetLogEntry loadForTarget({
- @required String path,
- @required Uri uri,
- }) {
- var entry = LoadLibrariesForTargetLogEntry._(
- LibrariesLogFile._(path, uri),
- );
- entries.add(entry);
- return entry;
- }
-}
-
-abstract class LibrariesLogEntry {
- final DateTime time = DateTime.now();
-}
-
-class LibrariesLogFile {
- final String path;
- final Uri uri;
-
- LibrariesLogFile._(this.path, this.uri);
-
- @override
- String toString() {
- return '(path: $path, uri: $uri)';
- }
-}
-
-class LoadLibrariesForTargetLogEntry extends LibrariesLogEntry {
- final LibrariesLogFile target;
- final List<LibrariesLogFile> loaded = [];
-
- LoadLibrariesForTargetLogEntry._(this.target);
-
- void addLibrary({
- @required String path,
- @required Uri uri,
- }) {
- loaded.add(
- LibrariesLogFile._(path, uri),
- );
- }
-
- @override
- String toString() {
- return 'Load(target: $target, loaded: $loaded)';
- }
-}
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index b77c5aa..b0e1808 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -20,7 +20,6 @@
import 'package:analyzer/src/dart/analysis/results.dart';
import 'package:analyzer/src/dart/micro/analysis_context.dart';
import 'package:analyzer/src/dart/micro/cider_byte_store.dart';
-import 'package:analyzer/src/dart/micro/libraries_log.dart';
import 'package:analyzer/src/dart/micro/library_analyzer.dart';
import 'package:analyzer/src/dart/micro/library_graph.dart';
import 'package:analyzer/src/exception/exception.dart';
@@ -76,13 +75,11 @@
MicroContextObjects contextObjects;
- final LibrariesLog _librariesLog = LibrariesLog();
-
_LibraryContext libraryContext;
/// List of ids for cache elements that are invalidated. Track elements that
- /// are invalidated during [changeFile]. Used in [releaseAndClearRemovedIds] to
- /// release the cache items and is then cleared.
+ /// are invalidated during [changeFile]. Used in [releaseAndClearRemovedIds]
+ /// to release the cache items and is then cleared.
final Set<int> removedCacheIds = {};
FileResolver(
@@ -124,10 +121,6 @@
this.byteStore = byteStore;
}
- List<LibrariesLogEntry> get librariesLogEntries {
- return _librariesLog.entries;
- }
-
/// Update the resolver to reflect the fact that the file with the given
/// [path] was changed. We need to make sure that when this file, of any file
/// that directly or indirectly referenced it, is resolved, we used the new
@@ -142,13 +135,8 @@
var removedFiles = <FileState>[];
fsState.changeFile(path, removedFiles);
- // Update the log.
- var logEntry = _librariesLog.changeFile(path);
+ // Schedule disposing references to cached unlinked data.
for (var removedFile in removedFiles) {
- logEntry.addRemoved(
- path: removedFile.path,
- uri: removedFile.uri,
- );
removedCacheIds.add(removedFile.id);
}
@@ -474,7 +462,6 @@
resourceProvider,
byteStore,
contextObjects,
- _librariesLog,
);
}
}
@@ -615,7 +602,6 @@
final ResourceProvider resourceProvider;
final CiderByteStore byteStore;
final MicroContextObjects contextObjects;
- final LibrariesLog librariesLog;
LinkedElementFactory elementFactory;
@@ -626,7 +612,6 @@
this.resourceProvider,
this.byteStore,
this.contextObjects,
- this.librariesLog,
) {
elementFactory = LinkedElementFactory(
contextObjects.analysisContext,
@@ -646,21 +631,9 @@
var librariesLinkedTimer = Stopwatch();
var inputsTimer = Stopwatch();
- var logEntry = librariesLog.loadForTarget(
- path: targetLibrary.path,
- uri: targetLibrary.uri,
- );
-
void loadBundle(LibraryCycle cycle) {
if (!loadedBundles.add(cycle)) return;
- for (var library in cycle.libraries) {
- logEntry.addLibrary(
- path: library.path,
- uri: library.uri,
- );
- }
-
performance.getDataInt('cycleCount').increment();
performance.getDataInt('libraryCount').add(cycle.libraries.length);
diff --git a/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart b/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
index 83c2031..af82bcf 100644
--- a/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
+++ b/pkg/analyzer/lib/src/pubspec/pubspec_validator.dart
@@ -8,6 +8,7 @@
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/pubspec/pubspec_warning_code.dart';
+import 'package:analyzer/src/util/yaml.dart';
import 'package:path/path.dart' as path;
import 'package:source_span/src/span.dart';
import 'package:yaml/yaml.dart';
@@ -27,12 +28,21 @@
/// configuration data.
static const String FLUTTER_FIELD = 'flutter';
+ /// The name of the field whose value is a git dependency.
+ static const String GIT_FIELD = 'git';
+
/// The name of the field whose value is the name of the package.
static const String NAME_FIELD = 'name';
/// The name of the field whose value is a path to a package dependency.
static const String PATH_FIELD = 'path';
+ /// The name of the field whose value is the where to publish the package.
+ static const String PUBLISH_TO_FIELD = 'publish_to';
+
+ /// The name of the field whose value is the version of the package.
+ static const String VERSION_FIELD = 'version';
+
/// The resource provider used to access the file system.
final ResourceProvider provider;
@@ -89,6 +99,16 @@
return false;
}
+ String _asString(dynamic node) {
+ if (node is String) {
+ return node;
+ }
+ if (node is YamlScalar && node.value is String) {
+ return node.value as String;
+ }
+ return null;
+ }
+
/// Return a map whose keys are the names of declared dependencies and whose
/// values are the specifications of those dependencies. The map is extracted
/// from the given [contents] using the given [key].
@@ -122,8 +142,17 @@
Map<dynamic, YamlNode> declaredDevDependencies =
_getDeclaredDependencies(reporter, contents, DEV_DEPENDENCIES_FIELD);
+ bool isPublishablePackage = false;
+ var version = contents[VERSION_FIELD];
+ if (version != null) {
+ var publishTo = _asString(contents[PUBLISH_TO_FIELD]);
+ if (publishTo != 'none') {
+ isPublishablePackage = true;
+ }
+ }
+
for (var dependency in declaredDependencies.entries) {
- _validatePathEntries(reporter, dependency.value);
+ _validatePathEntries(reporter, dependency.value, isPublishablePackage);
}
for (var dependency in declaredDevDependencies.entries) {
@@ -132,7 +161,7 @@
_reportErrorForNode(reporter, packageName,
PubspecWarningCode.UNNECESSARY_DEV_DEPENDENCY, [packageName.value]);
}
- _validatePathEntries(reporter, dependency.value);
+ _validatePathEntries(reporter, dependency.value, false);
}
}
@@ -209,33 +238,44 @@
/// Valid paths are directories that:
///
/// 1. exist,
- /// 2. contain a pubspec.yaml file, and
- /// 3. `lib` dir
- void _validatePathEntries(ErrorReporter reporter, YamlNode dependency) {
+ /// 2. contain a pubspec.yaml file
+ ///
+ /// If [checkForPathAndGitDeps] is true, `git` or `path` dependencies will
+ /// be marked invalid.
+ void _validatePathEntries(ErrorReporter reporter, YamlNode dependency,
+ bool checkForPathAndGitDeps) {
if (dependency is YamlMap) {
- for (var node in dependency.nodes.entries) {
- var pathEntry = dependency[PATH_FIELD];
- if (pathEntry != null) {
- var context = provider.pathContext;
- var normalizedPath = context.joinAll(path.posix.split(pathEntry));
- var packageRoot = context.dirname(source.fullName);
- var dependencyPath = context.join(packageRoot, normalizedPath);
- dependencyPath = context.absolute(dependencyPath);
- dependencyPath = context.normalize(dependencyPath);
- var packageFolder = provider.getFolder(dependencyPath);
- if (!packageFolder.exists) {
- _reportErrorForNode(reporter, node.value,
- PubspecWarningCode.PATH_DOES_NOT_EXIST, [pathEntry]);
- } else {
- if (!packageFolder
- .getChild(AnalysisEngine.PUBSPEC_YAML_FILE)
- .exists) {
- _reportErrorForNode(reporter, node.value,
- PubspecWarningCode.PATH_PUBSPEC_DOES_NOT_EXIST, [pathEntry]);
- }
- // todo (pq): test for presence of a lib dir.
+ var pathEntry = _asString(dependency[PATH_FIELD]);
+ if (pathEntry != null) {
+ YamlNode pathKey() => getKey(dependency, PATH_FIELD);
+ var context = provider.pathContext;
+ var normalizedPath = context.joinAll(path.posix.split(pathEntry));
+ var packageRoot = context.dirname(source.fullName);
+ var dependencyPath = context.join(packageRoot, normalizedPath);
+ dependencyPath = context.absolute(dependencyPath);
+ dependencyPath = context.normalize(dependencyPath);
+ var packageFolder = provider.getFolder(dependencyPath);
+ if (!packageFolder.exists) {
+ _reportErrorForNode(reporter, pathKey(),
+ PubspecWarningCode.PATH_DOES_NOT_EXIST, [pathEntry]);
+ } else {
+ if (!packageFolder
+ .getChild(AnalysisEngine.PUBSPEC_YAML_FILE)
+ .exists) {
+ _reportErrorForNode(reporter, pathKey(),
+ PubspecWarningCode.PATH_PUBSPEC_DOES_NOT_EXIST, [pathEntry]);
}
}
+ if (checkForPathAndGitDeps) {
+ _reportErrorForNode(reporter, pathKey(),
+ PubspecWarningCode.INVALID_DEPENDENCY, [PATH_FIELD]);
+ }
+ }
+
+ var gitEntry = dependency[GIT_FIELD];
+ if (gitEntry != null && checkForPathAndGitDeps) {
+ _reportErrorForNode(reporter, getKey(dependency, GIT_FIELD),
+ PubspecWarningCode.INVALID_DEPENDENCY, [GIT_FIELD]);
}
}
}
diff --git a/pkg/analyzer/lib/src/pubspec/pubspec_warning_code.dart b/pkg/analyzer/lib/src/pubspec/pubspec_warning_code.dart
index ecc7124..a93cca0 100644
--- a/pkg/analyzer/lib/src/pubspec/pubspec_warning_code.dart
+++ b/pkg/analyzer/lib/src/pubspec/pubspec_warning_code.dart
@@ -52,6 +52,17 @@
"The value of the 'flutter' field is expected to be a map.",
correction: "Try converting the value to be a map.");
+ /// A code indicating that a versioned package has an invalid dependency (git
+ /// or path).
+ ///
+ /// Parameters:
+ /// 0: the kind of dependency.
+ static const PubspecWarningCode INVALID_DEPENDENCY = PubspecWarningCode(
+ 'INVALID_DEPENDENCY', "Publishable packages can't have {0} dependencies.",
+ correction:
+ "Try adding a 'publish_to: none' entry to mark the package as not "
+ "for publishing or remove the {0} dependency.");
+
/// A code indicating that the name field is missing.
static const PubspecWarningCode MISSING_NAME = PubspecWarningCode(
'MISSING_NAME', "The name field is required but missing.",
diff --git a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
index 327276b..549701d 100644
--- a/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
+++ b/pkg/analyzer/test/src/dart/micro/simple_file_resolver_test.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/src/dart/error/syntactic_errors.dart';
-import 'package:analyzer/src/dart/micro/libraries_log.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/lint/registry.dart';
import 'package:matcher/matcher.dart';
@@ -25,10 +24,6 @@
String bPath;
String cPath;
- String get _asyncLibraryPath => futureElement.library.source.fullName;
-
- String get _coreLibraryPath => intElement.library.source.fullName;
-
@override
void setUp() {
super.setUp();
@@ -37,57 +32,6 @@
cPath = convertPath('/workspace/dart/test/lib/c.dart');
}
- test_changeFile_log() async {
- newFile(aPath, content: r'''
-class A {}
-''');
-
- newFile(bPath, content: r'''
-import 'a.dart';
-A a;
-B b;
-''');
-
- result = await resolveFile(bPath);
- assertErrorsInResolvedUnit(result, [
- error(CompileTimeErrorCode.UNDEFINED_CLASS, 22, 1),
- ]);
-
- newFile(aPath, content: r'''
-class A {}
-class B {}
-''');
- fileResolver.changeFile(aPath);
-
- result = await resolveFile(bPath);
- assertErrorsInResolvedUnit(result, []);
-
- // The failure of this check will be reported badly.
- expect(fileResolver.librariesLogEntries, [
- predicate((LoadLibrariesForTargetLogEntry entry) {
- expect(entry.target.path, bPath);
- var loadedPathSet = entry.loaded.map((f) => f.path).toSet();
- expect(loadedPathSet, contains(aPath));
- expect(loadedPathSet, contains(bPath));
- expect(loadedPathSet, contains(_asyncLibraryPath));
- expect(loadedPathSet, contains(_coreLibraryPath));
- return true;
- }),
- predicate((ChangeFileLoadEntry entry) {
- expect(entry.target, aPath);
- var removedPathSet = entry.removed.map((f) => f.path).toSet();
- expect(removedPathSet, {aPath, bPath});
- return true;
- }),
- predicate((LoadLibrariesForTargetLogEntry entry) {
- expect(entry.target.path, bPath);
- var loadedPathSet = entry.loaded.map((f) => f.path).toSet();
- expect(loadedPathSet, {aPath, bPath});
- return true;
- }),
- ]);
- }
-
test_changeFile_refreshedFiles() async {
newFile(aPath, content: r'''
class A {}
diff --git a/pkg/analyzer/test/src/pubspec/pubspec_validator_test.dart b/pkg/analyzer/test/src/pubspec/pubspec_validator_test.dart
index 32f7cf3..8e8944a 100644
--- a/pkg/analyzer/test/src/pubspec/pubspec_validator_test.dart
+++ b/pkg/analyzer/test/src/pubspec/pubspec_validator_test.dart
@@ -196,6 +196,73 @@
''');
}
+ test_dependencyGit_malformed_empty() {
+ // todo (pq): consider validating.
+ assertNoErrors('''
+name: sample
+dependencies:
+ foo:
+ git:
+''');
+ }
+
+ test_dependencyGit_malformed_list() {
+ // todo (pq): consider validating.
+ assertNoErrors('''
+name: sample
+dependencies:
+ foo:
+ git:
+ - baz
+''');
+ }
+
+ test_dependencyGit_malformed_scalar() {
+ // todo (pq): consider validating.
+ assertNoErrors('''
+name: sample
+dependencies:
+ foo:
+ git: baz
+''');
+ }
+
+ test_dependencyGit_noVersion_valid() {
+ assertNoErrors('''
+name: sample
+dependencies:
+ foo:
+ git:
+ url: git@github.com:foo/foo.git
+ path: path/to/foo
+''');
+ }
+
+ test_dependencyGit_version_error() {
+ assertErrors('''
+name: sample
+version: 0.1.0
+dependencies:
+ foo:
+ git:
+ url: git@github.com:foo/foo.git
+ path: path/to/foo
+''', [PubspecWarningCode.INVALID_DEPENDENCY]);
+ }
+
+ test_dependencyGit_version_valid() {
+ assertNoErrors('''
+name: sample
+version: 0.1.0
+publish_to: none
+dependencies:
+ foo:
+ git:
+ url: git@github.com:foo/foo.git
+ path: path/to/foo
+''');
+ }
+
test_dependencyGitPath() {
// git paths are not validated
assertNoErrors('''
@@ -208,6 +275,40 @@
''');
}
+ test_dependencyPath_malformed_empty() {
+ // todo (pq): consider validating.
+ assertNoErrors('''
+name: sample
+dependencies:
+ foo:
+ path:
+''');
+ }
+
+ test_dependencyPath_malformed_list() {
+ // todo (pq): consider validating.
+ assertNoErrors('''
+name: sample
+dependencies:
+ foo:
+ path:
+ - baz
+''');
+ }
+
+ test_dependencyPath_noVersion_valid() {
+ newFolder('/foo');
+ newFile('/foo/pubspec.yaml', content: '''
+name: foo
+''');
+ assertNoErrors('''
+name: sample
+dependencies:
+ foo:
+ path: /foo
+''');
+ }
+
test_dependencyPath_pubspecDoesNotExist() {
newFolder('/foo');
assertErrors('''
@@ -257,6 +358,35 @@
''');
}
+ test_dependencyPath_version_error() {
+ newFolder('/foo');
+ newFile('/foo/pubspec.yaml', content: '''
+name: foo
+''');
+ assertErrors('''
+name: sample
+version: 0.1.0
+dependencies:
+ foo:
+ path: /foo
+''', [PubspecWarningCode.INVALID_DEPENDENCY]);
+ }
+
+ test_dependencyPath_version_valid() {
+ newFolder('/foo');
+ newFile('/foo/pubspec.yaml', content: '''
+name: foo
+''');
+ assertNoErrors('''
+name: sample
+version: 0.1.0
+publish_to: none
+dependencies:
+ foo:
+ path: /foo
+''');
+ }
+
test_dependencyPathDoesNotExist_path_error() {
assertErrors('''
name: sample
@@ -288,6 +418,19 @@
''');
}
+ test_devDependencyGit_version_no_error() {
+ // Git paths are OK in dev_dependencies
+ assertNoErrors('''
+name: sample
+version: 0.1.0
+dev_dependencies:
+ foo:
+ git:
+ url: git@github.com:foo/foo.git
+ path: path/to/foo
+''');
+ }
+
test_devDependencyPathDoesNotExist_path_error() {
assertErrors('''
name: sample
diff --git a/tools/VERSION b/tools/VERSION
index ba1203e..6a2eb32 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 11
PATCH 0
-PRERELEASE 272
+PRERELEASE 273
PRERELEASE_PATCH 0
\ No newline at end of file