| // Copyright (c) 2017, 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. |
| |
| /// Source information strategy that concurrently builds sourcemaps for each of |
| /// child strategies. |
| |
| library dart2js.dual_source_information; |
| |
| import '../common.dart'; |
| import '../elements/entities.dart'; |
| import '../js/js_source_mapping.dart'; |
| import '../js/js.dart' as js; |
| import 'code_output.dart' show BufferedCodeOutput; |
| import 'source_information.dart'; |
| |
| class MultiSourceInformationStrategy<T> |
| implements JavaScriptSourceInformationStrategy<T> { |
| final List<JavaScriptSourceInformationStrategy<T>> strategies; |
| |
| const MultiSourceInformationStrategy(this.strategies); |
| |
| @override |
| SourceInformationBuilder<T> createBuilderForContext(MemberEntity member) { |
| return new MultiSourceInformationBuilder<T>( |
| strategies.map((s) => s.createBuilderForContext(member)).toList()); |
| } |
| |
| @override |
| void onComplete() { |
| strategies.forEach((s) => s.onComplete()); |
| } |
| |
| @override |
| SourceInformation buildSourceMappedMarker() { |
| return new MultiSourceInformation( |
| strategies.map((s) => s.buildSourceMappedMarker()).toList()); |
| } |
| |
| @override |
| SourceInformationProcessor createProcessor( |
| SourceMapperProvider sourceMapperProvider, |
| SourceInformationReader reader) { |
| return new MultiSourceInformationProcessor( |
| new List<SourceInformationProcessor>.generate(strategies.length, |
| (int index) { |
| return strategies[index].createProcessor(sourceMapperProvider, |
| new MultiSourceInformationReader(reader, index)); |
| })); |
| } |
| } |
| |
| class MultiSourceInformationProcessor implements SourceInformationProcessor { |
| final List<SourceInformationProcessor> processors; |
| |
| MultiSourceInformationProcessor(this.processors); |
| |
| @override |
| void onStartPosition(js.Node node, int startPosition) { |
| processors.forEach((p) => p.onStartPosition(node, startPosition)); |
| } |
| |
| @override |
| void onPositions( |
| js.Node node, int startPosition, int endPosition, int closingPosition) { |
| processors.forEach((p) => |
| p.onPositions(node, startPosition, endPosition, closingPosition)); |
| } |
| |
| @override |
| void process(js.Node node, BufferedCodeOutput code) { |
| processors.forEach((p) => p.process(node, code)); |
| } |
| } |
| |
| class MultiSourceInformationBuilder<T> implements SourceInformationBuilder<T> { |
| final List<SourceInformationBuilder<T>> builders; |
| |
| MultiSourceInformationBuilder(this.builders); |
| |
| @override |
| SourceInformationBuilder forContext(MemberEntity member) { |
| return new MultiSourceInformationBuilder( |
| builders.map((b) => b.forContext(member)).toList()); |
| } |
| |
| @override |
| SourceInformation buildSwitchCase(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildSwitchCase(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildSwitch(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildSwitch(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildAs(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildAs(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildIs(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildIs(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildTry(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildTry(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildCatch(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildCatch(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildBinary(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildBinary(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildUnary(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildUnary(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildIndexSet(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildIndexSet(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildIndex(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildIndex(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildForInSet(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildForInSet(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildForInCurrent(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildForInCurrent(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildForInMoveNext(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildForInMoveNext(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildForInIterator(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildForInIterator(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildStringInterpolation(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildStringInterpolation(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildForeignCode(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildForeignCode(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildVariableDeclaration() { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildVariableDeclaration()).toList()); |
| } |
| |
| @override |
| SourceInformation buildAwait(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildAwait(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildYield(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildYield(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildAsyncBody() { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildAsyncBody()).toList()); |
| } |
| |
| @override |
| SourceInformation buildAsyncExit() { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildAsyncExit()).toList()); |
| } |
| |
| @override |
| SourceInformation buildAssignment(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildAssignment(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildThrow(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildThrow(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildNew(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildNew(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildIf(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildIf(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildCall(T receiver, T call) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildCall(receiver, call)).toList()); |
| } |
| |
| @override |
| SourceInformation buildGet(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildGet(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildLoop(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildLoop(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildImplicitReturn(MemberEntity element) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildImplicitReturn(element)).toList()); |
| } |
| |
| @override |
| SourceInformation buildReturn(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildReturn(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildCreate(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildCreate(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildListLiteral(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildListLiteral(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildGeneric(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildGeneric(node)).toList()); |
| } |
| |
| @override |
| SourceInformation buildDeclaration(MemberEntity member) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildDeclaration(member)).toList()); |
| } |
| |
| @override |
| SourceInformation buildGoto(T node) { |
| return new MultiSourceInformation( |
| builders.map((b) => b.buildGoto(node)).toList()); |
| } |
| } |
| |
| class MultiSourceInformation implements SourceInformation { |
| final List<SourceInformation> infos; |
| |
| MultiSourceInformation(this.infos); |
| |
| @override |
| String get shortText => infos.first?.shortText; |
| |
| @override |
| List<SourceLocation> get sourceLocations => infos.first?.sourceLocations; |
| |
| @override |
| SourceLocation get endPosition => infos.first?.endPosition; |
| |
| @override |
| SourceLocation get closingPosition => infos.first?.closingPosition; |
| |
| @override |
| SourceLocation get startPosition => infos.first?.startPosition; |
| |
| @override |
| SourceSpan get sourceSpan => infos.first?.sourceSpan; |
| |
| String toString() => '$infos'; |
| } |
| |
| class MultiSourceInformationReader implements SourceInformationReader { |
| final SourceInformationReader reader; |
| final int index; |
| |
| MultiSourceInformationReader(this.reader, this.index); |
| |
| @override |
| SourceInformation getSourceInformation(js.Node node) { |
| MultiSourceInformation sourceInformation = |
| reader.getSourceInformation(node); |
| if (sourceInformation == null) return null; |
| return sourceInformation.infos[index]; |
| } |
| } |