Index: pkg/analyzer/lib/src/lint/pub.dart |
diff --git a/pkg/analyzer/lib/src/lint/pub.dart b/pkg/analyzer/lib/src/lint/pub.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..8d12e134bb54aa213c11ad6633cf85897e1a69ce |
--- /dev/null |
+++ b/pkg/analyzer/lib/src/lint/pub.dart |
@@ -0,0 +1,430 @@ |
+// Copyright (c) 2015, 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:collection'; |
+ |
+import 'package:source_span/source_span.dart'; |
+import 'package:yaml/yaml.dart'; |
+ |
+PSEntry _findEntry(YamlMap map, String key) { |
+ PSEntry entry; |
+ map.nodes.forEach((k, v) { |
+ if (k is YamlScalar && key == k.toString()) { |
+ entry = _processScalar(k, v); |
+ } |
+ }); |
+ return entry; |
+} |
+ |
+PSDependencyList _processDependencies(YamlScalar key, YamlNode v) { |
+ if (v is! YamlMap) { |
+ return null; |
+ } |
+ YamlMap depsMap = v; |
+ |
+ _PSDependencyList deps = new _PSDependencyList(new _PSNode(key)); |
+ depsMap.nodes.forEach((k, v) => deps.add(new _PSDependency(k, v))); |
+ return deps; |
+} |
+ |
+PSGitRepo _processGitRepo(YamlScalar key, YamlNode v) { |
+ if (v is! YamlMap) { |
+ return null; |
+ } |
+ YamlMap hostMap = v; |
+ // url: git://github.com/munificent/kittens.git |
+ // ref: some-branch |
+ _PSGitRepo repo = new _PSGitRepo(); |
+ repo.token = new _PSNode(key); |
+ repo.ref = _findEntry(hostMap, 'ref'); |
+ repo.url = _findEntry(hostMap, 'url'); |
+ return repo; |
+} |
+ |
+PSHost _processHost(YamlScalar key, YamlNode v) { |
+ if (v is! YamlMap) { |
+ return null; |
+ } |
+ YamlMap hostMap = v; |
+ // name: transmogrify |
+ // url: http://your-package-server.com |
+ _PSHost host = new _PSHost(); |
+ host.token = new _PSNode(key); |
+ host.name = _findEntry(hostMap, 'name'); |
+ host.url = _findEntry(hostMap, 'url'); |
+ return host; |
+} |
+ |
+PSNodeList _processList(YamlScalar key, YamlNode v) { |
+ if (v is! YamlList) { |
+ return null; |
+ } |
+ YamlList nodeList = v; |
+ |
+ return new _PSNodeList( |
+ new _PSNode(key), nodeList.nodes.map((n) => new _PSNode(n))); |
+} |
+ |
+PSEntry _processScalar(YamlScalar key, YamlNode value) { |
+ if (value is! YamlScalar) { |
+ return null; |
+ //WARN? |
+ } |
+ return new PSEntry(new _PSNode(key), new _PSNode(value)); |
+} |
+ |
+abstract class PSDependency { |
+ PSGitRepo get git; |
+ PSHost get host; |
+ PSNode get name; |
+ PSEntry get version; |
+} |
+ |
+abstract class PSDependencyList extends Object |
+ with IterableMixin<PSDependency> {} |
+ |
+class PSEntry { |
+ final PSNode key; |
+ final PSNode value; |
+ PSEntry(this.key, this.value); |
+ |
+ @override |
+ String toString() => '${key != null ? (key.toString() + ': ') : ''}$value'; |
+} |
+ |
+abstract class PSGitRepo { |
+ PSEntry get ref; |
+ PSNode get token; |
+ PSEntry get url; |
+} |
+ |
+abstract class PSHost { |
+ PSEntry get name; |
+ PSNode get token; |
+ PSEntry get url; |
+} |
+ |
+abstract class PSNode { |
+ SourceSpan get span; |
+ String get text; |
+} |
+ |
+abstract class PSNodeList extends Object with IterableMixin<PSNode> { |
+ @override |
+ Iterator<PSNode> get iterator; |
+ PSNode get token; |
+} |
+ |
+abstract class Pubspec { |
+ factory Pubspec.parse(String source, {Uri sourceUrl}) => |
+ new _Pubspec(source, sourceUrl: sourceUrl); |
+ PSEntry get author; |
+ PSNodeList get authors; |
+ PSDependencyList get dependencies; |
+ PSEntry get description; |
+ PSDependencyList get devDependencies; |
+ PSEntry get documentation; |
+ PSEntry get homepage; |
+ PSEntry get name; |
+ PSEntry get version; |
+ accept(PubspecVisitor visitor); |
+} |
+ |
+abstract class PubspecVisitor<T> { |
+ T visitPackageAuthor(PSEntry author) => null; |
+ T visitPackageAuthors(PSNodeList authors) => null; |
+ T visitPackageDependencies(PSDependencyList dependencies) => null; |
+ T visitPackageDependency(PSDependency dependency) => null; |
+ T visitPackageDescription(PSEntry description) => null; |
+ T visitPackageDevDependencies(PSDependencyList dependencies) => null; |
+ T visitPackageDevDependency(PSDependency dependency) => null; |
+ T visitPackageDocumentation(PSEntry documentation) => null; |
+ T visitPackageHomepage(PSEntry homepage) => null; |
+ T visitPackageName(PSEntry name) => null; |
+ T visitPackageVersion(PSEntry version) => null; |
+} |
+ |
+class _PSDependency extends PSDependency { |
+ @override |
+ PSNode name; |
+ @override |
+ PSEntry version; |
+ @override |
+ PSHost host; |
+ @override |
+ PSGitRepo git; |
+ |
+ factory _PSDependency(dynamic k, YamlNode v) { |
+ if (k is! YamlScalar) { |
+ return null; |
+ } |
+ YamlScalar key = k; |
+ |
+ _PSDependency dep = new _PSDependency._(); |
+ |
+ dep.name = new _PSNode(key); |
+ |
+ if (v is YamlScalar) { |
+ // Simple version |
+ dep.version = new PSEntry(null, new _PSNode(v)); |
+ } else if (v is YamlMap) { |
+ // hosted: |
+ // name: transmogrify |
+ // url: http://your-package-server.com |
+ // version: '>=0.4.0 <1.0.0' |
+ YamlMap details = v; |
+ details.nodes.forEach((k, v) { |
+ if (k is! YamlScalar) { |
+ return; |
+ } |
+ YamlScalar key = k; |
+ switch (key.toString()) { |
+ case 'version': |
+ dep.version = _processScalar(key, v); |
+ break; |
+ case 'hosted': |
+ dep.host = _processHost(key, v); |
+ break; |
+ case 'git': |
+ dep.git = _processGitRepo(key, v); |
+ break; |
+ } |
+ }); |
+ } |
+ return dep; |
+ } |
+ |
+ _PSDependency._(); |
+ |
+ @override |
+ String toString() { |
+ var sb = new StringBuffer(); |
+ if (name != null) { |
+ sb.write('$name:'); |
+ } |
+ var versionInfo = ''; |
+ if (version != null) { |
+ if (version.key == null) { |
+ versionInfo = ' $version'; |
+ } else { |
+ versionInfo = '\n $version'; |
+ } |
+ } |
+ sb.writeln(versionInfo); |
+ if (host != null) { |
+ sb.writeln(host); |
+ } |
+ if (git != null) { |
+ sb.writeln(git); |
+ } |
+ return sb.toString(); |
+ } |
+} |
+ |
+class _PSDependencyList extends PSDependencyList { |
+ final dependencies = <PSDependency>[]; |
+ final PSNode token; |
+ |
+ _PSDependencyList(this.token); |
+ |
+ @override |
+ Iterator<PSDependency> get iterator => dependencies.iterator; |
+ |
+ add(PSDependency dependency) { |
+ if (dependency != null) { |
+ dependencies.add(dependency); |
+ } |
+ } |
+ |
+ @override |
+ String toString() => '$token\n${dependencies.join(' ')}'; |
+} |
+ |
+class _PSGitRepo implements PSGitRepo { |
+ @override |
+ PSNode token; |
+ @override |
+ PSEntry ref; |
+ @override |
+ PSEntry url; |
+ @override |
+ String toString() => ''' |
+ $token: |
+ $url |
+ $ref'''; |
+} |
+ |
+class _PSHost implements PSHost { |
+ @override |
+ PSNode token; |
+ @override |
+ PSEntry name; |
+ @override |
+ PSEntry url; |
+ @override |
+ String toString() => ''' |
+ $token: |
+ $name |
+ $url'''; |
+} |
+ |
+class _PSNode implements PSNode { |
+ @override |
+ final String text; |
+ @override |
+ final SourceSpan span; |
+ |
+ _PSNode(YamlNode node) |
+ : text = node.value?.toString(), |
+ span = node.span; |
+ |
+ @override |
+ String toString() => '$text'; |
+} |
+ |
+class _PSNodeList extends PSNodeList { |
+ @override |
+ final PSNode token; |
+ final Iterable<PSNode> nodes; |
+ |
+ _PSNodeList(this.token, this.nodes); |
+ |
+ @override |
+ Iterator<PSNode> get iterator => nodes.iterator; |
+ |
+ @override |
+ String toString() => ''' |
+$token: |
+ - ${nodes.join('\n - ')}'''; |
+} |
+ |
+class _Pubspec implements Pubspec { |
+ @override |
+ PSEntry author; |
+ @override |
+ PSNodeList authors; |
+ @override |
+ PSEntry description; |
+ @override |
+ PSEntry documentation; |
+ @override |
+ PSEntry homepage; |
+ @override |
+ PSEntry name; |
+ @override |
+ PSEntry version; |
+ @override |
+ PSDependencyList dependencies; |
+ @override |
+ PSDependencyList devDependencies; |
+ |
+ _Pubspec(String src, {Uri sourceUrl}) { |
+ try { |
+ _parse(src, sourceUrl: sourceUrl); |
+ } on Exception { |
+ // ignore |
+ } |
+ } |
+ |
+ @override |
+ void accept(PubspecVisitor visitor) { |
+ if (author != null) { |
+ visitor.visitPackageAuthor(author); |
+ } |
+ if (authors != null) { |
+ visitor.visitPackageAuthors(authors); |
+ } |
+ if (description != null) { |
+ visitor.visitPackageDescription(description); |
+ } |
+ if (documentation != null) { |
+ visitor.visitPackageDocumentation(documentation); |
+ } |
+ if (homepage != null) { |
+ visitor.visitPackageHomepage(homepage); |
+ } |
+ if (name != null) { |
+ visitor.visitPackageName(name); |
+ } |
+ if (version != null) { |
+ visitor.visitPackageVersion(version); |
+ } |
+ if (dependencies != null) { |
+ visitor.visitPackageDependencies(dependencies); |
+ dependencies.forEach((d) => visitor.visitPackageDependency(d)); |
+ } |
+ if (devDependencies != null) { |
+ visitor.visitPackageDevDependencies(devDependencies); |
+ devDependencies.forEach((d) => visitor.visitPackageDevDependency(d)); |
+ } |
+ } |
+ |
+ @override |
+ String toString() { |
+ var sb = new _StringBuilder(); |
+ sb.writelin(name); |
+ sb.writelin(version); |
+ sb.writelin(author); |
+ sb.writelin(authors); |
+ sb.writelin(description); |
+ sb.writelin(homepage); |
+ sb.writelin(dependencies); |
+ sb.writelin(devDependencies); |
+ return sb.toString(); |
+ } |
+ |
+ _parse(String src, {Uri sourceUrl}) { |
+ var yaml = loadYamlNode(src, sourceUrl: sourceUrl); |
+ if (yaml is! YamlMap) { |
+ return; |
+ } |
+ YamlMap yamlMap = yaml; |
+ yamlMap.nodes.forEach((k, v) { |
+ if (k is! YamlScalar) { |
+ return; |
+ } |
+ YamlScalar key = k; |
+ switch (key.toString()) { |
+ case 'author': |
+ author = _processScalar(key, v); |
+ break; |
+ case 'authors': |
+ authors = _processList(key, v); |
+ break; |
+ case 'homepage': |
+ homepage = _processScalar(key, v); |
+ break; |
+ case 'name': |
+ name = _processScalar(key, v); |
+ break; |
+ case 'description': |
+ description = _processScalar(key, v); |
+ break; |
+ case 'documentation': |
+ documentation = _processScalar(key, v); |
+ break; |
+ case 'dependencies': |
+ dependencies = _processDependencies(key, v); |
+ break; |
+ case 'dev_dependencies': |
+ devDependencies = _processDependencies(key, v); |
+ break; |
+ case 'version': |
+ version = _processScalar(key, v); |
+ break; |
+ } |
+ }); |
+ } |
+} |
+ |
+class _StringBuilder { |
+ StringBuffer buffer = new StringBuffer(); |
+ @override |
+ String toString() => buffer.toString(); |
+ writelin(Object value) { |
+ if (value != null) { |
+ buffer.writeln(value); |
+ } |
+ } |
+} |