Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add resolve(id) to BuildStep #25

Merged
merged 1 commit into from
Feb 3, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/build.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) 2016, 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.
export 'src/analyzer/resolver.dart';
export 'src/asset/asset.dart';
export 'src/asset/exceptions.dart';
export 'src/asset/file_based.dart';
Expand Down
118 changes: 118 additions & 0 deletions lib/src/analyzer/resolver.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Copyright (c) 2016, 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:async';

import 'package:analyzer/analyzer.dart' show Expression;
import 'package:analyzer/src/generated/constant.dart' show EvaluationResult;
import 'package:analyzer/src/generated/element.dart';
import 'package:code_transformers/resolver.dart' as code_transformers
show Resolver;
import 'package:source_maps/refactor.dart';
import 'package:source_span/source_span.dart';

import '../asset/id.dart';
import '../builder/build_step.dart';
import '../util/barback.dart';

class Resolver {
final code_transformers.Resolver resolver;

Resolver(this.resolver);

/// Update the status of all the sources referenced by the entry points and
/// update the resolved library. If [entryPoints] is omitted, the input
/// asset of [buildStep] is used as the only entry point.
///
/// [release] must be called when done handling this [Resolver] to allow it
/// to be used by later phases.
Future<Resolver> resolve(BuildStep buildStep,
[List<AssetId> entryPoints]) async {
return new Resolver(await resolver.resolve(toBarbackTransform(buildStep),
entryPoints?.map(toBarbackAssetId)?.toList()));
}

/// Release this resolver so it can be updated by following build steps.
void release() => resolver.release();

/// Gets the resolved Dart library for an asset, or null if the AST has not
/// been resolved.
///
/// If the AST has not been resolved then this normally means that the
/// transformer hosting this needs to be in an earlier phase.
LibraryElement getLibrary(AssetId assetId) =>
resolver.getLibrary(toBarbackAssetId(assetId));

/// Gets all libraries accessible from the entry point, recursively.
///
/// This includes all Dart SDK libraries as well.
Iterable<LibraryElement> get libraries => resolver.libraries;

/// Finds the first library identified by [libraryName], or null if no
/// library can be found.
LibraryElement getLibraryByName(String libraryName) =>
resolver.getLibraryByName(libraryName);

/// Finds the first library identified by [libraryName], or null if no
/// library can be found.
///
/// [uri] must be an absolute URI of the form
/// `[dart:|package:]path/file.dart`.
LibraryElement getLibraryByUri(Uri uri) => resolver.getLibraryByUri(uri);

/// Resolves a fully-qualified type name (library_name.ClassName).
///
/// This will resolve the first instance of [typeName], because of potential
/// library name conflicts the name is not guaranteed to be unique.
ClassElement getType(String typeName) => resolver.getType(typeName);

/// Resolves a fully-qualified top-level library variable
/// (library_name.variableName).
///
/// This will resolve the first instance of [variableName], because of
/// potential library name conflicts the name is not guaranteed to be unique.
Element getLibraryVariable(String variableName) =>
resolver.getLibraryVariable(variableName);

/// Resolves a fully-qualified top-level library function
/// (library_name.functionName).
///
/// This will resolve the first instance of [functionName], because of
/// potential library name conflicts the name is not guaranteed to be unique.
Element getLibraryFunction(String functionName) =>
resolver.getLibraryFunction(functionName);

/// Gets the result of evaluating the constant [expression] in the context of
/// a [library].
EvaluationResult evaluateConstant(
LibraryElement library, Expression expression) =>
resolver.evaluateConstant(library, expression);

/// Gets an URI appropriate for importing the specified library.
///
/// Returns null if the library cannot be imported via an absolute URI or
/// from [from] (if provided).
Uri getImportUri(LibraryElement lib, {AssetId from}) => resolver
.getImportUri(lib, from: from == null ? null : toBarbackAssetId(from));

/// Get the asset ID of the file containing the asset.
AssetId getSourceAssetId(Element element) =>
toBuildAssetId(resolver.getSourceAssetId(element));

/// Get the source span where the specified element was defined or null if
/// the element came from the Dart SDK.
SourceSpan getSourceSpan(Element element) => resolver.getSourceSpan(element);

/// Get a [SourceFile] with the contents of the file that defines [element],
/// or null if the element came from the Dart SDK.
SourceFile getSourceFile(Element element) => resolver.getSourceFile(element);

/// Creates a text edit transaction for the given element if it is able
/// to be edited, returns null otherwise.
///
/// The transaction contains the entire text of the source file where the
/// element originated. If the element was from a library part then the
/// source file is the part file rather than the library.
TextEditTransaction createTextEditTransaction(Element element) =>
resolver.createTextEditTransaction(element);
}
5 changes: 5 additions & 0 deletions lib/src/builder/build_step.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import 'dart:async';
import 'dart:convert';

