Skip to content

Commit

Permalink
[cfe] Thread nullability modifiers for some InterfaceTypes in outline
Browse files Browse the repository at this point in the history
Closes flutter#38212.

Bug: http://dartbug.com/38212

Change-Id: I4127a1db46a932bd298f82053f58834b60fd4cbb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/115370
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
  • Loading branch information
Dmitry Stefantsov authored and commit-bot@chromium.org committed Sep 6, 2019
1 parent ec7ec4e commit 7ca157d
Show file tree
Hide file tree
Showing 64 changed files with 594 additions and 379 deletions.
2 changes: 2 additions & 0 deletions pkg/front_end/lib/src/fasta/builder/builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ export 'name_iterator.dart' show NameIterator;

export 'named_type_builder.dart' show NamedTypeBuilder;

export 'nullability_builder.dart' show NullabilityBuilder;

export 'prefix_builder.dart' show PrefixBuilder;

export 'type_alias_builder.dart' show TypeAliasBuilder;
Expand Down
14 changes: 9 additions & 5 deletions pkg/front_end/lib/src/fasta/builder/builtin_type_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

library fasta.builtin_type_builder;

import 'package:kernel/ast.dart' show DartType;
import 'package:kernel/ast.dart' show DartType, Nullability;

import 'builder.dart' show LibraryBuilder, TypeBuilder, TypeDeclarationBuilder;

Expand All @@ -15,11 +15,15 @@ abstract class BuiltinTypeBuilder extends TypeDeclarationBuilder {
String name, this.type, LibraryBuilder compilationUnit, int charOffset)
: super(null, 0, name, compilationUnit, charOffset);

DartType buildType(LibraryBuilder library, List<TypeBuilder> arguments) =>
type;
DartType buildType(LibraryBuilder library, Nullability nullability,
List<TypeBuilder> arguments) {
// TODO(dmitryas): Use [nullability].
return type;
}

