Linter Demo Errors: 0Warnings: 7File: /home/fstrocco/Dart/dart/benchmark/compiler/lib/src/apiimpl.dart // Copyright (c) 2012, 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. library leg_apiimpl; import 'dart:async'; import '../compiler.dart' as api; import 'dart2jslib.dart' as leg; import 'tree/tree.dart' as tree; import 'elements/elements.dart' as elements; import 'package:_internal/libraries.dart' hide LIBRARIES; import 'package:_internal/libraries.dart' as library_info show LIBRARIES; import 'io/source_file.dart'; const bool forceIncrementalSupport = const bool.fromEnvironment('DART2JS_EXPERIMENTAL_INCREMENTAL_SUPPORT'); class Compiler extends leg.Compiler { api.CompilerInputProvider provider; api.DiagnosticHandler handler; final Uri libraryRoot; final Uri packageRoot; List options; Map environment; bool mockableLibraryUsed = false; final Set allowedLibraryCategories; leg.GenericTask userHandlerTask; leg.GenericTask userProviderTask; Compiler(this.provider, api.CompilerOutputProvider outputProvider, this.handler, this.libraryRoot, this.packageRoot, List options, this.environment) : this.options = options, this.allowedLibraryCategories = getAllowedLibraryCategories(options), super( outputProvider: outputProvider, enableTypeAssertions: hasOption(options, '--enable-checked-mode'), enableUserAssertions: hasOption(options, '--enable-checked-mode'), trustTypeAnnotations: hasOption(options, '--trust-type-annotations'), trustPrimitives: hasOption(options, '--trust-primitives'), enableMinification: hasOption(options, '--minify'), preserveUris: hasOption(options, '--preserve-uris'), enableNativeLiveTypeAnalysis: !hasOption(options, '--disable-native-live-type-analysis'), emitJavaScript: !(hasOption(options, '--output-type=dart') || hasOption(options, '--output-type=dart-multi')), dart2dartMultiFile: hasOption(options, '--output-type=dart-multi'), generateSourceMap: !hasOption(options, '--no-source-maps'), analyzeAllFlag: hasOption(options, '--analyze-all'), analyzeOnly: hasOption(options, '--analyze-only'), analyzeMain: hasOption(options, '--analyze-main'), analyzeSignaturesOnly: hasOption(options, '--analyze-signatures-only'), strips: extractCsvOption(options, '--force-strip='), enableConcreteTypeInference: hasOption(options, '--enable-concrete-type-inference'), disableTypeInferenceFlag: hasOption(options, '--disable-type-inference'), preserveComments: hasOption(options, '--preserve-comments'), verbose: hasOption(options, '--verbose'), sourceMapUri: extractUriOption(options, '--source-map='), outputUri: extractUriOption(options, '--out='), terseDiagnostics: hasOption(options, '--terse'), deferredMapUri: extractUriOption(options, '--deferred-map='), dumpInfo: hasOption(options, '--dump-info'), buildId: extractStringOption( options, '--build-id=', "build number could not be determined"), showPackageWarnings: hasOption(options, '--show-package-warnings'), useContentSecurityPolicy: hasOption(options, '--csp'), hasIncrementalSupport: forceIncrementalSupport || hasOption(options, '--incremental-support'), suppressWarnings: hasOption(options, '--suppress-warnings'), enableExperimentalMirrors: hasOption(options, '--enable-experimental-mirrors'), generateCodeWithCompileTimeErrors: hasOption(options, '--generate-code-with-compile-time-errors'), allowNativeExtensions: hasOption(options, '--allow-native-extensions')) { tasks.addAll([ userHandlerTask = new leg.GenericTask('Diagnostic handler', this), userProviderTask = new leg.GenericTask('Input provider', this), ]); if (libraryRoot == null) { throw new ArgumentError("[libraryRoot] is null."); } if (!libraryRoot.path.endsWith("/")) { throw new ArgumentError("[libraryRoot] must end with a /."); } if (packageRoot == null) { throw new ArgumentError("[packageRoot] is null."); } if (!packageRoot.path.endsWith("/")) { throw new ArgumentError("[packageRoot] must end with a /."); } if (!analyzeOnly) { if (allowNativeExtensions) { throw new ArgumentError( "--allow-native-extensions is only supported in combination with " "--analyze-only"); } } } static String extractStringOption(List options, String prefix, String defaultValue) { for (String option in options) { if (option.startsWith(prefix)) { return option.substring(prefix.length); } } return defaultValue; } static Uri extractUriOption(List options, String prefix) { var option = extractStringOption(options, prefix, null); return (option == null) ? null : Uri.parse(option); } // CSV: Comma separated values. static List extractCsvOption(List options, String prefix) { for (String option in options) { if (option.startsWith(prefix)) { return option.substring(prefix.length).split(','); } } return const []; } static Set getAllowedLibraryCategories(List options) { var result = extractCsvOption(options, '--categories='); if (result.isEmpty) { result = ['Client']; } result.add('Shared'); result.add('Internal'); return new Set.from(result); } static bool hasOption(List options, String option) { return options.indexOf(option) >= 0; } // TODO(johnniwinther): Merge better with [translateDartUri] when // [scanBuiltinLibrary] is removed. String lookupLibraryPath(String dartLibraryName) { LibraryInfo info = lookupLibraryInfo(dartLibraryName); if (info == null) return null; if (!info.isDart2jsLibrary) return null; if (!allowedLibraryCategories.contains(info.category)) return null; String path = info.dart2jsPath; if (path == null) { path = info.path; } return "lib/$path"; } String lookupPatchPath(String dartLibraryName) { LibraryInfo info = lookupLibraryInfo(dartLibraryName); if (info == null) return null; if (!info.isDart2jsLibrary) return null; String path = info.dart2jsPatchPath; if (path == null) return null; return "lib/$path"; } void log(message) { handler(null, null, null, message, api.Diagnostic.VERBOSE_INFO); } /// See [leg.Compiler.translateResolvedUri]. Uri translateResolvedUri(elements.LibraryElement importingLibrary, Uri resolvedUri, tree.Node node) { if (resolvedUri.scheme == 'dart') { return translateDartUri(importingLibrary, resolvedUri, node); } return resolvedUri; } /** * Reads the script designated by [readableUri]. */ Future readScript(leg.Spannable node, Uri readableUri) { if (!readableUri.isAbsolute) { if (node == null) node = leg.NO_LOCATION_SPANNABLE; internalError(node, 'Relative uri $readableUri provided to readScript(Uri).'); } // We need to store the current element since we are reporting read errors // asynchronously and therefore need to restore the current element for // [node] to be valid. elements.Element element = currentElement; void reportReadError(exception) { if (element == null || node == null) { reportError( new leg.SourceSpan(readableUri, 0, 0), leg.MessageKind.READ_SELF_ERROR, {'uri': readableUri, 'exception': exception}); } else { withCurrentElement(element, () { reportError( node, leg.MessageKind.READ_SCRIPT_ERROR, {'uri': readableUri, 'exception': exception}); }); } } Uri resourceUri = translateUri(node, readableUri); if (resourceUri.scheme == 'dart-ext') { if (!allowNativeExtensions) { withCurrentElement(element, () { reportError(node, leg.MessageKind.DART_EXT_NOT_SUPPORTED); }); } return synthesizeScript(node, readableUri); } // TODO(johnniwinther): Wrap the result from [provider] in a specialized // [Future] to ensure that we never execute an asynchronous action without // setting up the current element of the compiler. return new Future.sync(() => callUserProvider(resourceUri)).then((data) { SourceFile sourceFile; if (data is List) { sourceFile = new Utf8BytesSourceFile(resourceUri, data); } else if (data is String) { sourceFile = new StringSourceFile.fromUri(resourceUri, data); } else { String message = "Expected a 'String' or a 'List' from the input " "provider, but got: ${Error.safeToString(data)}."; reportReadError(message); } // We use [readableUri] as the URI for the script since need to preserve // the scheme in the script because [Script.uri] is used for resolving // relative URIs mentioned in the script. See the comment on // [LibraryLoader] for more details. return new leg.Script(readableUri, resourceUri, sourceFile); }).catchError((error) { reportReadError(error); return synthesizeScript(node, readableUri); }); } Future synthesizeScript(leg.Spannable node, Uri readableUri) { Uri resourceUri = translateUri(node, readableUri); return new Future.value( new leg.Script( readableUri, resourceUri, new StringSourceFile.fromUri( resourceUri, "// Synthetic source file generated for '$readableUri'."), isSynthesized: true)); } /** * Translates a readable URI into a resource URI. * * See [LibraryLoader] for terminology on URIs. */ Uri translateUri(leg.Spannable node, Uri readableUri) { switch (readableUri.scheme) { case 'package': return translatePackageUri(node, readableUri); default: return readableUri; } } Uri translateDartUri(elements.LibraryElement importingLibrary, Uri resolvedUri, tree.Node node) { LibraryInfo libraryInfo = lookupLibraryInfo(resolvedUri.path); String path = lookupLibraryPath(resolvedUri.path); if (libraryInfo != null && libraryInfo.category == "Internal") { bool allowInternalLibraryAccess = false; if (importingLibrary != null) { if (importingLibrary.isPlatformLibrary || importingLibrary.isPatch) { allowInternalLibraryAccess = true; } else if (importingLibrary.canonicalUri.path.contains( 'dart/tests/compiler/dart2js_native')) { allowInternalLibraryAccess = true; } } if (!allowInternalLibraryAccess) { if (importingLibrary != null) { reportError( node, leg.MessageKind.INTERNAL_LIBRARY_FROM, {'resolvedUri': resolvedUri, 'importingUri': importingLibrary.canonicalUri}); } else { reportError( node, leg.MessageKind.INTERNAL_LIBRARY, {'resolvedUri': resolvedUri}); } } } if (path == null) { reportError(node, leg.MessageKind.LIBRARY_NOT_FOUND, {'resolvedUri': resolvedUri}); return null; } if (resolvedUri.path == 'html' || resolvedUri.path == 'io') { // TODO(ahe): Get rid of mockableLibraryUsed when test.dart // supports this use case better. mockableLibraryUsed = true; } return libraryRoot.resolve(path); } Uri resolvePatchUri(String dartLibraryPath) { String patchPath = lookupPatchPath(dartLibraryPath); if (patchPath == null) return null; return libraryRoot.resolve(patchPath); } Uri translatePackageUri(leg.Spannable node, Uri uri) { return packageRoot.resolve(uri.path); } Future run(Uri uri) { log('Allowed library categories: $allowedLibraryCategories'); return super.run(uri).then((bool success) { int cumulated = 0; for (final task in tasks) { int elapsed = task.timing; if (elapsed != 0) { cumulated += elapsed; log('${task.name} took ${elapsed}msec'); } } int total = totalCompileTime.elapsedMilliseconds; log('Total compile-time ${total}msec;' ' unaccounted ${total - cumulated}msec'); return success; }); } void reportDiagnostic(leg.Spannable node, leg.Message message, api.Diagnostic kind) { leg.SourceSpan span = spanFromSpannable(node); if (identical(kind, api.Diagnostic.ERROR) || identical(kind, api.Diagnostic.CRASH)) { compilationFailed = true; } // [:span.uri:] might be [:null:] in case of a [Script] with no [uri]. For // instance in the [Types] constructor in typechecker.dart. if (span == null || span.uri == null) { callUserHandler(null, null, null, '$message', kind); } else { callUserHandler( translateUri(null, span.uri), span.begin, span.end, '$message', kind); } } bool get isMockCompilation { return mockableLibraryUsed && (options.indexOf('--allow-mock-compilation') != -1); } void callUserHandler(Uri uri, int begin, int end, String message, api.Diagnostic kind) { try { userHandlerTask.measure(() { handler(uri, begin, end, message, kind); }); } catch (ex, s) { diagnoseCrashInUserCode( 'Uncaught exception in diagnostic handler', ex, s); rethrow; } } Future callUserProvider(Uri uri) { try { return userProviderTask.measure(() => provider(uri)); } catch (ex, s) { diagnoseCrashInUserCode('Uncaught exception in input provider', ex, s); rethrow; } } void diagnoseCrashInUserCode(String message, exception, stackTrace) { hasCrashed = true; print('$message: ${tryToString(exception)}'); print(tryToString(stackTrace)); } fromEnvironment(String name) => environment[name]; LibraryInfo lookupLibraryInfo(String libraryName) { return library_info.LIBRARIES[libraryName]; } }