import '../analyzer/resolver.dart';
import '../asset/asset.dart';
import '../asset/id.dart';

Expand All @@ -22,4 +23,8 @@ abstract class BuildStep {
/// Outputs an [Asset] using the current [AssetWriter], and adds [asset] to
/// [outputs].
void writeAsString(Asset asset, {Encoding encoding: UTF8});

/// Gives a [Resolver] for [id]. This must be released when it is done being
/// used.
Future<Resolver> resolve(id);
}
11 changes: 11 additions & 0 deletions lib/src/builder/build_step_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,23 @@ import 'dart:async';
import 'dart:collection';
import 'dart:convert';

import 'package:code_transformers/resolver.dart' as code_transformers;

import '../analyzer/resolver.dart';
import '../asset/asset.dart';
import '../asset/id.dart';
import '../asset/reader.dart';
import '../asset/writer.dart';
import '../util/barback.dart';
import 'build_step.dart';
import 'exceptions.dart';

/// A single step in the build processes. This represents a single input and
/// its expected and real outputs. It also handles tracking of dependencies.
class BuildStepImpl implements BuildStep {
static code_transformers.Resolvers _resolvers =
new code_transformers.Resolvers(code_transformers.dartSdkDirectory);

/// The primary input for this build step.
@override
final Asset input;
Expand Down Expand Up @@ -76,4 +83,8 @@ class BuildStepImpl implements BuildStep {
var done = _writer.writeAsString(asset, encoding: encoding);
_outputsCompleted = _outputsCompleted.then((_) => done);
}

/// Resolves [id] and returns a [Future<Resolver>] once that is done.
Future<Resolver> resolve(AssetId id) async => new Resolver(
await _resolvers.get(toBarbackTransform(this), [toBarbackAssetId(id)]));
}
30 changes: 9 additions & 21 deletions lib/src/transformer/transformer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import '../asset/reader.dart';
import '../asset/writer.dart';
import '../builder/builder.dart';
import '../builder/build_step_impl.dart';
import '../util/barback.dart';

