Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(533)

Unified Diff: lib/src/utils.dart

Issue 1879373004: Implement modular compilation (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/src/runner/v8_runner.dart ('k') | pubspec.yaml » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/src/utils.dart
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
deleted file mode 100644
index 229eef40628b14181ea81daca377a647a92b4b54..0000000000000000000000000000000000000000
--- a/lib/src/utils.dart
+++ /dev/null
@@ -1,460 +0,0 @@
-// 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.
-
-/// Holds a couple utility functions used at various places in the system.
-
-import 'dart:io';
-import 'package:path/path.dart' as path;
-import 'package:analyzer/dart/ast/ast.dart'
- show
- ImportDirective,
- ExportDirective,
- PartDirective,
- CompilationUnit,
- Identifier,
- AnnotatedNode,
- AstNode,
- Expression,
- SimpleIdentifier,
- MethodInvocation;
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
-import 'package:analyzer/src/generated/constant.dart' show DartObject;
-//TODO(leafp): Remove deprecated dependency
-//ignore: DEPRECATED_MEMBER_USE
-import 'package:analyzer/src/generated/element.dart' show DynamicTypeImpl;
-import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
-import 'package:analyzer/src/task/dart.dart' show ParseDartTask;
-import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
-import 'package:analyzer/src/generated/source.dart' show LineInfo, Source;
-import 'package:analyzer/analyzer.dart' show parseDirectives;
-import 'package:source_span/source_span.dart';
-
-import 'codegen/js_names.dart' show invalidVariableName;
-
-bool isDartPrivateLibrary(LibraryElement library) {
- var uri = library.source.uri;
- if (uri.scheme != "dart") return false;
- return Identifier.isPrivateName(uri.path);
-}
-
-/// Choose a canonical name from the library element. This is safe to use as a
-/// namespace in JS and Dart code generation. This never uses the library's
-/// name (the identifier in the `library` declaration) as it doesn't have any
-/// meaningful rules enforced.
-String canonicalLibraryName(LibraryElement library) {
- var uri = library.source.uri;
- var name = path.basenameWithoutExtension(uri.pathSegments.last);
- return _toIdentifier(name);
-}
-
-/// Escape [name] to make it into a valid identifier.
-String _toIdentifier(String name) {
- if (name.length == 0) return r'$';
-
- // Escape any invalid characters
- StringBuffer buffer = null;
- for (int i = 0; i < name.length; i++) {
- var ch = name[i];
- var needsEscape = ch == r'$' || _invalidCharInIdentifier.hasMatch(ch);
- if (needsEscape && buffer == null) {
- buffer = new StringBuffer(name.substring(0, i));
- }
- if (buffer != null) {
- buffer.write(needsEscape ? '\$${ch.codeUnits.join("")}' : ch);
- }
- }
-
- var result = buffer != null ? '$buffer' : name;
- // Ensure the identifier first character is not numeric and that the whole
- // identifier is not a keyword.
- if (result.startsWith(new RegExp('[0-9]')) || invalidVariableName(result)) {
- return '\$$result';
- }
- return result;
-}
-
-// Invalid characters for identifiers, which would need to be escaped.
-final _invalidCharInIdentifier = new RegExp(r'[^A-Za-z_$0-9]');
-
-/// Returns all libraries transitively imported or exported from [start].
-List<LibraryElement> reachableLibraries(LibraryElement start) {
- var results = <LibraryElement>[];
- var seen = new Set();
- void find(LibraryElement lib) {
- if (seen.contains(lib)) return;
- seen.add(lib);
- results.add(lib);
- lib.importedLibraries.forEach(find);
- lib.exportedLibraries.forEach(find);
- }
- find(start);
- return results;
-}
-
-/// Returns all sources transitively imported or exported from [start] in
-/// post-visit order. Internally this uses digest parsing to read only
-/// directives from each source, that way library resolution can be done
-/// bottom-up and improve performance of the analyzer internal cache.
-Iterable<Source> reachableSources(Source start, AnalysisContext context) {
- var results = <Source>[];
- var seen = new Set();
- void find(Source source) {
- if (seen.contains(source)) return;
- seen.add(source);
- _importsAndExportsOf(source, context).forEach(find);
- results.add(source);
- }
- find(start);
- return results;
-}
-
-/// Returns sources that are imported or exported in [source] (parts are
-/// excluded).
-Iterable<Source> _importsAndExportsOf(Source source, AnalysisContext context) {
- var unit =
- parseDirectives(context.getContents(source).data, name: source.fullName);
- return unit.directives
- .where((d) => d is ImportDirective || d is ExportDirective)
- .map((d) {
- var res = ParseDartTask.resolveDirective(context, source, d, null);
- if (res == null) print('error: couldn\'t resolve $d');
- return res;
- }).where((d) => d != null);
-}
-
-/// Returns the enclosing library of [e].
-LibraryElement enclosingLibrary(Element e) {
- while (e != null && e is! LibraryElement) e = e.enclosingElement;
- return e;
-}
-
-/// Returns sources that are included with part directives from [unit].
-Iterable<Source> partsOf(CompilationUnit unit, AnalysisContext context) {
- return unit.directives.where((d) => d is PartDirective).map((d) {
- var res =
- ParseDartTask.resolveDirective(context, unit.element.source, d, null);
- if (res == null) print('error: couldn\'t resolve $d');
- return res;
- }).where((d) => d != null);
-}
-
-/// Looks up the declaration that matches [member] in [type] or its superclasses
-/// and interfaces, and returns its declared type.
-// TODO(sigmund): add this to lookUp* in analyzer. The difference here is that
-// we also look in interfaces in addition to superclasses.
-FunctionType searchTypeFor(InterfaceType start, ExecutableElement member) {
- var getMemberTypeHelper = _memberTypeGetter(member);
- FunctionType search(InterfaceType type, bool first) {
- if (type == null) return null;
- var res = null;
- if (!first) {
- res = getMemberTypeHelper(type);
- if (res != null) return res;
- }
-
- for (var m in type.mixins.reversed) {
- res = search(m, false);
- if (res != null) return res;
- }
-
- res = search(type.superclass, false);
- if (res != null) return res;
-
- for (var i in type.interfaces) {
- res = search(i, false);
- if (res != null) return res;
- }
-
- return null;
- }
-
- return search(start, true);
-}
-
-/// Looks up the declaration that matches [member] in [type] and returns it's
-/// declared type.
-FunctionType getMemberType(InterfaceType type, ExecutableElement member) =>
- _memberTypeGetter(member)(type);
-
-typedef FunctionType _MemberTypeGetter(InterfaceType type);
-
-_MemberTypeGetter _memberTypeGetter(ExecutableElement member) {
- String memberName = member.name;
- final isGetter = member is PropertyAccessorElement && member.isGetter;
- final isSetter = member is PropertyAccessorElement && member.isSetter;
-
- FunctionType f(InterfaceType type) {
- ExecutableElement baseMethod;
- try {
- if (isGetter) {
- assert(!isSetter);
- // Look for getter or field.
- baseMethod = type.getGetter(memberName);
- } else if (isSetter) {
- baseMethod = type.getSetter(memberName);
- } else {
- baseMethod = type.getMethod(memberName);
- }
- } catch (e) {
- // TODO(sigmund): remove this try-catch block (see issue #48).
- }
- if (baseMethod == null || baseMethod.isStatic) return null;
- return baseMethod.type;
- }
- ;
- return f;
-}
-
-bool isDynamicTarget(Expression node) {
- if (node == null) return false;
-
- if (isLibraryPrefix(node)) return false;
-
- // Null type happens when we have unknown identifiers, like a dart: import
- // that doesn't resolve.
- var type = node.staticType;
- return type == null || type.isDynamic;
-}
-
-bool isLibraryPrefix(Expression node) =>
- node is SimpleIdentifier && node.staticElement is PrefixElement;
-
-/// Returns an ANSII color escape sequence corresponding to [levelName]. Colors
-/// are defined for: severe, error, warning, or info. Returns null if the level
-/// name is not recognized.
-String colorOf(String levelName) {
- levelName = levelName.toLowerCase();
- if (levelName == 'shout' || levelName == 'severe' || levelName == 'error') {
- return _RED_COLOR;
- }
- if (levelName == 'warning') return _MAGENTA_COLOR;
- if (levelName == 'info') return _CYAN_COLOR;
- return null;
-}
-
-const String _RED_COLOR = '\u001b[31m';
-const String _MAGENTA_COLOR = '\u001b[35m';
-const String _CYAN_COLOR = '\u001b[36m';
-const String GREEN_COLOR = '\u001b[32m';
-const String NO_COLOR = '\u001b[0m';
-
-class OutWriter {
- final String _path;
- final StringBuffer _sb = new StringBuffer();
- int _indent = 0;
- String _prefix = "";
- bool _needsIndent = true;
-
- OutWriter(this._path);
-
- void write(String string, [int indent = 0]) {
- if (indent < 0) inc(indent);
-
- var lines = string.split('\n');
- for (var i = 0, end = lines.length - 1; i < end; i++) {
- _writeln(lines[i]);
- }
- _write(lines.last);
-
- if (indent > 0) inc(indent);
- }
-
- void _writeln(String string) {
- if (_needsIndent && string.isNotEmpty) _sb.write(_prefix);
- _sb.writeln(string);
- _needsIndent = true;
- }
-
- void _write(String string) {
- if (_needsIndent && string.isNotEmpty) {
- _sb.write(_prefix);
- _needsIndent = false;
- }
- _sb.write(string);
- }
-
- void inc([int n = 2]) {
- _indent = _indent + n;
- assert(_indent >= 0);
- _prefix = "".padRight(_indent);
- }
-
- void dec([int n = 2]) {
- _indent = _indent - n;
- assert(_indent >= 0);
- _prefix = "".padRight(_indent);
- }
-
- void close() {
- new File(_path).writeAsStringSync('$_sb');
- }
-}
-
-SourceLocation locationForOffset(LineInfo lineInfo, Uri uri, int offset) {
- var loc = lineInfo.getLocation(offset);
- return new SourceLocation(offset,
- sourceUrl: uri, line: loc.lineNumber - 1, column: loc.columnNumber - 1);
-}
-
-String resourceOutputPath(Uri resourceUri, Uri entryUri, String runtimeDir) {
- if (resourceUri.scheme == 'package') return resourceUri.path;
-
- if (resourceUri.scheme != 'file') return null;
-
- var entryPath = entryUri.path;
- // The entry uri is either a directory or a dart/html file. If the latter,
- // trim the file.
- var entryDir = entryPath.endsWith('.dart') || entryPath.endsWith('.html')
- ? path.dirname(entryPath)
- : entryPath;
- var filepath = path.normalize(path.join(entryDir, resourceUri.path));
- if (path.isWithin(runtimeDir, filepath)) {
- filepath = path.relative(filepath, from: runtimeDir);
- return path.join('dev_compiler', 'runtime', filepath);
- }
-
- return path.relative(resourceUri.path, from: entryDir);
-}
-
-/// Given an annotated [node] and a [test] function, returns the first matching
-/// constant valued annotation.
-///
-/// For example if we had the ClassDeclaration node for `FontElement`:
-///
-/// @js.JS('HTMLFontElement')
-/// @deprecated
-/// class FontElement { ... }
-///
-/// We could match `@deprecated` with a test function like:
-///
-/// (v) => v.type.name == 'Deprecated' && v.type.element.library.isDartCore
-///
-DartObject findAnnotation(Element element, bool test(DartObject value)) {
- for (var metadata in element.metadata) {
- var value = metadata.constantValue;
- if (value != null && test(value)) return value;
- }
- return null;
-}
-
-/// Given a constant [value], a [fieldName], and an [expectedType], returns the
-/// value of that field.
-///
-/// If the field is missing or is not [expectedType], returns null.
-DartObject getConstantField(
- DartObject value, String fieldName, DartType expectedType) {
- var f = value?.getField(fieldName);
- return (f == null || f.type != expectedType) ? null : f;
-}
-
-DartType fillDynamicTypeArgs(DartType t, TypeProvider types) {
- if (t is ParameterizedType) {
- var dyn = new List.filled(t.typeArguments.length, types.dynamicType);
- return t.substitute2(dyn, t.typeArguments);
- }
- return t;
-}
-
-/// Similar to [SimpleIdentifier] inGetterContext, inSetterContext, and
-/// inDeclarationContext, this method returns true if [node] is used in an
-/// invocation context such as a MethodInvocation.
-bool inInvocationContext(SimpleIdentifier node) {
- var parent = node.parent;
- return parent is MethodInvocation && parent.methodName == node;
-}
-
-// TODO(vsm): Move this onto the appropriate class. Ideally, we'd attach
-// it to TypeProvider.
-
-/// Searches all supertype, in order of most derived members, to see if any
-/// [match] a condition. If so, returns the first match, otherwise returns null.
-InterfaceType findSupertype(InterfaceType type, bool match(InterfaceType t)) {
- for (var m in type.mixins.reversed) {
- if (match(m)) return m;
- }
- var s = type.superclass;
- if (s == null) return null;
-
- if (match(s)) return type;
- return findSupertype(s, match);
-}
-
-SourceSpanWithContext createSpanHelper(
- LineInfo lineInfo, int start, int end, Source source, String content) {
- var startLoc = locationForOffset(lineInfo, source.uri, start);
- var endLoc = locationForOffset(lineInfo, source.uri, end);
-
- var lineStart = startLoc.offset - startLoc.column;
- // Find the end of the line. This is not exposed directly on LineInfo, but
- // we can find it pretty easily.
- // TODO(jmesserly): for now we do the simple linear scan. Ideally we can get
- // some help from the LineInfo API.
- int lineEnd = endLoc.offset;
- int lineNum = lineInfo.getLocation(lineEnd).lineNumber;
- while (lineEnd < content.length &&
- lineInfo.getLocation(++lineEnd).lineNumber == lineNum);
-
- var text = content.substring(start, end);
- var lineText = content.substring(lineStart, lineEnd);
- return new SourceSpanWithContext(startLoc, endLoc, text, lineText);
-}
-
-bool isInlineJS(Element e) =>
- e is FunctionElement &&
- e.library.source.uri.toString() == 'dart:_foreign_helper' &&
- e.name == 'JS';
-
-bool isDartMathMinMax(Element e) =>
- e is FunctionElement &&
- e.library.source.uri.toString() == 'dart:math' &&
- (e.name == 'min' || e.name == 'max');
-
-/// Parses an enum value out of a string.
-// TODO(ochafik): generic signature.
-dynamic parseEnum(String s, List enumValues) =>
- enumValues.firstWhere((v) => s == getEnumName(v),
- orElse: () => throw new ArgumentError('Unknown enum value: $s '
- '(expected one of ${enumValues.map(getEnumName)})'));
-
-/// Gets the "simple" name of an enum value.
-getEnumName(v) {
- var parts = '$v'.split('.');
- if (parts.length != 2 || !parts.every((p) => p.isNotEmpty)) {
- throw new ArgumentError('Invalid enum value: $v');
- }
- return parts[1];
-}
-
-class FileSystem {
- const FileSystem();
-
- void _ensureParentExists(String file) {
- var dir = new Directory(path.dirname(file));
- if (!dir.existsSync()) dir.createSync(recursive: true);
- }
-
- void copySync(String source, String destination) {
- _ensureParentExists(destination);
- new File(source).copySync(destination);
- }
-
- void writeAsStringSync(String file, String contents) {
- _ensureParentExists(file);
- new File(file).writeAsStringSync(contents);
- }
-}
-
-//TODO(leafp): Is this really necessary? In theory I think
-// the static type should always be filled in for resolved
-// ASTs. This may be a vestigial workaround.
-DartType getStaticType(Expression e) =>
- e.staticType ?? DynamicTypeImpl.instance;
-
-// TODO(leafp) Factor this out or use an existing library
-class Tuple2<T0, T1> {
- final T0 e0;
- final T1 e1;
- Tuple2(this.e0, this.e1);
-}
« no previous file with comments | « lib/src/runner/v8_runner.dart ('k') | pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698