mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[kernel] Partial support for conditional imports in CFE.
In order to un-block Flutter integration, we introduce partial support for conditional imports into the CFE. There are two incomplete parts: - The condition strings are evaluated by the Target. They should be looked up in the environment, but this introduces complications with modular compilation. - Type inference and other static checks are performed with reference to the implementation (conditionally-imported) library rather than the interface library. See issue #30143 for more details. Bug: Change-Id: I740b45e9d32796644837de4caefd8d6e8015f229 Reviewed-on: https://dart-review.googlesource.com/34721 Reviewed-by: Peter von der Ahé <ahe@google.com>
This commit is contained in:
parent
b79696982d
commit
a2ff93da67
14
pkg/front_end/lib/src/fasta/configuration.dart
Normal file
14
pkg/front_end/lib/src/fasta/configuration.dart
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) 2018, 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 fasta.configuration;
|
||||
|
||||
class Configuration {
|
||||
final int charOffset;
|
||||
final String dottedName;
|
||||
final String condition;
|
||||
final String importUri;
|
||||
Configuration(
|
||||
this.charOffset, this.dottedName, this.condition, this.importUri);
|
||||
}
|
|
@ -12,6 +12,8 @@ import 'kernel/kernel_builder.dart' show toKernelCombinators;
|
|||
|
||||
import 'combinator.dart' show Combinator;
|
||||
|
||||
import 'configuration.dart' show Configuration;
|
||||
|
||||
typedef void AddToScope(String name, Builder member);
|
||||
|
||||
class Import {
|
||||
|
@ -29,12 +31,21 @@ class Import {
|
|||
|
||||
final List<Combinator> combinators;
|
||||
|
||||
final List<Configuration> configurations;
|
||||
|
||||
final int charOffset;
|
||||
|
||||
final int prefixCharOffset;
|
||||
|
||||
Import(this.importer, this.imported, this.deferred, this.prefix,
|
||||
this.combinators, this.charOffset, this.prefixCharOffset)
|
||||
Import(
|
||||
this.importer,
|
||||
this.imported,
|
||||
this.deferred,
|
||||
this.prefix,
|
||||
this.combinators,
|
||||
this.configurations,
|
||||
this.charOffset,
|
||||
this.prefixCharOffset)
|
||||
: prefixBuilder = createPrefixBuilder(prefix, importer, imported,
|
||||
combinators, deferred, charOffset, prefixCharOffset);
|
||||
|
||||
|
|
|
@ -44,7 +44,9 @@ import '../quote.dart' show unescapeString;
|
|||
|
||||
import 'source_library_builder.dart' show SourceLibraryBuilder;
|
||||
|
||||
import 'unhandled_listener.dart' show NullValue, Unhandled, UnhandledListener;
|
||||
import 'unhandled_listener.dart' show NullValue, UnhandledListener;
|
||||
|
||||
import '../configuration.dart' show Configuration;
|
||||
|
||||
enum MethodBody {
|
||||
Abstract,
|
||||
|
@ -143,7 +145,7 @@ class OutlineBuilder extends UnhandledListener {
|
|||
void endExport(Token exportKeyword, Token semicolon) {
|
||||
debugEvent("Export");
|
||||
List<Combinator> combinators = pop();
|
||||
Unhandled conditionalUris = pop();
|
||||
List<Configuration> conditionalUris = pop();
|
||||
int uriOffset = popCharOffset();
|
||||
String uri = pop();
|
||||
List<MetadataBuilder> metadata = pop();
|
||||
|
@ -171,15 +173,38 @@ class OutlineBuilder extends UnhandledListener {
|
|||
bool isDeferred = pop();
|
||||
int prefixOffset = pop();
|
||||
String prefix = pop(NullValue.Prefix);
|
||||
Unhandled conditionalUris = pop();
|
||||
List<Configuration> configurations = pop();
|
||||
int uriOffset = popCharOffset();
|
||||
String uri = pop();
|
||||
String uri = pop(); // For a conditional import, this is the default URI.
|
||||
List<MetadataBuilder> metadata = pop();
|
||||
library.addImport(metadata, uri, conditionalUris, prefix, combinators,
|
||||
library.addImport(metadata, uri, configurations, prefix, combinators,
|
||||
isDeferred, importKeyword.charOffset, prefixOffset, uriOffset);
|
||||
checkEmpty(importKeyword.charOffset);
|
||||
}
|
||||
|
||||
@override
|
||||
void endConditionalUris(int count) {
|
||||
debugEvent("EndConditionalUris");
|
||||
push(popList(count) ?? NullValue.ConditionalUris);
|
||||
}
|
||||
|
||||
@override
|
||||
void endConditionalUri(Token ifKeyword, Token leftParen, Token equalSign) {
|
||||
debugEvent("EndConditionalUri");
|
||||
int charOffset = popCharOffset();
|
||||
String uri = pop();
|
||||
if (equalSign != null) popCharOffset();
|
||||
String condition = popIfNotNull(equalSign) ?? "true";
|
||||
String dottedName = pop();
|
||||
push(new Configuration(charOffset, dottedName, condition, uri));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleDottedName(int count, Token firstIdentifier) {
|
||||
debugEvent("DottedName");
|
||||
push(popIdentifierList(count).join('.'));
|
||||
}
|
||||
|
||||
@override
|
||||
void handleRecoverImport(Token semicolon) {
|
||||
debugEvent("RecoverImport");
|
||||
|
|
|
@ -30,7 +30,6 @@ import '../builder/builder.dart'
|
|||
TypeBuilder,
|
||||
TypeDeclarationBuilder,
|
||||
TypeVariableBuilder,
|
||||
Unhandled,
|
||||
UnresolvedType;
|
||||
|
||||
import '../combinator.dart' show Combinator;
|
||||
|
@ -58,6 +57,8 @@ import '../fasta_codes.dart'
|
|||
|
||||
import '../import.dart' show Import;
|
||||
|
||||
import '../configuration.dart' show Configuration;
|
||||
|
||||
import '../problems.dart' show unhandled;
|
||||
|
||||
import 'source_loader.dart' show SourceLoader;
|
||||
|
@ -191,7 +192,7 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R>
|
|||
void addExport(
|
||||
List<MetadataBuilder> metadata,
|
||||
String uri,
|
||||
Unhandled conditionalUris,
|
||||
List<Configuration> conditionalUris,
|
||||
List<Combinator> combinators,
|
||||
int charOffset,
|
||||
int uriOffset) {
|
||||
|
@ -204,13 +205,24 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R>
|
|||
void addImport(
|
||||
List<MetadataBuilder> metadata,
|
||||
String uri,
|
||||
Unhandled conditionalUris,
|
||||
List<Configuration> configurations,
|
||||
String prefix,
|
||||
List<Combinator> combinators,
|
||||
bool deferred,
|
||||
int charOffset,
|
||||
int prefixCharOffset,
|
||||
int uriOffset) {
|
||||
if (configurations != null) {
|
||||
for (Configuration config in configurations) {
|
||||
if (loader.target.backendTarget
|
||||
.lookupImportCondition(config.dottedName) ==
|
||||
config.condition) {
|
||||
uri = config.importUri;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
imports.add(new Import(
|
||||
this,
|
||||
loader.read(resolve(this.uri, uri, uriOffset), charOffset,
|
||||
|
@ -218,6 +230,7 @@ abstract class SourceLibraryBuilder<T extends TypeBuilder, R>
|
|||
deferred,
|
||||
prefix,
|
||||
combinators,
|
||||
configurations,
|
||||
charOffset,
|
||||
prefixCharOffset));
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ enum NullValue {
|
|||
Combinators,
|
||||
Comments,
|
||||
ConditionalUris,
|
||||
ConditionallySelectedImport,
|
||||
ConstructorInitializerSeparator,
|
||||
ConstructorInitializers,
|
||||
ConstructorReferenceContinuationAfterTypeArguments,
|
||||
|
|
|
@ -152,6 +152,10 @@ abstract class Target {
|
|||
/// extensions, but targets like dart2js only enable it on the core libraries.
|
||||
bool enableNative(Uri uri) => false;
|
||||
|
||||
/// Returns whether the given condition Uri should evaluate to true for the
|
||||
/// purposes of resolving conditional imports.
|
||||
String lookupImportCondition(String condition) => "";
|
||||
|
||||
/// There are two variants of the `native` language extension. The VM expects
|
||||
/// the native token to be followed by string, whereas dart2js and DDC do not.
|
||||
// TODO(sigmund, ahe): ideally we should remove the `native` syntax, if not,
|
||||
|
|
Loading…
Reference in a new issue