/// A [Transformer] which runs multiple [Builder]s.
/// Extend this class and define the [builders] getter to create a [Transformer]
Expand All @@ -39,7 +40,7 @@ abstract class BuilderTransformer implements Transformer, DeclaringTransformer {

@override
Future apply(Transform transform) async {
var input = await _toBuildAsset(transform.primaryInput);
var input = await toBuildAsset(transform.primaryInput);
var reader = new _TransformAssetReader(transform);
var writer = new _TransformAssetWriter(transform);

Expand All @@ -56,8 +57,8 @@ abstract class BuilderTransformer implements Transformer, DeclaringTransformer {
var preExistingFiles = [];
for (var output in expected) {
if (!allExpected.add(output) ||
await transform.hasInput(_toBarbackAssetId(output))) {
preExistingFiles.add(_toBarbackAssetId(output));
await transform.hasInput(toBarbackAssetId(output))) {
preExistingFiles.add(toBarbackAssetId(output));
}
}
if (preExistingFiles.isNotEmpty) {
Expand All @@ -78,7 +79,7 @@ abstract class BuilderTransformer implements Transformer, DeclaringTransformer {
@override
void declareOutputs(DeclaringTransform transform) {
for (var outputId in _expectedOutputs(transform.primaryId, builders)) {
transform.declareOutput(_toBarbackAssetId(outputId));
transform.declareOutput(toBarbackAssetId(outputId));
}
}
}
Expand All @@ -91,11 +92,11 @@ class _TransformAssetReader implements AssetReader {

@override
Future<bool> hasInput(build.AssetId id) =>
transform.hasInput(_toBarbackAssetId(id));
transform.hasInput(toBarbackAssetId(id));

@override
Future<String> readAsString(build.AssetId id, {Encoding encoding: UTF8}) =>
transform.readInputAsString(_toBarbackAssetId(id), encoding: encoding);
transform.readInputAsString(toBarbackAssetId(id), encoding: encoding);
}

/// Very simple [AssetWriter] which uses a [Transform].
Expand All @@ -106,7 +107,7 @@ class _TransformAssetWriter implements AssetWriter {

@override
Future writeAsString(build.Asset asset, {Encoding encoding: UTF8}) {
transform.addOutput(_toBarbackAsset(asset));
transform.addOutput(toBarbackAsset(asset));
return new Future.value(null);
}
}
Expand All @@ -115,19 +116,6 @@ class _TransformAssetWriter implements AssetWriter {
Iterable<build.AssetId> _expectedOutputs(
barback.AssetId id, Iterable<Builder> builders) sync* {
for (var builder in builders) {
yield* builder.declareOutputs(_toBuildAssetId(id));
yield* builder.declareOutputs(toBuildAssetId(id));
}
}

barback.AssetId _toBarbackAssetId(build.AssetId id) =>
new barback.AssetId(id.package, id.path);

build.AssetId _toBuildAssetId(barback.AssetId id) =>
new build.AssetId(id.package, id.path);

barback.Asset _toBarbackAsset(build.Asset asset) =>
new barback.Asset.fromString(
_toBarbackAssetId(asset.id), asset.stringContents);

Future<build.Asset> _toBuildAsset(barback.Asset asset) async =>
new build.Asset(_toBuildAssetId(asset.id), await asset.readAsString());
78 changes: 78 additions & 0 deletions lib/src/util/barback.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Copyright (c) 2016, 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:async';
import 'dart:convert';

import 'package:barback/barback.dart' as barback;

import '../asset/asset.dart' as build;
import '../asset/id.dart' as build;
import '../builder/build_step.dart' as build;

barback.AssetId toBarbackAssetId(build.AssetId id) =>
new barback.AssetId(id.package, id.path);

build.AssetId toBuildAssetId(barback.AssetId id) =>
new build.AssetId(id.package, id.path);

barback.Asset toBarbackAsset(build.Asset asset) => new barback.Asset.fromString(
toBarbackAssetId(asset.id), asset.stringContents);

Future<build.Asset> toBuildAsset(barback.Asset asset) async =>
new build.Asset(toBuildAssetId(asset.id), await asset.readAsString());

barback.Transform toBarbackTransform(build.BuildStep buildStep) =>
new BuildStepTransform(buildStep);

class BuildStepTransform implements barback.Transform {
final build.BuildStep buildStep;

BuildStepTransform(this.buildStep);

@override
barback.Asset get primaryInput => toBarbackAsset(buildStep.input);

@override
barback.TransformLogger get logger =>
new barback.TransformLogger((asset, level, message, span) {
var buffer = new StringBuffer();
buffer.write('$level: ');
if (asset != null) {
buffer.write('From $asset');
if (span != null) {
buffer.write('()$span)');
}
buffer.write(': ');
}
buffer.write(message);
print(buffer);
});

@override
Future<barback.Asset> getInput(barback.AssetId id, {Encoding encoding}) =>
throw new UnimplementedError();

@override
Future<String> readInputAsString(barback.AssetId id, {Encoding encoding}) {
return buildStep.readAsString(toBuildAssetId(id), encoding: encoding);
}

@override
Stream<List<int>> readInput(barback.AssetId id) =>
throw new UnimplementedError();

@override
Future<bool> hasInput(barback.AssetId id) =>
buildStep.hasInput(toBuildAssetId(id));

@override
void addOutput(barback.Asset output) {
toBuildAsset(output).then((asset) {
buildStep.writeAsString(asset);
});
}

@override
void consumePrimary() => throw new UnimplementedError();
}
4 changes: 4 additions & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@ environment:
sdk: '>=1.9.1 <2.0.0'

dependencies:
analyzer: ^0.27.1
barback: ^0.15.0
code_transformers: ^0.4.0
glob: ^1.1.0
path: ^1.1.0
source_maps: '>=0.9.4 <0.11.0'
source_span: '>=1.0.0 <2.0.0'
stack_trace: ^1.6.0
yaml: ^2.1.0

Expand Down
Loading