DartType buildTypesWithBuiltArguments(
LibraryBuilder library, List<DartType> arguments) {
DartType buildTypesWithBuiltArguments(LibraryBuilder library,
Nullability nullability, List<DartType> arguments) {
// TODO(dmitryas): Use [nullability].
return type;
}

Expand Down
14 changes: 9 additions & 5 deletions pkg/front_end/lib/src/fasta/builder/class_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import 'package:kernel/ast.dart'
Member,
MethodInvocation,
Name,
Nullability,
Procedure,
ProcedureKind,
RedirectingFactoryConstructor,
Expand Down Expand Up @@ -407,10 +408,12 @@ abstract class ClassBuilder extends DeclarationBuilder {
InterfaceType get thisType => cls.thisType;

/// [arguments] have already been built.
InterfaceType buildTypesWithBuiltArguments(
LibraryBuilder library, List<DartType> arguments) {
InterfaceType buildTypesWithBuiltArguments(LibraryBuilder library,
Nullability nullability, List<DartType> arguments) {
assert(arguments == null || cls.typeParameters.length == arguments.length);
return arguments == null ? cls.rawType : new InterfaceType(cls, arguments);
return arguments == null
? cls.rawType
: new InterfaceType(cls, arguments, nullability);
}

@override
Expand Down Expand Up @@ -455,9 +458,10 @@ abstract class ClassBuilder extends DeclarationBuilder {
}

/// If [arguments] are null, the default types for the variables are used.
InterfaceType buildType(LibraryBuilder library, List<TypeBuilder> arguments) {
InterfaceType buildType(LibraryBuilder library, Nullability nullability,
List<TypeBuilder> arguments) {
return buildTypesWithBuiltArguments(
library, buildTypeArguments(library, arguments));
library, nullability, buildTypeArguments(library, arguments));
}

Supertype buildSupertype(
Expand Down
23 changes: 15 additions & 8 deletions pkg/front_end/lib/src/fasta/builder/enum_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

library fasta.enum_builder;

import 'builder.dart' show ClassBuilder, MetadataBuilder;
import 'builder.dart' show ClassBuilder, MetadataBuilder, NullabilityBuilder;

import 'package:kernel/ast.dart'
show
Expand All @@ -19,6 +19,7 @@ import 'package:kernel/ast.dart'
IntLiteral,
InterfaceType,
ListLiteral,
Nullability,
ProcedureKind,
ReturnStatement,
StaticGet,
Expand Down Expand Up @@ -107,15 +108,19 @@ class EnumBuilder extends SourceClassBuilder {
assert(enumConstantInfos == null || enumConstantInfos.isNotEmpty);
// TODO(ahe): These types shouldn't be looked up in scope, they come
// directly from dart:core.
TypeBuilder intType = new NamedTypeBuilder("int", null);
TypeBuilder stringType = new NamedTypeBuilder("String", null);
NamedTypeBuilder objectType = new NamedTypeBuilder("Object", null);
TypeBuilder intType =
new NamedTypeBuilder("int", const NullabilityBuilder.omitted(), null);
TypeBuilder stringType = new NamedTypeBuilder(
"String", const NullabilityBuilder.omitted(), null);
NamedTypeBuilder objectType = new NamedTypeBuilder(
"Object", const NullabilityBuilder.omitted(), null);
Class cls = new Class(name: name);
Map<String, MemberBuilder> members = <String, MemberBuilder>{};
Map<String, MemberBuilder> constructors = <String, MemberBuilder>{};
NamedTypeBuilder selfType = new NamedTypeBuilder(name, null);
TypeBuilder listType =
new NamedTypeBuilder("List", <TypeBuilder>[selfType]);
NamedTypeBuilder selfType =
new NamedTypeBuilder(name, const NullabilityBuilder.omitted(), null);
TypeBuilder listType = new NamedTypeBuilder(
"List", const NullabilityBuilder.omitted(), <TypeBuilder>[selfType]);

/// metadata class E {
/// final int index;
Expand Down Expand Up @@ -258,7 +263,9 @@ class EnumBuilder extends SourceClassBuilder {

TypeBuilder get mixedInType => null;

InterfaceType buildType(LibraryBuilder library, List<TypeBuilder> arguments) {
InterfaceType buildType(LibraryBuilder library, Nullability nullability,
List<TypeBuilder> arguments) {
// TODO(dmitryas): Use [nullability].
return cls.rawType;
}

Expand Down
7 changes: 4 additions & 3 deletions pkg/front_end/lib/src/fasta/builder/extension_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,14 @@ abstract class ExtensionBuilder extends DeclarationBuilder {
fileUri);

@override
DartType buildType(LibraryBuilder library, List<TypeBuilder> arguments) {
DartType buildType(LibraryBuilder library, Nullability nullability,
List<TypeBuilder> arguments) {
throw new UnsupportedError("ExtensionBuilder.buildType is not supported.");
}

@override
DartType buildTypesWithBuiltArguments(
LibraryBuilder library, List<DartType> arguments) {
DartType buildTypesWithBuiltArguments(LibraryBuilder library,
Nullability nullability, List<DartType> arguments) {
throw new UnsupportedError("ExtensionBuilder.buildTypesWithBuiltArguments "
"is not supported.");
}
Expand Down
11 changes: 6 additions & 5 deletions pkg/front_end/lib/src/fasta/builder/invalid_type_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

library fasta.invalid_type_builder;

import 'package:kernel/ast.dart' show DartType, InvalidType;
import 'package:kernel/ast.dart' show DartType, InvalidType, Nullability;

import '../fasta_codes.dart' show LocatedMessage;

Expand All @@ -28,13 +28,14 @@ class InvalidTypeBuilder extends TypeDeclarationBuilder {
@override
InvalidType get target => const InvalidType();

DartType buildType(LibraryBuilder library, List<TypeBuilder> arguments) {
return buildTypesWithBuiltArguments(library, null);
DartType buildType(LibraryBuilder library, Nullability nullability,
List<TypeBuilder> arguments) {
return buildTypesWithBuiltArguments(library, null, null);
}

/// [Arguments] have already been built.
DartType buildTypesWithBuiltArguments(
LibraryBuilder library, List<DartType> arguments) {
DartType buildTypesWithBuiltArguments(LibraryBuilder library,
Nullability nullability, List<DartType> arguments) {
if (!suppressMessage) {
library.addProblem(message.messageObject, message.charOffset,
message.length, message.uri,
Expand Down
14 changes: 14 additions & 0 deletions pkg/front_end/lib/src/fasta/builder/library_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import 'builder.dart'
FieldBuilder,
ModifierBuilder,
NameIterator,
NullabilityBuilder,
PrefixBuilder,
Scope,
ScopeBuilder,
Expand Down Expand Up @@ -272,6 +273,19 @@ abstract class LibraryBuilder extends ModifierBuilder {
void buildOutlineExpressions() {}

List<FieldBuilder> takeImplicitlyTypedFields() => null;

// TODO(dmitryas): Compute the predicate using the library version instead.
bool get isNonNullableByDefault => loader.target.enableNonNullable;

NullabilityBuilder computeNullabilityFromToken(bool markedAsNullable) {
if (!isNonNullableByDefault) {
return const NullabilityBuilder.legacy();
}
if (markedAsNullable) {
return const NullabilityBuilder.nullable();
}
return const NullabilityBuilder.omitted();
}
}

class LibraryLocalDeclarationIterator implements Iterator<Builder> {
Expand Down
18 changes: 13 additions & 5 deletions pkg/front_end/lib/src/fasta/builder/named_type_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import 'builder.dart'
Builder,
Identifier,
LibraryBuilder,
NullabilityBuilder,
PrefixBuilder,
QualifiedName,
Scope,
Expand All @@ -54,12 +55,15 @@ class NamedTypeBuilder extends TypeBuilder {

List<TypeBuilder> arguments;

final NullabilityBuilder nullabilityBuilder;

@override
TypeDeclarationBuilder declaration;

NamedTypeBuilder(this.name, this.arguments);
NamedTypeBuilder(this.name, this.nullabilityBuilder, this.arguments);

NamedTypeBuilder.fromTypeDeclarationBuilder(this.declaration,
NamedTypeBuilder.fromTypeDeclarationBuilder(
this.declaration, this.nullabilityBuilder,
[this.arguments])
: this.name = declaration.name;

Expand Down Expand Up @@ -181,6 +185,7 @@ class NamedTypeBuilder extends TypeBuilder {
t.printOn(buffer);
}
buffer.write(">");
nullabilityBuilder.writeNullabilityOn(buffer);
return buffer;
}

Expand Down Expand Up @@ -209,7 +214,8 @@ class NamedTypeBuilder extends TypeBuilder {

DartType build(LibraryBuilder library) {
assert(declaration != null, "Declaration has not been resolved on $this.");
return declaration.buildType(library, arguments);
return declaration.buildType(
library, nullabilityBuilder.build(library), arguments);
}

Supertype buildSupertype(
Expand Down Expand Up @@ -265,7 +271,8 @@ class NamedTypeBuilder extends TypeBuilder {
i++;
}
if (arguments != null) {
return new NamedTypeBuilder(name, arguments)..bind(declaration);
return new NamedTypeBuilder(name, nullabilityBuilder, arguments)
..bind(declaration);
}
}
return this;
Expand All @@ -279,7 +286,8 @@ class NamedTypeBuilder extends TypeBuilder {
clonedArguments[i] = arguments[i].clone(newTypes);
}
}
NamedTypeBuilder newType = new NamedTypeBuilder(name, clonedArguments);
NamedTypeBuilder newType =
new NamedTypeBuilder(name, nullabilityBuilder, clonedArguments);
newTypes.add(newType);
return newType;
}
Expand Down
84 changes: 84 additions & 0 deletions pkg/front_end/lib/src/fasta/builder/nullability_builder.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright (c) 2019, 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:core' hide MapEntry;
import 'package:kernel/ast.dart';
import '../kernel/body_builder.dart';
import '../builder/builder.dart';
import '../problems.dart';

/// Represents the nullability modifiers encountered while parsing the types.
///
/// The syntactic nullability needs to be interpreted, that is, built, into the
/// semantic nullability used on [DartType]s of Kernel.
enum SyntacticNullability {
/// Used when the type is declared with '?' suffix after it.
nullable,

/// Used when the type is declared in an opted-out library.
legacy,

/// Used when the type is declared without any nullability suffixes.
omitted,
}

class NullabilityBuilder {
final SyntacticNullability _syntacticNullability;

const NullabilityBuilder.nullable()
: _syntacticNullability = SyntacticNullability.nullable;

const NullabilityBuilder.legacy()
: _syntacticNullability = SyntacticNullability.legacy;

const NullabilityBuilder.omitted()
: _syntacticNullability = SyntacticNullability.omitted;

/// Used temporarily in the places that need proper handling of NNBD features.
///
/// Over time the uses of [NullabilityBuilder.pendingImplementation] should be
/// eliminated, and the constructor should be eventually removed. Currently,
/// it redirects to [NullabilityBuilder.legacy] as a conservative safety
/// measure for the pre-NNBD code and as a visible reminder of the feature
/// implementation being in progress in the NNBD code.
// TODO(dmitryas): Remove this constructor.
const NullabilityBuilder.pendingImplementation() : this.legacy();

Nullability build(LibraryBuilder libraryBuilder, {Nullability ifOmitted}) {
// TODO(dmitryas): Ensure that either ifOmitted is set or libraryBuilder is
// provided;
//assert(libraryBuilder != null || ifOmitted != null);
ifOmitted ??= (libraryBuilder == null ? Nullability.legacy : null);

ifOmitted ??= libraryBuilder.isNonNullableByDefault
? Nullability.nonNullable
: Nullability.legacy;
switch (_syntacticNullability) {
case SyntacticNullability.legacy:
return Nullability.legacy;
case SyntacticNullability.nullable:
return Nullability.nullable;
case SyntacticNullability.omitted:
return ifOmitted;
}
return unhandled("$_syntacticNullability", "buildNullability",
TreeNode.noOffset, noLocation);
}

void writeNullabilityOn(StringBuffer sb) {
switch (_syntacticNullability) {
case SyntacticNullability.legacy:
sb.write("*");
return;
case SyntacticNullability.nullable:
sb.write("?");
return;
case SyntacticNullability.omitted:
// Do nothing.
return;
}
unhandled("$_syntacticNullability", "writeNullabilityOn", TreeNode.noOffset,
noLocation);
}
}
11 changes: 7 additions & 4 deletions pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:kernel/ast.dart'
DynamicType,
FunctionType,
InvalidType,
Nullability,
TypeParameter,
Typedef,
VariableDeclaration;
Expand Down Expand Up @@ -146,8 +147,9 @@ class TypeAliasBuilder extends TypeDeclarationBuilder {
}

/// [arguments] have already been built.
DartType buildTypesWithBuiltArguments(
LibraryBuilder library, List<DartType> arguments) {
DartType buildTypesWithBuiltArguments(LibraryBuilder library,
Nullability nullability, List<DartType> arguments) {
// TODO(dmitryas): Use [nullability].
DartType thisType = buildThisType(library);
if (const DynamicType() == thisType) return thisType;
FunctionType result = thisType;
Expand Down Expand Up @@ -202,14 +204,15 @@ class TypeAliasBuilder extends TypeDeclarationBuilder {
int get typeVariablesCount => typeVariables?.length ?? 0;

@override
DartType buildType(LibraryBuilder library, List<TypeBuilder> arguments) {
DartType buildType(LibraryBuilder library, Nullability nullability,
List<TypeBuilder> arguments) {
DartType thisType = buildThisType(library);
if (thisType is InvalidType) return thisType;
FunctionType result = thisType;
if (typedef.typeParameters.isEmpty && arguments == null) return result;
// Otherwise, substitute.
return buildTypesWithBuiltArguments(
library, buildTypeArguments(library, arguments));
library, nullability, buildTypeArguments(library, arguments));
}
}

Expand Down
Loading

0 comments on commit 7ca157d

Please sign in to comment.