Version 2.15.0-233.0.dev
Merge commit '098d517e9fc49c3ee0495673ce7eb78e3dfef600' into 'dev'
diff --git a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
index a1b1989..c2d764a 100644
--- a/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
+++ b/pkg/analysis_server/lib/src/provisional/completion/dart/completion_dart.dart
@@ -19,10 +19,14 @@
/// An object that contributes results for the `completion.getSuggestions`
/// request results.
abstract class DartCompletionContributor {
+ final DartCompletionRequest request;
+ final SuggestionBuilder builder;
+
+ DartCompletionContributor(this.request, this.builder);
+
/// Return a [Future] that completes when the suggestions appropriate for the
/// given completion [request] have been added to the [builder].
- Future<void> computeSuggestions(
- DartCompletionRequest request, SuggestionBuilder builder);
+ Future<void> computeSuggestions();
}
/// The information about a requested list of completions within a Dart file.
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
index 05f7592..44f88c6 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
@@ -14,20 +14,18 @@
/// A contributor that produces suggestions for named expression labels that
/// correspond to named parameters when completing in argument lists.
class ArgListContributor extends DartCompletionContributor {
- /// The request that is currently being handled.
- late DartCompletionRequest request;
-
- /// The suggestion builder used to build suggestions.
- late SuggestionBuilder builder;
-
/// The argument list that is the containing node of the target, or `null` if
/// the containing node of the target is not an argument list (such as when
/// it's a named expression).
ArgumentList? argumentList;
+ ArgListContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
@override
- Future<void> computeSuggestions(
- DartCompletionRequest request, SuggestionBuilder builder) async {
+ Future<void> computeSuggestions() async {
var parameters = request.target.executableElement?.parameters ??
request.target.functionType?.parameters;
if (parameters == null) {
@@ -39,8 +37,6 @@
argumentList = node;
}
- this.request = request;
- this.builder = builder;
_addSuggestions(parameters);
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/combinator_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/combinator_contributor.dart
index 12fe155..138c369 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/combinator_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/combinator_contributor.dart
@@ -11,9 +11,13 @@
/// A contributor that produces suggestions based on the members of a library
/// when the completion is in a show or hide combinator of an import or export.
class CombinatorContributor extends DartCompletionContributor {
+ CombinatorContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
@override
- Future<void> computeSuggestions(
- DartCompletionRequest request, SuggestionBuilder builder) async {
+ Future<void> computeSuggestions() async {
var node = request.target.containingNode;
if (node is! Combinator) {
return;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index cec2be3..f8298ff 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -126,30 +126,32 @@
// Request Dart specific completions from each contributor
var builder = SuggestionBuilder(dartRequest, listener: listener);
var contributors = <DartCompletionContributor>[
- ArgListContributor(),
- CombinatorContributor(),
- ExtensionMemberContributor(),
- FieldFormalContributor(),
- KeywordContributor(),
- LabelContributor(),
- LibraryMemberContributor(),
- LibraryPrefixContributor(),
- LocalLibraryContributor(),
- LocalReferenceContributor(),
- NamedConstructorContributor(),
- if (enableOverrideContributor) OverrideContributor(),
- RedirectingContributor(),
- StaticMemberContributor(),
- TypeMemberContributor(),
- if (enableUriContributor) UriContributor(),
- VariableNameContributor()
+ ArgListContributor(dartRequest, builder),
+ CombinatorContributor(dartRequest, builder),
+ ExtensionMemberContributor(dartRequest, builder),
+ FieldFormalContributor(dartRequest, builder),
+ KeywordContributor(dartRequest, builder),
+ LabelContributor(dartRequest, builder),
+ LibraryMemberContributor(dartRequest, builder),
+ LibraryPrefixContributor(dartRequest, builder),
+ LocalLibraryContributor(dartRequest, builder),
+ LocalReferenceContributor(dartRequest, builder),
+ NamedConstructorContributor(dartRequest, builder),
+ if (enableOverrideContributor) OverrideContributor(dartRequest, builder),
+ RedirectingContributor(dartRequest, builder),
+ StaticMemberContributor(dartRequest, builder),
+ TypeMemberContributor(dartRequest, builder),
+ if (enableUriContributor) UriContributor(dartRequest, builder),
+ VariableNameContributor(dartRequest, builder),
];
if (includedElementKinds != null) {
_addIncludedElementKinds(dartRequest);
_addIncludedSuggestionRelevanceTags(dartRequest);
} else {
- contributors.add(ImportedReferenceContributor());
+ contributors.add(
+ ImportedReferenceContributor(dartRequest, builder),
+ );
}
try {
@@ -157,7 +159,7 @@
await performance.runAsync(
'DartCompletionManager - ${contributor.runtimeType}',
(_) async {
- await contributor.computeSuggestions(dartRequest, builder);
+ await contributor.computeSuggestions();
},
);
request.checkAborted();
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
index 476125a..58e3b83 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
@@ -16,9 +16,13 @@
class ExtensionMemberContributor extends DartCompletionContributor {
late MemberSuggestionBuilder memberBuilder;
+ ExtensionMemberContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
@override
- Future<void> computeSuggestions(
- DartCompletionRequest request, SuggestionBuilder builder) async {
+ Future<void> computeSuggestions() async {
var containingLibrary = request.libraryElement;
memberBuilder = MemberSuggestionBuilder(request, builder);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart
index e722f99..d073956 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/field_formal_contributor.dart
@@ -12,9 +12,13 @@
/// already initialized. More concretely, this class produces suggestions for
/// expressions of the form `this.^` in a constructor's parameter list.
class FieldFormalContributor extends DartCompletionContributor {
+ FieldFormalContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
@override
- Future<void> computeSuggestions(
- DartCompletionRequest request, SuggestionBuilder builder) async {
+ Future<void> computeSuggestions() async {
var node = request.target.containingNode;
// TODO(brianwilkerson) We should suggest field formal parameters even if
// the user hasn't already typed the `this.` prefix, by including the
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
index e2a6c60..c10194f 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/imported_reference_contributor.dart
@@ -10,9 +10,13 @@
/// A contributor for calculating suggestions for imported top level members.
class ImportedReferenceContributor extends DartCompletionContributor {
+ ImportedReferenceContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
@override
- Future<void> computeSuggestions(
- DartCompletionRequest request, SuggestionBuilder builder) async {
+ Future<void> computeSuggestions() async {
if (!request.includeIdentifiers) {
return;
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
index 268064a..a32f625 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/keyword_contributor.dart
@@ -27,9 +27,13 @@
/// A contributor that produces suggestions based on the set of keywords that
/// are valid at the completion point.
class KeywordContributor extends DartCompletionContributor {
+ KeywordContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
@override
- Future<void> computeSuggestions(
- DartCompletionRequest request, SuggestionBuilder builder) async {
+ Future<void> computeSuggestions() async {
// Don't suggest anything right after double or integer literals.
if (request.target.isDoubleOrIntLiteral()) {
return;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
index 9434271..c3d8f57 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/label_contributor.dart
@@ -14,9 +14,13 @@
/// scope. More concretely, this class produces completions in `break` and
/// `continue` statements.
class LabelContributor extends DartCompletionContributor {
+ LabelContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
@override
- Future<void> computeSuggestions(
- DartCompletionRequest request, SuggestionBuilder builder) async {
+ Future<void> computeSuggestions() async {
var optype = (request as DartCompletionRequestImpl).opType;
// Collect suggestions from the specific child [AstNode] that contains
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
index 75ae6b50..460324a 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/library_member_contributor.dart
@@ -14,9 +14,13 @@
/// produces suggestions for expressions of the form `p.^`, where `p` is a
/// prefix.
class LibraryMemberContributor extends DartCompletionContributor {
+ LibraryMemberContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
@override
- Future<void> computeSuggestions(
- DartCompletionRequest request, SuggestionBuilder builder) async {
+ Future<void> computeSuggestions() async {
// Determine if the target looks like a library prefix.
var targetId = request.dotTarget;
if (targetId is SimpleIdentifier && !request.target.isCascade) {
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
index 0e0a8a4..5fad45d 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/library_prefix_contributor.dart
@@ -8,9 +8,13 @@
/// A contributor that produces suggestions based on the prefixes defined on
/// import directives.
class LibraryPrefixContributor extends DartCompletionContributor {
+ LibraryPrefixContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
@override
- Future<void> computeSuggestions(
- DartCompletionRequest request, SuggestionBuilder builder) async {
+ Future<void> computeSuggestions() async {
if (!request.includeIdentifiers) {
return;
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
index f14d554..e0b113d 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_library_contributor.dart
@@ -151,9 +151,13 @@
/// the library in which the completion is requested but outside the file in
/// which the completion is requested.
class LocalLibraryContributor extends DartCompletionContributor {
+ LocalLibraryContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
@override
- Future<void> computeSuggestions(
- DartCompletionRequest request, SuggestionBuilder builder) async {
+ Future<void> computeSuggestions() async {
if (!request.includeIdentifiers) {
return;
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
index b97e431..39c1dda 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/local_reference_contributor.dart
@@ -31,9 +31,13 @@
/// been shadowed by local declarations.
_VisibilityTracker visibilityTracker = _VisibilityTracker();
+ LocalReferenceContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
@override
- Future<void> computeSuggestions(
- DartCompletionRequest request, SuggestionBuilder builder) async {
+ Future<void> computeSuggestions() async {
var opType = request.opType;
AstNode? node = request.target.containingNode;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
index 0632487..c120d04 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/named_constructor_contributor.dart
@@ -12,9 +12,13 @@
/// for expressions of the form `C.^` or `C<E>.^`, where `C` is the name of a
/// class.
class NamedConstructorContributor extends DartCompletionContributor {
+ NamedConstructorContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
@override
- Future<void> computeSuggestions(
- DartCompletionRequest request, SuggestionBuilder builder) async {
+ Future<void> computeSuggestions() async {
var node = request.target.containingNode;
if (node is ConstructorName) {
var libraryElement = request.libraryElement;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
index 1cccc64..0e62f8e 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
@@ -10,10 +10,14 @@
/// A completion contributor used to suggest replacing partial identifiers
/// inside a class declaration with templates for inherited members.
-class OverrideContributor implements DartCompletionContributor {
+class OverrideContributor extends DartCompletionContributor {
+ OverrideContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
@override
- Future<void> computeSuggestions(
- DartCompletionRequest request, SuggestionBuilder builder) async {
+ Future<void> computeSuggestions() async {
var targetId = _getTargetId(request.target);
if (targetId == null) {
return;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/redirecting_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/redirecting_contributor.dart
index 3db1549..4fd743a 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/redirecting_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/redirecting_contributor.dart
@@ -11,9 +11,13 @@
/// expressions of the form `this.^` or `super.^` in a constructor's initializer
/// list or after an `=` in a factory constructor.
class RedirectingContributor extends DartCompletionContributor {
+ RedirectingContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
@override
- Future<void> computeSuggestions(
- DartCompletionRequest request, SuggestionBuilder builder) async {
+ Future<void> computeSuggestions() async {
var entity = request.target.entity;
if (entity is SimpleIdentifier) {
var parent = entity.parent;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
index 15b6c33..1faa088 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/static_member_contributor.dart
@@ -12,9 +12,13 @@
/// suggestions for expressions of the form `C.^`, where `C` is the name of a
/// class, enum, or extension.
class StaticMemberContributor extends DartCompletionContributor {
+ StaticMemberContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
@override
- Future<void> computeSuggestions(
- DartCompletionRequest request, SuggestionBuilder builder) async {
+ Future<void> computeSuggestions() async {
var library = request.libraryElement;
bool isVisible(Element element) => element.isAccessibleIn(library);
var targetId = request.dotTarget;
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
index e67d203..f15812e 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
@@ -17,9 +17,13 @@
/// expressions of the form `o.^`, where `o` is an expression denoting an
/// instance of a type.
class TypeMemberContributor extends DartCompletionContributor {
+ TypeMemberContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
@override
- Future<void> computeSuggestions(
- DartCompletionRequest request, SuggestionBuilder builder) async {
+ Future<void> computeSuggestions() async {
// Recompute the target because resolution might have changed it.
var expression = request.dotTarget;
if (expression == null ||
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart
index 227c538..cbb8337 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/uri_contributor.dart
@@ -12,9 +12,13 @@
/// A contributor that produces suggestions based on the content of the file
/// system to complete within URIs in import, export and part directives.
class UriContributor extends DartCompletionContributor {
+ UriContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
@override
- Future<void> computeSuggestions(
- DartCompletionRequest request, SuggestionBuilder builder) async {
+ Future<void> computeSuggestions() async {
var visitor = _UriSuggestionBuilder(request, builder);
request.target.containingNode.accept(visitor);
}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
index ba74ab0..97b2249 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/variable_name_contributor.dart
@@ -11,9 +11,13 @@
/// A contributor that produces suggestions for variable names based on the
/// static type of the variable.
class VariableNameContributor extends DartCompletionContributor {
+ VariableNameContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) : super(request, builder);
+
@override
- Future<void> computeSuggestions(
- DartCompletionRequest request, SuggestionBuilder builder) async {
+ Future<void> computeSuggestions() async {
var opType = request.opType;
// Collect suggestions from the specific child [AstNode] that contains
diff --git a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
index 789ff5f..8dfaa60 100644
--- a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
@@ -4,6 +4,7 @@
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/arglist_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';
@@ -109,8 +110,11 @@
}
@override
- DartCompletionContributor createContributor() {
- return ArgListContributor();
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return ArgListContributor(request, builder);
}
}
diff --git a/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart
index ea96470..e41e5a2 100644
--- a/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/combinator_contributor_test.dart
@@ -4,6 +4,7 @@
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/combinator_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -18,8 +19,11 @@
@reflectiveTest
class CombinatorContributorTest extends DartCompletionContributorTest {
@override
- DartCompletionContributor createContributor() {
- return CombinatorContributor();
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return CombinatorContributor(request, builder);
}
Future<void> test_Block_inherited_local() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
index 51ab571..8545220 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_contributor_util.dart
@@ -43,24 +43,20 @@
/// suggestions.
abstract class DartCompletionContributorTest
extends _BaseDartCompletionContributorTest {
- late DartCompletionContributor contributor;
-
@nonVirtual
@override
Future<List<CompletionSuggestion>> computeContributedSuggestions(
DartCompletionRequest request) async {
var builder = SuggestionBuilder(request);
- await contributor.computeSuggestions(request, builder);
+ var contributor = createContributor(request, builder);
+ await contributor.computeSuggestions();
return builder.suggestions.toList();
}
- DartCompletionContributor createContributor();
-
- @override
- void setUp() {
- super.setUp();
- contributor = createContributor();
- }
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ );
}
abstract class _BaseDartCompletionContributorTest extends AbstractContextTest {
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
index 8ebde10..38fb1ef 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
@@ -9,6 +9,7 @@
import 'package:analysis_server/src/services/completion/completion_performance.dart';
import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
import 'package:analysis_server/src/services/completion/dart/imported_reference_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
@@ -26,8 +27,11 @@
@reflectiveTest
class CompletionManagerTest extends DartCompletionContributorTest {
@override
- DartCompletionContributor createContributor() {
- return ImportedReferenceContributor();
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return ImportedReferenceContributor(request, builder);
}
Future<void> test_resolveDirectives() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/extension_member_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/extension_member_contributor_test.dart
index 5def996..4e72a0e 100644
--- a/pkg/analysis_server/test/services/completion/dart/extension_member_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/extension_member_contributor_test.dart
@@ -4,6 +4,7 @@
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/extension_member_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import 'completion_contributor_util.dart';
@@ -17,8 +18,11 @@
@reflectiveTest
class ExtensionMemberContributorTest extends DartCompletionContributorTest {
@override
- DartCompletionContributor createContributor() {
- return ExtensionMemberContributor();
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return ExtensionMemberContributor(request, builder);
}
Future<void> test_extended_members_inExtension_field() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
index d28095f..f38df45 100644
--- a/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/field_formal_contributor_test.dart
@@ -4,6 +4,7 @@
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/field_formal_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -18,8 +19,11 @@
@reflectiveTest
class FieldFormalContributorTest extends DartCompletionContributorTest {
@override
- DartCompletionContributor createContributor() {
- return FieldFormalContributor();
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return FieldFormalContributor(request, builder);
}
/// https://github.com/dart-lang/sdk/issues/39028
diff --git a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
index 05f16bd..b1cfe12 100644
--- a/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/imported_reference_contributor_test.dart
@@ -5,6 +5,7 @@
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/imported_reference_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -22,8 +23,11 @@
bool get isNullExpectedReturnTypeConsideredDynamic => false;
@override
- DartCompletionContributor createContributor() {
- return ImportedReferenceContributor();
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return ImportedReferenceContributor(request, builder);
}
}
diff --git a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
index 1673cfd..1d96cae 100644
--- a/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/keyword_contributor_test.dart
@@ -4,6 +4,7 @@
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/keyword_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
@@ -443,8 +444,11 @@
}
@override
- DartCompletionContributor createContributor() {
- return KeywordContributor();
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return KeywordContributor(request, builder);
}
/// Return `true` if the given [feature] is enabled.
diff --git a/pkg/analysis_server/test/services/completion/dart/label_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/label_contributor_test.dart
index 9204f6d..ad09ba3 100644
--- a/pkg/analysis_server/test/services/completion/dart/label_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/label_contributor_test.dart
@@ -5,6 +5,7 @@
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/label_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -33,8 +34,11 @@
}
@override
- DartCompletionContributor createContributor() {
- return LabelContributor();
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return LabelContributor(request, builder);
}
Future<void> test_break_ignores_outer_functions_using_closure() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/library_member_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/library_member_contributor_test.dart
index 023cef5..d4a3f76 100644
--- a/pkg/analysis_server/test/services/completion/dart/library_member_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/library_member_contributor_test.dart
@@ -4,6 +4,7 @@
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/library_member_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -18,8 +19,11 @@
@reflectiveTest
class LibraryMemberContributorTest extends DartCompletionContributorTest {
@override
- DartCompletionContributor createContributor() {
- return LibraryMemberContributor();
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return LibraryMemberContributor(request, builder);
}
Future<void> test_extension() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/library_prefix_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/library_prefix_contributor_test.dart
index ae303ec..96ecfce 100644
--- a/pkg/analysis_server/test/services/completion/dart/library_prefix_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/library_prefix_contributor_test.dart
@@ -5,6 +5,7 @@
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/library_prefix_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -34,8 +35,11 @@
}
@override
- DartCompletionContributor createContributor() {
- return LibraryPrefixContributor();
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return LibraryPrefixContributor(request, builder);
}
Future<void> test_Block() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart
index 6417557..d5cfe06 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_library_contributor_test.dart
@@ -4,6 +4,7 @@
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/local_library_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -18,8 +19,11 @@
@reflectiveTest
class LocalLibraryContributorTest extends DartCompletionContributorTest {
@override
- DartCompletionContributor createContributor() {
- return LocalLibraryContributor();
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return LocalLibraryContributor(request, builder);
}
Future<void> test_partFile_Constructor() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
index 243cdb5..25888ec 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
@@ -5,6 +5,7 @@
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/local_reference_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -22,8 +23,11 @@
bool get isNullExpectedReturnTypeConsideredDynamic => false;
@override
- DartCompletionContributor createContributor() {
- return LocalReferenceContributor();
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return LocalReferenceContributor(request, builder);
}
Future<void> test_ArgDefaults_function() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/named_constructor_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/named_constructor_contributor_test.dart
index 0e35485..2c3ed18 100644
--- a/pkg/analysis_server/test/services/completion/dart/named_constructor_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/named_constructor_contributor_test.dart
@@ -4,6 +4,7 @@
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/named_constructor_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -39,8 +40,11 @@
}
@override
- DartCompletionContributor createContributor() {
- return NamedConstructorContributor();
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return NamedConstructorContributor(request, builder);
}
Future<void> test_ConstructorName_importedClass() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart
index 7b27e88..3178bc4 100644
--- a/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart
@@ -4,6 +4,7 @@
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/override_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -17,8 +18,11 @@
@reflectiveTest
class OverrideContributorTest extends DartCompletionContributorTest {
@override
- DartCompletionContributor createContributor() {
- return OverrideContributor();
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return OverrideContributor(request, builder);
}
Future<void> test_alreadyOverridden() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/static_member_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/static_member_contributor_test.dart
index 0cecf86..1c6e558 100644
--- a/pkg/analysis_server/test/services/completion/dart/static_member_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/static_member_contributor_test.dart
@@ -4,6 +4,7 @@
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/static_member_contributor.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -18,8 +19,11 @@
@reflectiveTest
class StaticMemberContributorTest extends DartCompletionContributorTest {
@override
- DartCompletionContributor createContributor() {
- return StaticMemberContributor();
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return StaticMemberContributor(request, builder);
}
Future<void> test_class_static_notPrivate() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
index c9d8574..8633ece 100644
--- a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analysis_server/src/services/completion/dart/type_member_contributor.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:test/test.dart';
@@ -48,8 +49,11 @@
}
@override
- DartCompletionContributor createContributor() {
- return TypeMemberContributor();
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return TypeMemberContributor(request, builder);
}
Future<void> test_ArgDefaults_method() async {
diff --git a/pkg/analysis_server/test/services/completion/dart/uri_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/uri_contributor_test.dart
index 0620fbf..f2e442c 100644
--- a/pkg/analysis_server/test/services/completion/dart/uri_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/uri_contributor_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analysis_server/src/services/completion/dart/uri_contributor.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
@@ -25,8 +26,11 @@
String get testPackageTestPath => '$testPackageRootPath/test';
@override
- DartCompletionContributor createContributor() {
- return UriContributor();
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return UriContributor(request, builder);
}
Future<void> test_after_import() async {
@@ -550,8 +554,11 @@
@reflectiveTest
class UriContributorWindowsTest extends DartCompletionContributorTest {
@override
- DartCompletionContributor createContributor() {
- return UriContributor();
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return UriContributor(request, builder);
}
@override
diff --git a/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
index 3b75a53..97bac2b 100644
--- a/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/variable_name_contributor_test.dart
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
+import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
import 'package:analysis_server/src/services/completion/dart/variable_name_contributor.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -18,8 +19,11 @@
@reflectiveTest
class VariableNameContributorTest extends DartCompletionContributorTest {
@override
- DartCompletionContributor createContributor() {
- return VariableNameContributor();
+ DartCompletionContributor createContributor(
+ DartCompletionRequest request,
+ SuggestionBuilder builder,
+ ) {
+ return VariableNameContributor(request, builder);
}
Future<void> test_ExpressionStatement_dont_suggest_type() async {
diff --git a/pkg/analyzer/lib/src/generated/ffi_verifier.dart b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
index 033f4c4..926b8da 100644
--- a/pkg/analyzer/lib/src/generated/ffi_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/ffi_verifier.dart
@@ -42,6 +42,8 @@
'Double',
];
+ static const _primitiveBoolNativeType = 'Bool';
+
static const _structClassName = 'Struct';
static const _unionClassName = 'Union';
@@ -432,6 +434,8 @@
return true;
case _PrimitiveDartType.int:
return true;
+ case _PrimitiveDartType.bool:
+ return true;
case _PrimitiveDartType.void_:
return false;
case _PrimitiveDartType.handle:
@@ -490,6 +494,7 @@
return allowHandle;
case _PrimitiveDartType.double:
case _PrimitiveDartType.int:
+ case _PrimitiveDartType.bool:
return true;
case _PrimitiveDartType.none:
// These are the cases below.
@@ -560,6 +565,9 @@
if (_primitiveDoubleNativeTypes.contains(name)) {
return _PrimitiveDartType.double;
}
+ if (name == _primitiveBoolNativeType) {
+ return _PrimitiveDartType.bool;
+ }
if (name == 'Void') {
return _PrimitiveDartType.void_;
}
@@ -580,6 +588,8 @@
return _PrimitiveDartType.int;
} else if (_primitiveDoubleNativeTypes.contains(name)) {
return _PrimitiveDartType.double;
+ } else if (_primitiveBoolNativeType == name) {
+ return _PrimitiveDartType.bool;
}
}
return _PrimitiveDartType.none;
@@ -738,6 +748,8 @@
return dartType.isDartCoreInt;
} else if (nativeReturnType == _PrimitiveDartType.double) {
return dartType.isDartCoreDouble;
+ } else if (nativeReturnType == _PrimitiveDartType.bool) {
+ return dartType.isDartCoreBool;
} else if (nativeReturnType == _PrimitiveDartType.void_) {
return dartType.isVoid;
} else if (nativeReturnType == _PrimitiveDartType.handle) {
@@ -827,6 +839,8 @@
_validateAnnotations(fieldType, annotations, _PrimitiveDartType.int);
} else if (declaredType.isDartCoreDouble) {
_validateAnnotations(fieldType, annotations, _PrimitiveDartType.double);
+ } else if (declaredType.isDartCoreBool) {
+ _validateAnnotations(fieldType, annotations, _PrimitiveDartType.bool);
} else if (declaredType.isPointer) {
_validateNoAnnotations(annotations);
} else if (declaredType.isArray) {
@@ -1162,6 +1176,7 @@
enum _PrimitiveDartType {
double,
int,
+ bool,
void_,
handle,
none,
@@ -1337,6 +1352,8 @@
return false;
} else if (declaredType.isDartCoreDouble) {
return false;
+ } else if (declaredType.isDartCoreBool) {
+ return false;
} else if (declaredType.isPointer) {
return false;
} else if (declaredType.isCompoundSubtype) {
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect
index f15273b..1d8965d 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.1.expect
@@ -43,6 +43,9 @@
ffi::AllocatorAlloc,
ffi::Array,
ffi::ArrayArray,
+ ffi::Bool,
+ ffi::BoolArray,
+ ffi::BoolPointer,
ffi::DartRepresentationOf,
ffi::Dart_CObject,
ffi::Double,
@@ -113,6 +116,9 @@
ffi::AllocatorAlloc,
ffi::Array,
ffi::ArrayArray,
+ ffi::Bool,
+ ffi::BoolArray,
+ ffi::BoolPointer,
ffi::DartRepresentationOf,
ffi::Dart_CObject,
ffi::Double,
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect
index 0b32258..6bf1e19 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_50_ffi.yaml.world.2.expect
@@ -43,6 +43,9 @@
ffi::AllocatorAlloc,
ffi::Array,
ffi::ArrayArray,
+ ffi::Bool,
+ ffi::BoolArray,
+ ffi::BoolPointer,
ffi::DartRepresentationOf,
ffi::Dart_CObject,
ffi::Double,
@@ -113,6 +116,9 @@
ffi::AllocatorAlloc,
ffi::Array,
ffi::ArrayArray,
+ ffi::Bool,
+ ffi::BoolArray,
+ ffi::BoolPointer,
ffi::DartRepresentationOf,
ffi::Dart_CObject,
ffi::Double,
diff --git a/pkg/vm/lib/transformations/ffi.dart b/pkg/vm/lib/transformations/ffi.dart
index c39a22f..dc51195 100644
--- a/pkg/vm/lib/transformations/ffi.dart
+++ b/pkg/vm/lib/transformations/ffi.dart
@@ -39,6 +39,7 @@
kOpaque,
kStruct,
kHandle,
+ kBool,
}
const Set<NativeType> nativeIntTypes = <NativeType>{
@@ -75,6 +76,7 @@
NativeType.kOpaque: 'Opaque',
NativeType.kStruct: 'Struct',
NativeType.kHandle: 'Handle',
+ NativeType.kBool: 'Bool',
};
const int UNKNOWN = 0;
@@ -102,6 +104,7 @@
NativeType.kOpaque: UNKNOWN,
NativeType.kStruct: UNKNOWN,
NativeType.kHandle: WORD_SIZE,
+ NativeType.kBool: 1,
};
/// The struct layout in various ABIs.
@@ -178,6 +181,7 @@
/// Load, store, and elementAt are rewired to their static type for these types.
const List<NativeType> optimizedTypes = [
+ NativeType.kBool,
NativeType.kInt8,
NativeType.kInt16,
NativeType.kInt32,
@@ -210,6 +214,7 @@
final Class objectClass;
final Class intClass;
final Class doubleClass;
+ final Class boolClass;
final Class listClass;
final Class typeClass;
final Procedure unsafeCastMethod;
@@ -319,6 +324,7 @@
objectClass = coreTypes.objectClass,
intClass = coreTypes.intClass,
doubleClass = coreTypes.doubleClass,
+ boolClass = coreTypes.boolClass,
listClass = coreTypes.listClass,
typeClass = coreTypes.typeClass,
unsafeCastMethod =
@@ -514,6 +520,7 @@
/// [IntPtr] -> [int]
/// [Double] -> [double]
/// [Float] -> [double]
+ /// [Bool] -> [bool]
/// [Void] -> [void]
/// [Pointer]<T> -> [Pointer]<T>
/// T extends [Pointer] -> T
@@ -555,6 +562,9 @@
if (nativeType_ == NativeType.kFloat || nativeType_ == NativeType.kDouble) {
return InterfaceType(doubleClass, Nullability.legacy);
}
+ if (nativeType_ == NativeType.kBool) {
+ return InterfaceType(boolClass, Nullability.legacy);
+ }
if (nativeType_ == NativeType.kVoid) {
return VoidType();
}
diff --git a/runtime/bin/ffi_test/ffi_test_functions_generated.cc b/runtime/bin/ffi_test/ffi_test_functions_generated.cc
index 647c2ae..dc17bb0 100644
--- a/runtime/bin/ffi_test/ffi_test_functions_generated.cc
+++ b/runtime/bin/ffi_test/ffi_test_functions_generated.cc
@@ -35,6 +35,10 @@
CHECK(((EXPECTED * 0.99) <= (ACTUAL) && (EXPECTED * 1.01) >= (ACTUAL)) || \
((EXPECTED * 0.99) >= (ACTUAL) && (EXPECTED * 1.01) <= (ACTUAL)))
+struct Struct1ByteBool {
+ bool a0;
+};
+
struct Struct1ByteInt {
int8_t a0;
};
@@ -113,6 +117,19 @@
int8_t a1;
};
+struct Struct10BytesHomogeneousBool {
+ bool a0;
+ bool a1;
+ bool a2;
+ bool a3;
+ bool a4;
+ bool a5;
+ bool a6;
+ bool a7;
+ bool a8;
+ bool a9;
+};
+
struct Struct12BytesHomogeneousFloat {
float a0;
float a1;
@@ -419,6 +436,10 @@
uint8_t a0[8];
};
+struct Struct10BytesInlineArrayBool {
+ bool a0[10];
+};
+
struct StructInlineArrayIrregular {
Struct3BytesInt2ByteAligned a0[2];
uint8_t a1;
@@ -4746,6 +4767,134 @@
}
// Used for testing structs and unions by value.
+// Passing bools and a struct with bools.
+// Exhausts the registers to test bools and the bool struct alignment on the
+// stack.
+DART_EXPORT int32_t PassUint8Boolx9Struct10BytesHomogeneousBoolBool(
+ uint8_t a0,
+ bool a1,
+ bool a2,
+ bool a3,
+ bool a4,
+ bool a5,
+ bool a6,
+ bool a7,
+ bool a8,
+ bool a9,
+ Struct10BytesHomogeneousBool a10,
+ bool a11) {
+ std::cout << "PassUint8Boolx9Struct10BytesHomogeneousBoolBool"
+ << "(" << static_cast<int>(a0) << ", " << a1 << ", " << a2 << ", "
+ << a3 << ", " << a4 << ", " << a5 << ", " << a6 << ", " << a7
+ << ", " << a8 << ", " << a9 << ", (" << a10.a0 << ", " << a10.a1
+ << ", " << a10.a2 << ", " << a10.a3 << ", " << a10.a4 << ", "
+ << a10.a5 << ", " << a10.a6 << ", " << a10.a7 << ", " << a10.a8
+ << ", " << a10.a9 << "), " << a11 << ")"
+ << "\n";
+
+ int32_t result = 0;
+
+ result += a0;
+ result += a1 ? 1 : 0;
+ result += a2 ? 1 : 0;
+ result += a3 ? 1 : 0;
+ result += a4 ? 1 : 0;
+ result += a5 ? 1 : 0;
+ result += a6 ? 1 : 0;
+ result += a7 ? 1 : 0;
+ result += a8 ? 1 : 0;
+ result += a9 ? 1 : 0;
+ result += a10.a0 ? 1 : 0;
+ result += a10.a1 ? 1 : 0;
+ result += a10.a2 ? 1 : 0;
+ result += a10.a3 ? 1 : 0;
+ result += a10.a4 ? 1 : 0;
+ result += a10.a5 ? 1 : 0;
+ result += a10.a6 ? 1 : 0;
+ result += a10.a7 ? 1 : 0;
+ result += a10.a8 ? 1 : 0;
+ result += a10.a9 ? 1 : 0;
+ result += a11 ? 1 : 0;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs and unions by value.
+// Passing bools and a struct with bools.
+// Exhausts the registers to test bools and the bool struct alignment on the
+// stack.
+DART_EXPORT int32_t PassUint8Boolx9Struct10BytesInlineArrayBoolBool(
+ uint8_t a0,
+ bool a1,
+ bool a2,
+ bool a3,
+ bool a4,
+ bool a5,
+ bool a6,
+ bool a7,
+ bool a8,
+ bool a9,
+ Struct10BytesInlineArrayBool a10,
+ bool a11) {
+ std::cout << "PassUint8Boolx9Struct10BytesInlineArrayBoolBool"
+ << "(" << static_cast<int>(a0) << ", " << a1 << ", " << a2 << ", "
+ << a3 << ", " << a4 << ", " << a5 << ", " << a6 << ", " << a7
+ << ", " << a8 << ", " << a9 << ", ([" << a10.a0[0] << ", "
+ << a10.a0[1] << ", " << a10.a0[2] << ", " << a10.a0[3] << ", "
+ << a10.a0[4] << ", " << a10.a0[5] << ", " << a10.a0[6] << ", "
+ << a10.a0[7] << ", " << a10.a0[8] << ", " << a10.a0[9] << "]), "
+ << a11 << ")"
+ << "\n";
+
+ int32_t result = 0;
+
+ result += a0;
+ result += a1 ? 1 : 0;
+ result += a2 ? 1 : 0;
+ result += a3 ? 1 : 0;
+ result += a4 ? 1 : 0;
+ result += a5 ? 1 : 0;
+ result += a6 ? 1 : 0;
+ result += a7 ? 1 : 0;
+ result += a8 ? 1 : 0;
+ result += a9 ? 1 : 0;
+ result += a10.a0[0] ? 1 : 0;
+ result += a10.a0[1] ? 1 : 0;
+ result += a10.a0[2] ? 1 : 0;
+ result += a10.a0[3] ? 1 : 0;
+ result += a10.a0[4] ? 1 : 0;
+ result += a10.a0[5] ? 1 : 0;
+ result += a10.a0[6] ? 1 : 0;
+ result += a10.a0[7] ? 1 : 0;
+ result += a10.a0[8] ? 1 : 0;
+ result += a10.a0[9] ? 1 : 0;
+ result += a11 ? 1 : 0;
+
+ std::cout << "result = " << result << "\n";
+
+ return result;
+}
+
+// Used for testing structs and unions by value.
+// Returning a bool.
+DART_EXPORT bool PassUint8Struct1ByteBool(uint8_t a0, Struct1ByteBool a1) {
+ std::cout << "PassUint8Struct1ByteBool"
+ << "(" << static_cast<int>(a0) << ", (" << a1.a0 << "))"
+ << "\n";
+
+ uint64_t result = 0;
+
+ result += a0;
+ result += a1.a0 ? 1 : 0;
+
+ std::cout << "result = " << result << "\n";
+
+ return result % 2 != 0;
+}
+
+// Used for testing structs and unions by value.
// Smallest struct with data.
DART_EXPORT Struct1ByteInt ReturnStruct1ByteInt(int8_t a0) {
std::cout << "ReturnStruct1ByteInt"
@@ -12261,6 +12410,215 @@
}
// Used for testing structs and unions by value.
+// Passing bools and a struct with bools.
+// Exhausts the registers to test bools and the bool struct alignment on the
+// stack.
+DART_EXPORT intptr_t TestPassUint8Boolx9Struct10BytesHomogeneousBoolBool(
+ // NOLINTNEXTLINE(whitespace/parens)
+ int32_t (*f)(uint8_t a0,
+ bool a1,
+ bool a2,
+ bool a3,
+ bool a4,
+ bool a5,
+ bool a6,
+ bool a7,
+ bool a8,
+ bool a9,
+ Struct10BytesHomogeneousBool a10,
+ bool a11)) {
+ uint8_t a0;
+ bool a1;
+ bool a2;
+ bool a3;
+ bool a4;
+ bool a5;
+ bool a6;
+ bool a7;
+ bool a8;
+ bool a9;
+ Struct10BytesHomogeneousBool a10 = {};
+ bool a11;
+
+ a0 = 1;
+ a1 = false;
+ a2 = true;
+ a3 = false;
+ a4 = true;
+ a5 = false;
+ a6 = true;
+ a7 = false;
+ a8 = true;
+ a9 = false;
+ a10.a0 = true;
+ a10.a1 = false;
+ a10.a2 = true;
+ a10.a3 = false;
+ a10.a4 = true;
+ a10.a5 = false;
+ a10.a6 = true;
+ a10.a7 = false;
+ a10.a8 = true;
+ a10.a9 = false;
+ a11 = true;
+
+ std::cout << "Calling TestPassUint8Boolx9Struct10BytesHomogeneousBoolBool("
+ << "(" << static_cast<int>(a0) << ", " << a1 << ", " << a2 << ", "
+ << a3 << ", " << a4 << ", " << a5 << ", " << a6 << ", " << a7
+ << ", " << a8 << ", " << a9 << ", (" << a10.a0 << ", " << a10.a1
+ << ", " << a10.a2 << ", " << a10.a3 << ", " << a10.a4 << ", "
+ << a10.a5 << ", " << a10.a6 << ", " << a10.a7 << ", " << a10.a8
+ << ", " << a10.a9 << "), " << a11 << ")"
+ << ")\n";
+
+ int32_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_EQ(11, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
+
+ CHECK_EQ(0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
+
+ CHECK_EQ(0, result);
+
+ return 0;
+}
+
+// Used for testing structs and unions by value.
+// Passing bools and a struct with bools.
+// Exhausts the registers to test bools and the bool struct alignment on the
+// stack.
+DART_EXPORT intptr_t TestPassUint8Boolx9Struct10BytesInlineArrayBoolBool(
+ // NOLINTNEXTLINE(whitespace/parens)
+ int32_t (*f)(uint8_t a0,
+ bool a1,
+ bool a2,
+ bool a3,
+ bool a4,
+ bool a5,
+ bool a6,
+ bool a7,
+ bool a8,
+ bool a9,
+ Struct10BytesInlineArrayBool a10,
+ bool a11)) {
+ uint8_t a0;
+ bool a1;
+ bool a2;
+ bool a3;
+ bool a4;
+ bool a5;
+ bool a6;
+ bool a7;
+ bool a8;
+ bool a9;
+ Struct10BytesInlineArrayBool a10 = {};
+ bool a11;
+
+ a0 = 1;
+ a1 = false;
+ a2 = true;
+ a3 = false;
+ a4 = true;
+ a5 = false;
+ a6 = true;
+ a7 = false;
+ a8 = true;
+ a9 = false;
+ a10.a0[0] = true;
+ a10.a0[1] = false;
+ a10.a0[2] = true;
+ a10.a0[3] = false;
+ a10.a0[4] = true;
+ a10.a0[5] = false;
+ a10.a0[6] = true;
+ a10.a0[7] = false;
+ a10.a0[8] = true;
+ a10.a0[9] = false;
+ a11 = true;
+
+ std::cout << "Calling TestPassUint8Boolx9Struct10BytesInlineArrayBoolBool("
+ << "(" << static_cast<int>(a0) << ", " << a1 << ", " << a2 << ", "
+ << a3 << ", " << a4 << ", " << a5 << ", " << a6 << ", " << a7
+ << ", " << a8 << ", " << a9 << ", ([" << a10.a0[0] << ", "
+ << a10.a0[1] << ", " << a10.a0[2] << ", " << a10.a0[3] << ", "
+ << a10.a0[4] << ", " << a10.a0[5] << ", " << a10.a0[6] << ", "
+ << a10.a0[7] << ", " << a10.a0[8] << ", " << a10.a0[9] << "]), "
+ << a11 << ")"
+ << ")\n";
+
+ int32_t result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_EQ(11, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
+
+ CHECK_EQ(0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
+
+ CHECK_EQ(0, result);
+
+ return 0;
+}
+
+// Used for testing structs and unions by value.
+// Returning a bool.
+DART_EXPORT intptr_t TestPassUint8Struct1ByteBool(
+ // NOLINTNEXTLINE(whitespace/parens)
+ bool (*f)(uint8_t a0, Struct1ByteBool a1)) {
+ uint8_t a0;
+ Struct1ByteBool a1 = {};
+
+ a0 = 1;
+ a1.a0 = false;
+
+ std::cout << "Calling TestPassUint8Struct1ByteBool("
+ << "(" << static_cast<int>(a0) << ", (" << a1.a0 << "))"
+ << ")\n";
+
+ bool result = f(a0, a1);
+
+ std::cout << "result = " << result << "\n";
+
+ CHECK_APPROX(1, result);
+
+ // Pass argument that will make the Dart callback throw.
+ a0 = 42;
+
+ result = f(a0, a1);
+
+ CHECK_APPROX(0.0, result);
+
+ // Pass argument that will make the Dart callback return null.
+ a0 = 84;
+
+ result = f(a0, a1);
+
+ CHECK_APPROX(0.0, result);
+
+ return 0;
+}
+
+// Used for testing structs and unions by value.
// Smallest struct with data.
DART_EXPORT intptr_t TestReturnStruct1ByteInt(
// NOLINTNEXTLINE(whitespace/parens)
diff --git a/runtime/bin/security_context.cc b/runtime/bin/security_context.cc
index ee431c8..95028ee 100644
--- a/runtime/bin/security_context.cc
+++ b/runtime/bin/security_context.cc
@@ -755,12 +755,12 @@
}
static Dart_Handle ASN1TimeToMilliseconds(ASN1_TIME* aTime) {
- ASN1_UTCTIME* epoch_start = M_ASN1_UTCTIME_new();
+ ASN1_UTCTIME* epoch_start = ASN1_UTCTIME_new();
ASN1_UTCTIME_set_string(epoch_start, "700101000000Z");
int days;
int seconds;
int result = ASN1_TIME_diff(&days, &seconds, epoch_start, aTime);
- M_ASN1_UTCTIME_free(epoch_start);
+ ASN1_UTCTIME_free(epoch_start);
if (result != 1) {
// TODO(whesse): Propagate an error to Dart.
Syslog::PrintErr("ASN1Time error %d\n", result);
diff --git a/runtime/tools/ffi/sdk_lib_ffi_generator.dart b/runtime/tools/ffi/sdk_lib_ffi_generator.dart
index 3b68036..d44c2ec 100644
--- a/runtime/tools/ffi/sdk_lib_ffi_generator.dart
+++ b/runtime/tools/ffi/sdk_lib_ffi_generator.dart
@@ -27,6 +27,7 @@
Config("IntPtr", "int", kDoNotEmit, kIntPtrElementSize),
Config("Float", "double", "Float32List", 4),
Config("Double", "double", "Float64List", 8),
+ Config("Bool", "bool", kDoNotEmit, 1),
];
//
@@ -92,8 +93,12 @@
}
} else if (nativeType == "Float") {
property = "float";
- } else {
+ } else if (nativeType == "Double") {
property = "double";
+ } else if (nativeType == "Bool") {
+ property = "bool";
+ } else {
+ throw "Unexpected type: $nativeType";
}
const platformIntPtr = """
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 377964b..fd3faae 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -206,6 +206,7 @@
#if defined(DEBUG)
for (intptr_t i = 0; i < class_array.Length(); i++) {
cls ^= class_array.At(i);
+ // Recognized a new class, but forgot to add @pragma('vm:entrypoint')?
ASSERT(cls.is_declaration_loaded());
}
#endif
diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h
index 8d17bea..bc52316 100644
--- a/runtime/vm/class_id.h
+++ b/runtime/vm/class_id.h
@@ -156,7 +156,8 @@
#define CLASS_LIST_FFI_TYPE_MARKER(V) \
CLASS_LIST_FFI_NUMERIC(V) \
V(Void) \
- V(Handle)
+ V(Handle) \
+ V(Bool)
#define CLASS_LIST_FFI(V) \
V(NativeFunction) \
@@ -404,9 +405,9 @@
case kPointerCid:
case kDynamicLibraryCid:
#define CASE_FFI_CID(name) case kFfi##name##Cid:
- CLASS_LIST_FFI(CASE_FFI_CID)
+ CLASS_LIST_FFI(CASE_FFI_CID)
#undef CASE_FFI_CID
- return true;
+ return true;
default:
return false;
}
diff --git a/runtime/vm/compiler/ffi/callback.cc b/runtime/vm/compiler/ffi/callback.cc
index d1d9b67..ef58014 100644
--- a/runtime/vm/compiler/ffi/callback.cc
+++ b/runtime/vm/compiler/ffi/callback.cc
@@ -52,7 +52,8 @@
//
// Exceptional return values currently cannot be pointers because we don't
// have constant pointers.
- ASSERT(exceptional_return.IsNull() || exceptional_return.IsNumber());
+ ASSERT(exceptional_return.IsNull() || exceptional_return.IsNumber() ||
+ exceptional_return.IsBool());
if (!exceptional_return.IsSmi() && exceptional_return.IsNew()) {
function.SetFfiCallbackExceptionalReturn(Instance::Handle(
zone, exceptional_return.CopyShallowToOldSpace(thread)));
diff --git a/runtime/vm/compiler/ffi/marshaller.h b/runtime/vm/compiler/ffi/marshaller.h
index 9d9f3cc..fc29f67 100644
--- a/runtime/vm/compiler/ffi/marshaller.h
+++ b/runtime/vm/compiler/ffi/marshaller.h
@@ -109,6 +109,10 @@
return AbstractType::Handle(zone_, CType(arg_index)).type_class_id() ==
kFfiHandleCid;
}
+ bool IsBool(intptr_t arg_index) const {
+ return AbstractType::Handle(zone_, CType(arg_index)).type_class_id() ==
+ kFfiBoolCid;
+ }
bool IsCompound(intptr_t arg_index) const {
const auto& type = AbstractType::Handle(zone_, CType(arg_index));
diff --git a/runtime/vm/compiler/ffi/native_type.cc b/runtime/vm/compiler/ffi/native_type.cc
index 125fa3e..6dfaeb7 100644
--- a/runtime/vm/compiler/ffi/native_type.cc
+++ b/runtime/vm/compiler/ffi/native_type.cc
@@ -357,6 +357,7 @@
return kInt16;
case kFfiInt32Cid:
return kInt32;
+ case kFfiBoolCid:
case kFfiUint8Cid:
return kUint8;
case kFfiUint16Cid:
diff --git a/runtime/vm/compiler/ffi/native_type_vm_test.cc b/runtime/vm/compiler/ffi/native_type_vm_test.cc
index 52f0835..196ae4c 100644
--- a/runtime/vm/compiler/ffi/native_type_vm_test.cc
+++ b/runtime/vm/compiler/ffi/native_type_vm_test.cc
@@ -25,6 +25,28 @@
EXPECT(native_type.IsPrimitive());
}
+// In all calling conventions `bool` behaves as `uint8_t` when it comes to:
+// - size
+// - alignment in structs
+// - alignment on stack
+// - upper bytes in cpu registers.
+ISOLATE_UNIT_TEST_CASE(Ffi_NativeType_Bool_FromAbstractType) {
+ Zone* Z = thread->zone();
+
+ const auto& ffi_library = Library::Handle(Library::FfiLibrary());
+ const auto& bool_class = Class::Handle(GetClass(ffi_library, "Bool"));
+ const auto& bool_type = Type::Handle(bool_class.DeclarationType());
+ const auto& bool_native_type = NativeType::FromAbstractType(Z, bool_type);
+
+ const auto& uint8_native_type = *new (Z) NativePrimitiveType(kUint8);
+
+ EXPECT(bool_native_type.Equals(uint8_native_type));
+ EXPECT_EQ(1, bool_native_type.SizeInBytes());
+ EXPECT_STREQ("uint8", bool_native_type.ToCString());
+ EXPECT(bool_native_type.IsInt());
+ EXPECT(bool_native_type.IsPrimitive());
+}
+
// Test that we construct `NativeType` correctly from `Type`.
ISOLATE_UNIT_TEST_CASE(Ffi_NativeType_Struct_FromAbstractType) {
Zone* Z = thread->zone();
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index ab29403..091658f 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -3959,6 +3959,48 @@
return Fragment(unbox);
}
+// TODO(http://dartbug.com/47487): Support unboxed output value.
+Fragment FlowGraphBuilder::BoolToInt() {
+ // TODO(http://dartbug.com/36855) Build IfThenElseInstr, instead of letting
+ // the optimizer turn this into that.
+
+ LocalVariable* expression_temp = parsed_function_->expression_temp_var();
+
+ Fragment instructions;
+ TargetEntryInstr* is_true;
+ TargetEntryInstr* is_false;
+
+ instructions += BranchIfTrue(&is_true, &is_false);
+ JoinEntryInstr* join = BuildJoinEntry();
+
+ {
+ Fragment store_1(is_true);
+ store_1 += IntConstant(1);
+ store_1 += StoreLocal(TokenPosition::kNoSource, expression_temp);
+ store_1 += Drop();
+ store_1 += Goto(join);
+ }
+
+ {
+ Fragment store_0(is_false);
+ store_0 += IntConstant(0);
+ store_0 += StoreLocal(TokenPosition::kNoSource, expression_temp);
+ store_0 += Drop();
+ store_0 += Goto(join);
+ }
+
+ instructions = Fragment(instructions.entry, join);
+ instructions += LoadLocal(expression_temp);
+ return instructions;
+}
+
+Fragment FlowGraphBuilder::IntToBool() {
+ Fragment body;
+ body += IntConstant(0);
+ body += StrictCompare(Token::kNE_STRICT);
+ return body;
+}
+
Fragment FlowGraphBuilder::NativeReturn(
const compiler::ffi::CallbackMarshaller& marshaller) {
auto* instr = new (Z)
@@ -4314,6 +4356,10 @@
}
body += Box(marshaller.RepInDart(arg_index));
+
+ if (marshaller.IsBool(arg_index)) {
+ body += IntToBool();
+ }
}
return body;
}
@@ -4332,6 +4378,10 @@
} else if (marshaller.IsHandle(arg_index)) {
body += WrapHandle(api_local_scope);
} else {
+ if (marshaller.IsBool(arg_index)) {
+ body += BoolToInt();
+ }
+
body += UnboxTruncate(marshaller.RepInDart(arg_index));
}
@@ -4388,6 +4438,7 @@
}
function_body += LoadLocal(
parsed_function_->ParameterVariable(kFirstArgumentParameterOffset + i));
+ // TODO(http://dartbug.com/47486): Support entry without checking for null.
// Check for 'null'.
function_body += CheckNullOptimized(
String::ZoneHandle(
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index 20c5b77c..7c9154d 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -271,6 +271,12 @@
// target representation.
Fragment UnboxTruncate(Representation to);
+ // Converts a true to 1 and false to 0.
+ Fragment BoolToInt();
+
+ // Converts 0 to false and the rest to true.
+ Fragment IntToBool();
+
// Creates an ffi.Pointer holding a given address (TOS).
Fragment FfiPointerFromAddress(const Type& result_type);
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 63ce112..ee81b99 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -109,6 +109,7 @@
V(ExternalOneByteString, "_ExternalOneByteString") \
V(ExternalTwoByteString, "_ExternalTwoByteString") \
V(FallThroughError, "FallThroughError") \
+ V(FfiBool, "Bool") \
V(FfiCallback, "_FfiCallback") \
V(FfiDouble, "Double") \
V(FfiDynamicLibrary, "DynamicLibrary") \
diff --git a/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart b/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart
index cc7831b..426a170 100644
--- a/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart
+++ b/sdk/lib/_internal/vm/lib/ffi_native_type_patch.dart
@@ -69,6 +69,10 @@
@patch
@pragma("vm:entry-point")
+abstract class Bool extends NativeType {}
+
+@patch
+@pragma("vm:entry-point")
abstract class Void extends NativeType {}
@patch
diff --git a/sdk/lib/_internal/vm/lib/ffi_patch.dart b/sdk/lib/_internal/vm/lib/ffi_patch.dart
index b3faeab..3f7276b 100644
--- a/sdk/lib/_internal/vm/lib/ffi_patch.dart
+++ b/sdk/lib/_internal/vm/lib/ffi_patch.dart
@@ -313,6 +313,15 @@
external void _storePointer<S extends NativeType>(
Object typedDataBase, int offsetInBytes, Pointer<S> value);
+bool _loadBool(Object typedDataBase, int offsetInBytes) =>
+ _loadUint8(typedDataBase, offsetInBytes) != 0;
+
+void _storeBool(Object typedDataBase, int offsetInBytes, bool value) =>
+ _storeUint8(typedDataBase, offsetInBytes, value ? 1 : 0);
+
+Pointer<Bool> _elementAtBool(Pointer<Bool> pointer, int index) =>
+ Pointer.fromAddress(pointer.address + 1 * index);
+
Pointer<Int8> _elementAtInt8(Pointer<Int8> pointer, int index) =>
Pointer.fromAddress(pointer.address + 1 * index);
@@ -548,6 +557,20 @@
Float64List asTypedList(int elements) => _asExternalTypedData(this, elements);
}
+extension BoolPointer on Pointer<Bool> {
+ @patch
+ bool get value => _loadBool(this, 0);
+
+ @patch
+ set value(bool value) => _storeBool(this, 0, value);
+
+ @patch
+ bool operator [](int index) => _loadBool(this, index);
+
+ @patch
+ operator []=(int index, bool value) => _storeBool(this, index, value);
+}
+
extension Int8Array on Array<Int8> {
@patch
int operator [](int index) {
@@ -702,6 +725,20 @@
}
}
+extension BoolArray on Array<Bool> {
+ @patch
+ bool operator [](int index) {
+ _checkIndex(index);
+ return _loadBool(_typedDataBase, index);
+ }
+
+ @patch
+ operator []=(int index, bool value) {
+ _checkIndex(index);
+ return _storeBool(_typedDataBase, index, value);
+ }
+}
+
//
// End of generated code.
//
diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart
index 0bbf753..fa98c88 100644
--- a/sdk/lib/ffi/ffi.dart
+++ b/sdk/lib/ffi/ffi.dart
@@ -561,6 +561,20 @@
external Float64List asTypedList(int length);
}
+/// Extension on [Pointer] specialized for the type argument [Bool].
+extension BoolPointer on Pointer<Bool> {
+ /// The bool at [address].
+ external bool get value;
+
+ external void set value(bool value);
+
+ /// The bool at `address + index`.
+ external bool operator [](int index);
+
+ /// The bool at `address + index`.
+ external void operator []=(int index, bool value);
+}
+
/// Bounds checking indexing methods on [Array]s of [Int8].
extension Int8Array on Array<Int8> {
external int operator [](int index);
@@ -638,6 +652,13 @@
external void operator []=(int index, double value);
}
+/// Bounds checking indexing methods on [Array]s of [Bool].
+extension BoolArray on Array<Bool> {
+ external bool operator [](int index);
+
+ external void operator []=(int index, bool value);
+}
+
//
// End of generated code.
//
diff --git a/sdk/lib/ffi/native_type.dart b/sdk/lib/ffi/native_type.dart
index 31e4b72..217a68a 100644
--- a/sdk/lib/ffi/native_type.dart
+++ b/sdk/lib/ffi/native_type.dart
@@ -122,6 +122,14 @@
const Double();
}
+/// Represents a native bool in C.
+///
+/// [Bool] is not constructible in the Dart code and serves purely as marker
+/// in type signatures.
+class Bool extends NativeType {
+ const Bool();
+}
+
/// Represents a void type in C.
///
/// [Void] is not constructible in the Dart code and serves purely as marker in
diff --git a/tests/ffi/bool_test.dart b/tests/ffi/bool_test.dart
new file mode 100644
index 0000000..19f5594
--- /dev/null
+++ b/tests/ffi/bool_test.dart
@@ -0,0 +1,89 @@
+// Copyright (c) 2021, 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.
+//
+// Dart test program for testing dart:ffi bools.
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+import "package:ffi/ffi.dart";
+
+import 'function_structs_by_value_generated_compounds.dart';
+
+void main() {
+ testSizeOf();
+ testStoreLoad();
+ testStoreLoadIndexed();
+ testStruct();
+ testStruct2();
+ testInlineArray();
+}
+
+void testSizeOf() {
+ Expect.equals(1, sizeOf<Bool>());
+}
+
+void testStoreLoad() {
+ final p = calloc<Bool>();
+ p.value = true;
+ Expect.equals(true, p.value);
+ p.value = false;
+ Expect.equals(false, p.value);
+ calloc.free(p);
+}
+
+void testStoreLoadIndexed() {
+ final p = calloc<Bool>(2);
+ p[0] = true;
+ p[1] = false;
+ Expect.equals(true, p[0]);
+ Expect.equals(false, p[1]);
+ calloc.free(p);
+}
+
+void testStruct() {
+ final p = calloc<Struct1ByteBool>();
+ p.ref.a0 = true;
+ Expect.equals(true, p.ref.a0);
+ p.ref.a0 = false;
+ Expect.equals(false, p.ref.a0);
+ calloc.free(p);
+}
+
+void testStruct2() {
+ final p = calloc<Struct10BytesHomogeneousBool>();
+ p.ref.a0 = true;
+ p.ref.a1 = false;
+ p.ref.a2 = true;
+ p.ref.a3 = false;
+ p.ref.a4 = true;
+ p.ref.a5 = false;
+ p.ref.a6 = true;
+ p.ref.a7 = false;
+ p.ref.a8 = true;
+ p.ref.a9 = false;
+ Expect.equals(true, p.ref.a0);
+ Expect.equals(false, p.ref.a1);
+ Expect.equals(true, p.ref.a2);
+ Expect.equals(false, p.ref.a3);
+ Expect.equals(true, p.ref.a4);
+ Expect.equals(false, p.ref.a5);
+ Expect.equals(true, p.ref.a6);
+ Expect.equals(false, p.ref.a7);
+ Expect.equals(true, p.ref.a8);
+ Expect.equals(false, p.ref.a9);
+ calloc.free(p);
+}
+
+void testInlineArray() {
+ final p = calloc<Struct10BytesInlineArrayBool>();
+ final array = p.ref.a0;
+ for (int i = 0; i < 10; i++) {
+ array[i] = i % 2 == 0;
+ }
+ for (int i = 0; i < 10; i++) {
+ Expect.equals(i % 2 == 0, array[i]);
+ }
+ calloc.free(p);
+}
diff --git a/tests/ffi/function_callbacks_structs_by_value_generated_test.dart b/tests/ffi/function_callbacks_structs_by_value_generated_test.dart
index c0521d7..232b7a5 100644
--- a/tests/ffi/function_callbacks_structs_by_value_generated_test.dart
+++ b/tests/ffi/function_callbacks_structs_by_value_generated_test.dart
@@ -351,6 +351,21 @@
passUnion16BytesNestedFloatx10, 0.0),
passUnion16BytesNestedFloatx10AfterCallback),
CallbackTest.withCheck(
+ "PassUint8Boolx9Struct10BytesHomogeneousBoolBool",
+ Pointer.fromFunction<PassUint8Boolx9Struct10BytesHomogeneousBoolBoolType>(
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool, 0),
+ passUint8Boolx9Struct10BytesHomogeneousBoolBoolAfterCallback),
+ CallbackTest.withCheck(
+ "PassUint8Boolx9Struct10BytesInlineArrayBoolBool",
+ Pointer.fromFunction<PassUint8Boolx9Struct10BytesInlineArrayBoolBoolType>(
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool, 0),
+ passUint8Boolx9Struct10BytesInlineArrayBoolBoolAfterCallback),
+ CallbackTest.withCheck(
+ "PassUint8Struct1ByteBool",
+ Pointer.fromFunction<PassUint8Struct1ByteBoolType>(
+ passUint8Struct1ByteBool, false),
+ passUint8Struct1ByteBoolAfterCallback),
+ CallbackTest.withCheck(
"ReturnStruct1ByteInt",
Pointer.fromFunction<ReturnStruct1ByteIntType>(returnStruct1ByteInt),
returnStruct1ByteIntAfterCallback),
@@ -7583,6 +7598,299 @@
Expect.approxEquals(10.0, result);
}
+typedef PassUint8Boolx9Struct10BytesHomogeneousBoolBoolType = Int32 Function(
+ Uint8,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Struct10BytesHomogeneousBool,
+ Bool);
+
+// Global variables to be able to test inputs after callback returned.
+int passUint8Boolx9Struct10BytesHomogeneousBoolBool_a0 = 0;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a1 = false;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a2 = false;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a3 = false;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a4 = false;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a5 = false;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a6 = false;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a7 = false;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a8 = false;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a9 = false;
+Struct10BytesHomogeneousBool
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10 =
+ Pointer<Struct10BytesHomogeneousBool>.fromAddress(0).ref;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a11 = false;
+
+// Result variable also global, so we can delete it after the callback.
+int passUint8Boolx9Struct10BytesHomogeneousBoolBoolResult = 0;
+
+int passUint8Boolx9Struct10BytesHomogeneousBoolBoolCalculateResult() {
+ int result = 0;
+
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a1 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a2 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a3 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a4 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a5 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a6 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a7 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a8 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a9 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a0 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a1 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a2 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a3 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a4 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a5 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a6 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a7 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a8 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a9 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a11 ? 1 : 0;
+
+ passUint8Boolx9Struct10BytesHomogeneousBoolBoolResult = result;
+
+ return result;
+}
+
+/// Passing bools and a struct with bools.
+/// Exhausts the registers to test bools and the bool struct alignment on the
+/// stack.
+int passUint8Boolx9Struct10BytesHomogeneousBoolBool(
+ int a0,
+ bool a1,
+ bool a2,
+ bool a3,
+ bool a4,
+ bool a5,
+ bool a6,
+ bool a7,
+ bool a8,
+ bool a9,
+ Struct10BytesHomogeneousBool a10,
+ bool a11) {
+ print(
+ "passUint8Boolx9Struct10BytesHomogeneousBoolBool(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9}, ${a10}, ${a11})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassUint8Boolx9Struct10BytesHomogeneousBoolBool throwing on purpose!");
+ }
+
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a0 = a0;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a1 = a1;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a2 = a2;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a3 = a3;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a4 = a4;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a5 = a5;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a6 = a6;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a7 = a7;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a8 = a8;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a9 = a9;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10 = a10;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a11 = a11;
+
+ final result =
+ passUint8Boolx9Struct10BytesHomogeneousBoolBoolCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passUint8Boolx9Struct10BytesHomogeneousBoolBoolAfterCallback() {
+ final result =
+ passUint8Boolx9Struct10BytesHomogeneousBoolBoolCalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(11, result);
+}
+
+typedef PassUint8Boolx9Struct10BytesInlineArrayBoolBoolType = Int32 Function(
+ Uint8,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Struct10BytesInlineArrayBool,
+ Bool);
+
+// Global variables to be able to test inputs after callback returned.
+int passUint8Boolx9Struct10BytesInlineArrayBoolBool_a0 = 0;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a1 = false;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a2 = false;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a3 = false;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a4 = false;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a5 = false;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a6 = false;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a7 = false;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a8 = false;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a9 = false;
+Struct10BytesInlineArrayBool
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10 =
+ Pointer<Struct10BytesInlineArrayBool>.fromAddress(0).ref;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a11 = false;
+
+// Result variable also global, so we can delete it after the callback.
+int passUint8Boolx9Struct10BytesInlineArrayBoolBoolResult = 0;
+
+int passUint8Boolx9Struct10BytesInlineArrayBoolBoolCalculateResult() {
+ int result = 0;
+
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a1 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a2 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a3 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a4 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a5 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a6 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a7 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a8 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a9 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[0] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[1] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[2] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[3] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[4] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[5] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[6] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[7] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[8] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[9] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a11 ? 1 : 0;
+
+ passUint8Boolx9Struct10BytesInlineArrayBoolBoolResult = result;
+
+ return result;
+}
+
+/// Passing bools and a struct with bools.
+/// Exhausts the registers to test bools and the bool struct alignment on the
+/// stack.
+int passUint8Boolx9Struct10BytesInlineArrayBoolBool(
+ int a0,
+ bool a1,
+ bool a2,
+ bool a3,
+ bool a4,
+ bool a5,
+ bool a6,
+ bool a7,
+ bool a8,
+ bool a9,
+ Struct10BytesInlineArrayBool a10,
+ bool a11) {
+ print(
+ "passUint8Boolx9Struct10BytesInlineArrayBoolBool(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9}, ${a10}, ${a11})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassUint8Boolx9Struct10BytesInlineArrayBoolBool throwing on purpose!");
+ }
+
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a0 = a0;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a1 = a1;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a2 = a2;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a3 = a3;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a4 = a4;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a5 = a5;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a6 = a6;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a7 = a7;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a8 = a8;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a9 = a9;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10 = a10;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a11 = a11;
+
+ final result =
+ passUint8Boolx9Struct10BytesInlineArrayBoolBoolCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passUint8Boolx9Struct10BytesInlineArrayBoolBoolAfterCallback() {
+ final result =
+ passUint8Boolx9Struct10BytesInlineArrayBoolBoolCalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(11, result);
+}
+
+typedef PassUint8Struct1ByteBoolType = Bool Function(Uint8, Struct1ByteBool);
+
+// Global variables to be able to test inputs after callback returned.
+int passUint8Struct1ByteBool_a0 = 0;
+Struct1ByteBool passUint8Struct1ByteBool_a1 =
+ Pointer<Struct1ByteBool>.fromAddress(0).ref;
+
+// Result variable also global, so we can delete it after the callback.
+bool passUint8Struct1ByteBoolResult = false;
+
+bool passUint8Struct1ByteBoolCalculateResult() {
+ int result = 0;
+
+ result += passUint8Struct1ByteBool_a0;
+ result += passUint8Struct1ByteBool_a1.a0 ? 1 : 0;
+
+ passUint8Struct1ByteBoolResult = result % 2 != 0;
+
+ return result % 2 != 0;
+}
+
+/// Returning a bool.
+bool passUint8Struct1ByteBool(int a0, Struct1ByteBool a1) {
+ print("passUint8Struct1ByteBool(${a0}, ${a1})");
+
+ // In legacy mode, possibly return null.
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("PassUint8Struct1ByteBool throwing on purpose!");
+ }
+
+ passUint8Struct1ByteBool_a0 = a0;
+ passUint8Struct1ByteBool_a1 = a1;
+
+ final result = passUint8Struct1ByteBoolCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passUint8Struct1ByteBoolAfterCallback() {
+ final result = passUint8Struct1ByteBoolCalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(1 % 2 != 0, result);
+}
+
typedef ReturnStruct1ByteIntType = Struct1ByteInt Function(Int8);
// Global variables to be able to test inputs after callback returned.
diff --git a/tests/ffi/function_structs_by_value_generated_compounds.dart b/tests/ffi/function_structs_by_value_generated_compounds.dart
index 2c411cf..2f41b75 100644
--- a/tests/ffi/function_structs_by_value_generated_compounds.dart
+++ b/tests/ffi/function_structs_by_value_generated_compounds.dart
@@ -7,6 +7,13 @@
import 'dart:ffi';
+class Struct1ByteBool extends Struct {
+ @Bool()
+ external bool a0;
+
+ String toString() => "(${a0})";
+}
+
class Struct1ByteInt extends Struct {
@Int8()
external int a0;
@@ -177,6 +184,41 @@
String toString() => "(${a0}, ${a1})";
}
+class Struct10BytesHomogeneousBool extends Struct {
+ @Bool()
+ external bool a0;
+
+ @Bool()
+ external bool a1;
+
+ @Bool()
+ external bool a2;
+
+ @Bool()
+ external bool a3;
+
+ @Bool()
+ external bool a4;
+
+ @Bool()
+ external bool a5;
+
+ @Bool()
+ external bool a6;
+
+ @Bool()
+ external bool a7;
+
+ @Bool()
+ external bool a8;
+
+ @Bool()
+ external bool a9;
+
+ String toString() =>
+ "(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})";
+}
+
class Struct12BytesHomogeneousFloat extends Struct {
@Float()
external double a0;
@@ -938,6 +980,13 @@
String toString() => "(${[for (var i0 = 0; i0 < 8; i0 += 1) a0[i0]]})";
}
+class Struct10BytesInlineArrayBool extends Struct {
+ @Array(10)
+ external Array<Bool> a0;
+
+ String toString() => "(${[for (var i0 = 0; i0 < 10; i0 += 1) a0[i0]]})";
+}
+
class StructInlineArrayIrregular extends Struct {
@Array(2)
external Array<Struct3BytesInt2ByteAligned> a0;
diff --git a/tests/ffi/function_structs_by_value_generated_leaf_test.dart b/tests/ffi/function_structs_by_value_generated_leaf_test.dart
index 9efc77b..2067463 100644
--- a/tests/ffi/function_structs_by_value_generated_leaf_test.dart
+++ b/tests/ffi/function_structs_by_value_generated_leaf_test.dart
@@ -86,6 +86,9 @@
testPassUnion9BytesNestedIntx10Leaf();
testPassUnion16BytesNestedInlineArrayFloatx10Leaf();
testPassUnion16BytesNestedFloatx10Leaf();
+ testPassUint8Boolx9Struct10BytesHomogeneousBoolBoolLeaf();
+ testPassUint8Boolx9Struct10BytesInlineArrayBoolBoolLeaf();
+ testPassUint8Struct1ByteBoolLeaf();
testReturnStruct1ByteIntLeaf();
testReturnStruct3BytesHomogeneousUint8Leaf();
testReturnStruct3BytesInt2ByteAlignedLeaf();
@@ -5295,6 +5298,169 @@
calloc.free(a9Pointer);
}
+final passUint8Boolx9Struct10BytesHomogeneousBoolBoolLeaf =
+ ffiTestFunctions
+ .lookupFunction<
+ Int32 Function(Uint8, Bool, Bool, Bool, Bool, Bool, Bool, Bool,
+ Bool, Bool, Struct10BytesHomogeneousBool, Bool),
+ int Function(
+ int,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ Struct10BytesHomogeneousBool,
+ bool)>("PassUint8Boolx9Struct10BytesHomogeneousBoolBool",
+ isLeaf: true);
+
+/// Passing bools and a struct with bools.
+/// Exhausts the registers to test bools and the bool struct alignment on the
+/// stack.
+void testPassUint8Boolx9Struct10BytesHomogeneousBoolBoolLeaf() {
+ int a0;
+ bool a1;
+ bool a2;
+ bool a3;
+ bool a4;
+ bool a5;
+ bool a6;
+ bool a7;
+ bool a8;
+ bool a9;
+ final a10Pointer = calloc<Struct10BytesHomogeneousBool>();
+ final Struct10BytesHomogeneousBool a10 = a10Pointer.ref;
+ bool a11;
+
+ a0 = 1;
+ a1 = false;
+ a2 = true;
+ a3 = false;
+ a4 = true;
+ a5 = false;
+ a6 = true;
+ a7 = false;
+ a8 = true;
+ a9 = false;
+ a10.a0 = true;
+ a10.a1 = false;
+ a10.a2 = true;
+ a10.a3 = false;
+ a10.a4 = true;
+ a10.a5 = false;
+ a10.a6 = true;
+ a10.a7 = false;
+ a10.a8 = true;
+ a10.a9 = false;
+ a11 = true;
+
+ final result = passUint8Boolx9Struct10BytesHomogeneousBoolBoolLeaf(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
+
+ print("result = $result");
+
+ Expect.equals(11, result);
+
+ calloc.free(a10Pointer);
+}
+
+final passUint8Boolx9Struct10BytesInlineArrayBoolBoolLeaf =
+ ffiTestFunctions
+ .lookupFunction<
+ Int32 Function(Uint8, Bool, Bool, Bool, Bool, Bool, Bool, Bool,
+ Bool, Bool, Struct10BytesInlineArrayBool, Bool),
+ int Function(
+ int,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ Struct10BytesInlineArrayBool,
+ bool)>("PassUint8Boolx9Struct10BytesInlineArrayBoolBool",
+ isLeaf: true);
+
+/// Passing bools and a struct with bools.
+/// Exhausts the registers to test bools and the bool struct alignment on the
+/// stack.
+void testPassUint8Boolx9Struct10BytesInlineArrayBoolBoolLeaf() {
+ int a0;
+ bool a1;
+ bool a2;
+ bool a3;
+ bool a4;
+ bool a5;
+ bool a6;
+ bool a7;
+ bool a8;
+ bool a9;
+ final a10Pointer = calloc<Struct10BytesInlineArrayBool>();
+ final Struct10BytesInlineArrayBool a10 = a10Pointer.ref;
+ bool a11;
+
+ a0 = 1;
+ a1 = false;
+ a2 = true;
+ a3 = false;
+ a4 = true;
+ a5 = false;
+ a6 = true;
+ a7 = false;
+ a8 = true;
+ a9 = false;
+ a10.a0[0] = true;
+ a10.a0[1] = false;
+ a10.a0[2] = true;
+ a10.a0[3] = false;
+ a10.a0[4] = true;
+ a10.a0[5] = false;
+ a10.a0[6] = true;
+ a10.a0[7] = false;
+ a10.a0[8] = true;
+ a10.a0[9] = false;
+ a11 = true;
+
+ final result = passUint8Boolx9Struct10BytesInlineArrayBoolBoolLeaf(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
+
+ print("result = $result");
+
+ Expect.equals(11, result);
+
+ calloc.free(a10Pointer);
+}
+
+final passUint8Struct1ByteBoolLeaf = ffiTestFunctions.lookupFunction<
+ Bool Function(Uint8, Struct1ByteBool),
+ bool Function(
+ int, Struct1ByteBool)>("PassUint8Struct1ByteBool", isLeaf: true);
+
+/// Returning a bool.
+void testPassUint8Struct1ByteBoolLeaf() {
+ int a0;
+ final a1Pointer = calloc<Struct1ByteBool>();
+ final Struct1ByteBool a1 = a1Pointer.ref;
+
+ a0 = 1;
+ a1.a0 = false;
+
+ final result = passUint8Struct1ByteBoolLeaf(a0, a1);
+
+ print("result = $result");
+
+ Expect.equals(1 % 2 != 0, result);
+
+ calloc.free(a1Pointer);
+}
+
final returnStruct1ByteIntLeaf = ffiTestFunctions.lookupFunction<
Struct1ByteInt Function(Int8),
Struct1ByteInt Function(int)>("ReturnStruct1ByteInt", isLeaf: true);
diff --git a/tests/ffi/function_structs_by_value_generated_test.dart b/tests/ffi/function_structs_by_value_generated_test.dart
index 14557da..463118d 100644
--- a/tests/ffi/function_structs_by_value_generated_test.dart
+++ b/tests/ffi/function_structs_by_value_generated_test.dart
@@ -86,6 +86,9 @@
testPassUnion9BytesNestedIntx10();
testPassUnion16BytesNestedInlineArrayFloatx10();
testPassUnion16BytesNestedFloatx10();
+ testPassUint8Boolx9Struct10BytesHomogeneousBoolBool();
+ testPassUint8Boolx9Struct10BytesInlineArrayBoolBool();
+ testPassUint8Struct1ByteBool();
testReturnStruct1ByteInt();
testReturnStruct3BytesHomogeneousUint8();
testReturnStruct3BytesInt2ByteAligned();
@@ -5224,6 +5227,164 @@
calloc.free(a9Pointer);
}
+final passUint8Boolx9Struct10BytesHomogeneousBoolBool =
+ ffiTestFunctions.lookupFunction<
+ Int32 Function(Uint8, Bool, Bool, Bool, Bool, Bool, Bool, Bool, Bool,
+ Bool, Struct10BytesHomogeneousBool, Bool),
+ int Function(
+ int,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ Struct10BytesHomogeneousBool,
+ bool)>("PassUint8Boolx9Struct10BytesHomogeneousBoolBool");
+
+/// Passing bools and a struct with bools.
+/// Exhausts the registers to test bools and the bool struct alignment on the
+/// stack.
+void testPassUint8Boolx9Struct10BytesHomogeneousBoolBool() {
+ int a0;
+ bool a1;
+ bool a2;
+ bool a3;
+ bool a4;
+ bool a5;
+ bool a6;
+ bool a7;
+ bool a8;
+ bool a9;
+ final a10Pointer = calloc<Struct10BytesHomogeneousBool>();
+ final Struct10BytesHomogeneousBool a10 = a10Pointer.ref;
+ bool a11;
+
+ a0 = 1;
+ a1 = false;
+ a2 = true;
+ a3 = false;
+ a4 = true;
+ a5 = false;
+ a6 = true;
+ a7 = false;
+ a8 = true;
+ a9 = false;
+ a10.a0 = true;
+ a10.a1 = false;
+ a10.a2 = true;
+ a10.a3 = false;
+ a10.a4 = true;
+ a10.a5 = false;
+ a10.a6 = true;
+ a10.a7 = false;
+ a10.a8 = true;
+ a10.a9 = false;
+ a11 = true;
+
+ final result = passUint8Boolx9Struct10BytesHomogeneousBoolBool(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
+
+ print("result = $result");
+
+ Expect.equals(11, result);
+
+ calloc.free(a10Pointer);
+}
+
+final passUint8Boolx9Struct10BytesInlineArrayBoolBool =
+ ffiTestFunctions.lookupFunction<
+ Int32 Function(Uint8, Bool, Bool, Bool, Bool, Bool, Bool, Bool, Bool,
+ Bool, Struct10BytesInlineArrayBool, Bool),
+ int Function(
+ int,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ Struct10BytesInlineArrayBool,
+ bool)>("PassUint8Boolx9Struct10BytesInlineArrayBoolBool");
+
+/// Passing bools and a struct with bools.
+/// Exhausts the registers to test bools and the bool struct alignment on the
+/// stack.
+void testPassUint8Boolx9Struct10BytesInlineArrayBoolBool() {
+ int a0;
+ bool a1;
+ bool a2;
+ bool a3;
+ bool a4;
+ bool a5;
+ bool a6;
+ bool a7;
+ bool a8;
+ bool a9;
+ final a10Pointer = calloc<Struct10BytesInlineArrayBool>();
+ final Struct10BytesInlineArrayBool a10 = a10Pointer.ref;
+ bool a11;
+
+ a0 = 1;
+ a1 = false;
+ a2 = true;
+ a3 = false;
+ a4 = true;
+ a5 = false;
+ a6 = true;
+ a7 = false;
+ a8 = true;
+ a9 = false;
+ a10.a0[0] = true;
+ a10.a0[1] = false;
+ a10.a0[2] = true;
+ a10.a0[3] = false;
+ a10.a0[4] = true;
+ a10.a0[5] = false;
+ a10.a0[6] = true;
+ a10.a0[7] = false;
+ a10.a0[8] = true;
+ a10.a0[9] = false;
+ a11 = true;
+
+ final result = passUint8Boolx9Struct10BytesInlineArrayBoolBool(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
+
+ print("result = $result");
+
+ Expect.equals(11, result);
+
+ calloc.free(a10Pointer);
+}
+
+final passUint8Struct1ByteBool = ffiTestFunctions.lookupFunction<
+ Bool Function(Uint8, Struct1ByteBool),
+ bool Function(int, Struct1ByteBool)>("PassUint8Struct1ByteBool");
+
+/// Returning a bool.
+void testPassUint8Struct1ByteBool() {
+ int a0;
+ final a1Pointer = calloc<Struct1ByteBool>();
+ final Struct1ByteBool a1 = a1Pointer.ref;
+
+ a0 = 1;
+ a1.a0 = false;
+
+ final result = passUint8Struct1ByteBool(a0, a1);
+
+ print("result = $result");
+
+ Expect.equals(1 % 2 != 0, result);
+
+ calloc.free(a1Pointer);
+}
+
final returnStruct1ByteInt = ffiTestFunctions.lookupFunction<
Struct1ByteInt Function(Int8),
Struct1ByteInt Function(int)>("ReturnStruct1ByteInt");
diff --git a/tests/ffi/generator/c_types.dart b/tests/ffi/generator/c_types.dart
index 7236aed..d0825f6 100644
--- a/tests/ffi/generator/c_types.dart
+++ b/tests/ffi/generator/c_types.dart
@@ -6,6 +6,7 @@
import 'utils.dart';
+const bool_ = FundamentalType(PrimitiveType.bool_);
const int8 = FundamentalType(PrimitiveType.int8);
const int16 = FundamentalType(PrimitiveType.int16);
const int32 = FundamentalType(PrimitiveType.int32);
@@ -19,6 +20,7 @@
const double_ = FundamentalType(PrimitiveType.double_);
enum PrimitiveType {
+ bool_,
int8,
int16,
int32,
@@ -33,6 +35,7 @@
}
const primitiveNames = [
+ "bool",
"int8",
"int16",
"int32",
@@ -47,7 +50,7 @@
];
const intptrSize = -1;
-const primitiveSizesInBytes = [1, 2, 4, 8, 1, 2, 4, 8, intptrSize, 4, 8];
+const primitiveSizesInBytes = [1, 1, 2, 4, 8, 1, 2, 4, 8, intptrSize, 4, 8];
abstract class CType {
String get cType;
@@ -67,6 +70,9 @@
/// All members have a integer type.
bool get isOnlyInteger;
+ /// All members have a bool type.
+ bool get isOnlyBool;
+
String toString() => dartCType;
const CType();
@@ -77,12 +83,15 @@
const FundamentalType(this.primitive);
+ bool get isBool => primitive == PrimitiveType.bool_;
bool get isFloatingPoint =>
primitive == PrimitiveType.float || primitive == PrimitiveType.double_;
- bool get isInteger => !isFloatingPoint;
+ bool get isInteger => !isFloatingPoint && !isBool;
bool get isOnlyFloatingPoint => isFloatingPoint;
bool get isOnlyInteger => isInteger;
+ bool get isOnlyBool => isBool;
bool get isUnsigned =>
+ primitive == PrimitiveType.bool_ ||
primitive == PrimitiveType.uint8 ||
primitive == PrimitiveType.uint16 ||
primitive == PrimitiveType.uint32 ||
@@ -93,7 +102,13 @@
String get cType => "${name}${isInteger ? "_t" : ""}";
String get dartCType => name.upperCaseFirst();
- String get dartType => isInteger ? "int" : "double";
+ String get dartType {
+ if (isInteger) return 'int';
+ if (isOnlyFloatingPoint) return 'double';
+ if (isBool) return 'bool';
+ throw 'Unknown type $primitive';
+ }
+
String get dartStructFieldAnnotation => "@${dartCType}()";
bool get hasSize => primitive != PrimitiveType.intptr;
int get size {
@@ -118,6 +133,7 @@
bool get isOnlyFloatingPoint => false;
bool get isOnlyInteger => true;
+ bool get isOnlyBool => false;
}
/// Used to give [StructType] fields and [FunctionType] arguments names.
@@ -186,11 +202,11 @@
String get dartSuperClass;
bool get isOnlyFloatingPoint =>
- !memberTypes.map((e) => e.isOnlyFloatingPoint).contains(false);
- bool get isOnlyInteger =>
- !memberTypes.map((e) => e.isOnlyInteger).contains(false);
+ memberTypes.every((e) => e.isOnlyFloatingPoint);
+ bool get isOnlyInteger => memberTypes.every((e) => e.isOnlyInteger);
+ bool get isOnlyBool => memberTypes.every((e) => e.isOnlyBool);
- bool get isMixed => !isOnlyInteger && !isOnlyFloatingPoint;
+ bool get isMixed => !isOnlyInteger && !isOnlyFloatingPoint && !isOnlyBool;
bool get hasNestedStructs =>
members.map((e) => e.type is StructType).contains(true);
@@ -219,8 +235,7 @@
String get cKeyword => "struct";
String get dartSuperClass => "Struct";
- bool get hasSize =>
- !memberTypes.map((e) => e.hasSize).contains(false) && !hasPadding;
+ bool get hasSize => memberTypes.every((e) => e.hasSize) && !hasPadding;
int get size => memberTypes.fold(0, (int acc, e) => acc + e.size);
bool get hasPacking => packing != null;
@@ -273,6 +288,8 @@
result += "Float";
} else if (isOnlyInteger) {
result += "Int";
+ } else if (isOnlyBool) {
+ result += "Bool";
} else {
result += "Mixed";
}
@@ -287,7 +304,7 @@
String get cKeyword => "union";
String get dartSuperClass => "Union";
- bool get hasSize => !memberTypes.map((e) => e.hasSize).contains(false);
+ bool get hasSize => memberTypes.every((e) => e.hasSize);
int get size => memberTypes.fold(0, (int acc, e) => math.max(acc, e.size));
String get name {
@@ -364,6 +381,7 @@
bool get isOnlyFloatingPoint => elementType.isOnlyFloatingPoint;
bool get isOnlyInteger => elementType.isOnlyInteger;
+ bool get isOnlyBool => elementType.isOnlyBool;
}
class FunctionType extends CType {
@@ -396,6 +414,7 @@
bool get isOnlyFloatingPoint => throw "Not implemented";
bool get isOnlyInteger => throw "Not implemented";
+ bool get isOnlyBool => throw "Not implemented";
/// Group consecutive [arguments] by same type.
///
diff --git a/tests/ffi/generator/structs_by_value_tests_configuration.dart b/tests/ffi/generator/structs_by_value_tests_configuration.dart
index 78c187f..a5d62af 100644
--- a/tests/ffi/generator/structs_by_value_tests_configuration.dart
+++ b/tests/ffi/generator/structs_by_value_tests_configuration.dart
@@ -374,6 +374,54 @@
Union with homogenous floats."""),
FunctionType(List.filled(10, union16bytesFloat2), double_, """
Union with homogenous floats."""),
+ FunctionType(
+ [
+ uint8,
+ bool_,
+ bool_,
+ bool_,
+ bool_,
+ bool_,
+ bool_,
+ bool_,
+ bool_,
+ bool_,
+ struct10bytesBool,
+ bool_,
+ ],
+ int32,
+ """
+Passing bools and a struct with bools.
+Exhausts the registers to test bools and the bool struct alignment on the
+stack."""),
+ FunctionType(
+ [
+ uint8,
+ bool_,
+ bool_,
+ bool_,
+ bool_,
+ bool_,
+ bool_,
+ bool_,
+ bool_,
+ bool_,
+ structInlineArrayBool,
+ bool_,
+ ],
+ int32,
+ """
+Passing bools and a struct with bools.
+Exhausts the registers to test bools and the bool struct alignment on the
+stack."""),
+ FunctionType(
+ [
+ uint8,
+ struct1byteBool,
+ ],
+ bool_,
+ """
+Returning a bool."""),
];
final functionsStructReturn = [
@@ -558,6 +606,7 @@
];
final compounds = [
+ struct1byteBool,
struct1byteInt,
struct3bytesInt,
struct3bytesInt2,
@@ -571,6 +620,7 @@
struct8BytesMixed,
struct9bytesInt,
struct9bytesInt2,
+ struct10bytesBool,
struct12bytesFloat,
struct16bytesFloat,
struct16bytesMixed,
@@ -598,6 +648,7 @@
structNestedBigger,
structNestedEvenBigger,
structInlineArray,
+ structInlineArrayBool,
structInlineArrayIrregular,
structInlineArray100Bytes,
structInlineArrayBig,
@@ -623,6 +674,7 @@
union16bytesFloat2,
];
+final struct1byteBool = StructType([bool_]);
final struct1byteInt = StructType([int8]);
final struct3bytesInt = StructType(List.filled(3, uint8));
final struct3bytesInt2 = StructType.disambiguate([int16, int8], "2ByteAligned");
@@ -638,6 +690,7 @@
final struct9bytesInt = StructType(List.filled(9, uint8));
final struct9bytesInt2 =
StructType.disambiguate([int64, int8], "4Or8ByteAligned");
+final struct10bytesBool = StructType(List.filled(10, bool_));
final struct12bytesFloat = StructType([float, float, float]);
/// The largest homogenous float that goes into FPU registers on softfp and
@@ -716,6 +769,8 @@
final structInlineArray = StructType([FixedLengthArrayType(uint8, 8)]);
+final structInlineArrayBool = StructType([FixedLengthArrayType(bool_, 10)]);
+
final structInlineArrayIrregular = StructType.override(
[FixedLengthArrayType(struct3bytesInt2, 2), uint8], "InlineArrayIrregular");
diff --git a/tests/ffi/generator/structs_by_value_tests_generator.dart b/tests/ffi/generator/structs_by_value_tests_generator.dart
index 03f16ff..51de2db 100644
--- a/tests/ffi/generator/structs_by_value_tests_generator.dart
+++ b/tests/ffi/generator/structs_by_value_tests_generator.dart
@@ -102,7 +102,9 @@
String addToResultStatements(String variableName) {
switch (this.runtimeType) {
case FundamentalType:
- return "result += $variableName;\n";
+ final this_ = this as FundamentalType;
+ final boolToInt = this_.isBool ? ' ? 1 : 0' : '';
+ return "result += $variableName$boolToInt;\n";
case StructType:
final this_ = this as StructType;
@@ -214,15 +216,21 @@
String nextValue(FundamentalType type) {
int argumentValue = i;
i++;
+ if (type.isBool) {
+ argumentValue = argumentValue % 2;
+ }
if (type.isSigned && i % 2 == 0) {
argumentValue = -argumentValue;
}
sum += argumentValue;
if (type.isFloatingPoint) {
return argumentValue.toDouble().toString();
- } else {
+ } else if (type.isInteger) {
return argumentValue.toString();
+ } else if (type.isBool) {
+ return argumentValue == 1 ? 'true' : 'false';
}
+ throw 'Unknown type $type';
}
String sumValue(FundamentalType type) {
@@ -261,7 +269,13 @@
if (this_.isInteger) {
return "${dartType} ${variableName} = 0;\n";
}
- return "${dartType} ${variableName} = 0.0;\n";
+ if (this_.isFloatingPoint) {
+ return "${dartType} ${variableName} = 0.0;\n";
+ }
+ if (this_.isBool) {
+ return "${dartType} ${variableName} = false;\n";
+ }
+ throw 'Unknown type $this_';
case StructType:
case UnionType:
@@ -345,8 +359,13 @@
if (this_.isInteger) {
return "Expect.equals(${expected}, ${actual});";
}
- assert(this_.isFloatingPoint);
- return "Expect.approxEquals(${expected}, ${actual});";
+ if (this_.isFloatingPoint) {
+ return "Expect.approxEquals(${expected}, ${actual});";
+ }
+ if (this_.isBool) {
+ return "Expect.equals(${expected} % 2 != 0, ${actual});";
+ }
+ throw 'Unexpected type $this_';
case StructType:
final this_ = this as StructType;
@@ -594,15 +613,24 @@
bool structsAsPointers = false;
String assignReturnGlobal = "";
String buildReturnValue = "";
+ String returnValueType = returnValue.dartType;
+ String result = 'result';
+ if (returnValueType == 'bool') {
+ // We can't sum a bool;
+ returnValueType = 'int';
+ result = 'result % 2 != 0';
+ }
+
switch (testType) {
case TestType.structArguments:
// Sum all input values.
+
buildReturnValue = """
- ${returnValue.dartType} result = 0;
+ $returnValueType result = 0;
${arguments.addToResultStatements('${dartName}_')}
""";
- assignReturnGlobal = "${dartName}Result = result;";
+ assignReturnGlobal = "${dartName}Result = $result;";
break;
case TestType.structReturn:
// Allocate a struct.
@@ -675,7 +703,7 @@
$assignReturnGlobal
- return result;
+ return $result;
}
${reason.makeDartDocComment()}
@@ -719,10 +747,15 @@
String get dartCallbackTestConstructor {
String exceptionalReturn = "";
if (returnValue is FundamentalType) {
- if ((returnValue as FundamentalType).isFloatingPoint) {
+ final returnValue_ = returnValue as FundamentalType;
+ if (returnValue_.isFloatingPoint) {
exceptionalReturn = ", 0.0";
- } else {
+ } else if (returnValue_.isInteger) {
exceptionalReturn = ", 0";
+ } else if (returnValue_.isBool) {
+ exceptionalReturn = ", false";
+ } else {
+ throw 'Unexpected type $returnValue_';
}
}
return """
@@ -734,24 +767,31 @@
String get cCallCode {
String body = "";
+ String returnValueType = returnValue.cType;
+ String returnStatement = 'return result;';
+ if (returnValueType == 'bool') {
+ // We can't sum in a bool.
+ returnValueType = 'uint64_t';
+ returnStatement = 'return result % 2 != 0;';
+ }
switch (testType) {
case TestType.structArguments:
body = """
- ${returnValue.cType} result = 0;
+ $returnValueType result = 0;
${arguments.addToResultStatements()}
""";
break;
case TestType.structReturn:
body = """
- ${returnValue.cType} result = {};
+ $returnValueType result = {};
${arguments.copyValueStatements("", "result.")}
""";
break;
case TestType.structReturnArgument:
body = """
- ${returnValue.cType} result = ${structReturnArgument.name};
+ $returnValueType result = ${structReturnArgument.name};
""";
break;
}
@@ -769,7 +809,7 @@
${returnValue.coutStatement("result")}
- return result;
+ $returnStatement
}
""";
diff --git a/tests/ffi_2/bool_test.dart b/tests/ffi_2/bool_test.dart
new file mode 100644
index 0000000..36af8a8
--- /dev/null
+++ b/tests/ffi_2/bool_test.dart
@@ -0,0 +1,91 @@
+// Copyright (c) 2021, 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.
+//
+// Dart test program for testing dart:ffi bools.
+
+// @dart = 2.9
+
+import 'dart:ffi';
+
+import "package:expect/expect.dart";
+import "package:ffi/ffi.dart";
+
+import 'function_structs_by_value_generated_compounds.dart';
+
+void main() {
+ testSizeOf();
+ testStoreLoad();
+ testStoreLoadIndexed();
+ testStruct();
+ testStruct2();
+ testInlineArray();
+}
+
+void testSizeOf() {
+ Expect.equals(1, sizeOf<Bool>());
+}
+
+void testStoreLoad() {
+ final p = calloc<Bool>();
+ p.value = true;
+ Expect.equals(true, p.value);
+ p.value = false;
+ Expect.equals(false, p.value);
+ calloc.free(p);
+}
+
+void testStoreLoadIndexed() {
+ final p = calloc<Bool>(2);
+ p[0] = true;
+ p[1] = false;
+ Expect.equals(true, p[0]);
+ Expect.equals(false, p[1]);
+ calloc.free(p);
+}
+
+void testStruct() {
+ final p = calloc<Struct1ByteBool>();
+ p.ref.a0 = true;
+ Expect.equals(true, p.ref.a0);
+ p.ref.a0 = false;
+ Expect.equals(false, p.ref.a0);
+ calloc.free(p);
+}
+
+void testStruct2() {
+ final p = calloc<Struct10BytesHomogeneousBool>();
+ p.ref.a0 = true;
+ p.ref.a1 = false;
+ p.ref.a2 = true;
+ p.ref.a3 = false;
+ p.ref.a4 = true;
+ p.ref.a5 = false;
+ p.ref.a6 = true;
+ p.ref.a7 = false;
+ p.ref.a8 = true;
+ p.ref.a9 = false;
+ Expect.equals(true, p.ref.a0);
+ Expect.equals(false, p.ref.a1);
+ Expect.equals(true, p.ref.a2);
+ Expect.equals(false, p.ref.a3);
+ Expect.equals(true, p.ref.a4);
+ Expect.equals(false, p.ref.a5);
+ Expect.equals(true, p.ref.a6);
+ Expect.equals(false, p.ref.a7);
+ Expect.equals(true, p.ref.a8);
+ Expect.equals(false, p.ref.a9);
+ calloc.free(p);
+}
+
+void testInlineArray() {
+ final p = calloc<Struct10BytesInlineArrayBool>();
+ final array = p.ref.a0;
+ for (int i = 0; i < 10; i++) {
+ array[i] = i % 2 == 0;
+ }
+ for (int i = 0; i < 10; i++) {
+ Expect.equals(i % 2 == 0, array[i]);
+ }
+ calloc.free(p);
+}
diff --git a/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart b/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart
index ba0f7ff..d593bd1 100644
--- a/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart
+++ b/tests/ffi_2/function_callbacks_structs_by_value_generated_test.dart
@@ -353,6 +353,21 @@
passUnion16BytesNestedFloatx10, 0.0),
passUnion16BytesNestedFloatx10AfterCallback),
CallbackTest.withCheck(
+ "PassUint8Boolx9Struct10BytesHomogeneousBoolBool",
+ Pointer.fromFunction<PassUint8Boolx9Struct10BytesHomogeneousBoolBoolType>(
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool, 0),
+ passUint8Boolx9Struct10BytesHomogeneousBoolBoolAfterCallback),
+ CallbackTest.withCheck(
+ "PassUint8Boolx9Struct10BytesInlineArrayBoolBool",
+ Pointer.fromFunction<PassUint8Boolx9Struct10BytesInlineArrayBoolBoolType>(
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool, 0),
+ passUint8Boolx9Struct10BytesInlineArrayBoolBoolAfterCallback),
+ CallbackTest.withCheck(
+ "PassUint8Struct1ByteBool",
+ Pointer.fromFunction<PassUint8Struct1ByteBoolType>(
+ passUint8Struct1ByteBool, false),
+ passUint8Struct1ByteBoolAfterCallback),
+ CallbackTest.withCheck(
"ReturnStruct1ByteInt",
Pointer.fromFunction<ReturnStruct1ByteIntType>(returnStruct1ByteInt),
returnStruct1ByteIntAfterCallback),
@@ -7833,6 +7848,311 @@
Expect.approxEquals(10.0, result);
}
+typedef PassUint8Boolx9Struct10BytesHomogeneousBoolBoolType = Int32 Function(
+ Uint8,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Struct10BytesHomogeneousBool,
+ Bool);
+
+// Global variables to be able to test inputs after callback returned.
+int passUint8Boolx9Struct10BytesHomogeneousBoolBool_a0 = 0;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a1 = false;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a2 = false;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a3 = false;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a4 = false;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a5 = false;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a6 = false;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a7 = false;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a8 = false;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a9 = false;
+Struct10BytesHomogeneousBool
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10 =
+ Pointer<Struct10BytesHomogeneousBool>.fromAddress(0).ref;
+bool passUint8Boolx9Struct10BytesHomogeneousBoolBool_a11 = false;
+
+// Result variable also global, so we can delete it after the callback.
+int passUint8Boolx9Struct10BytesHomogeneousBoolBoolResult = 0;
+
+int passUint8Boolx9Struct10BytesHomogeneousBoolBoolCalculateResult() {
+ int result = 0;
+
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a1 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a2 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a3 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a4 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a5 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a6 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a7 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a8 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a9 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a0 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a1 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a2 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a3 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a4 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a5 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a6 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a7 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a8 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10.a9 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesHomogeneousBoolBool_a11 ? 1 : 0;
+
+ passUint8Boolx9Struct10BytesHomogeneousBoolBoolResult = result;
+
+ return result;
+}
+
+/// Passing bools and a struct with bools.
+/// Exhausts the registers to test bools and the bool struct alignment on the
+/// stack.
+int passUint8Boolx9Struct10BytesHomogeneousBoolBool(
+ int a0,
+ bool a1,
+ bool a2,
+ bool a3,
+ bool a4,
+ bool a5,
+ bool a6,
+ bool a7,
+ bool a8,
+ bool a9,
+ Struct10BytesHomogeneousBool a10,
+ bool a11) {
+ print(
+ "passUint8Boolx9Struct10BytesHomogeneousBoolBool(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9}, ${a10}, ${a11})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassUint8Boolx9Struct10BytesHomogeneousBoolBool throwing on purpose!");
+ }
+
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a0 = a0;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a1 = a1;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a2 = a2;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a3 = a3;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a4 = a4;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a5 = a5;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a6 = a6;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a7 = a7;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a8 = a8;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a9 = a9;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a10 = a10;
+ passUint8Boolx9Struct10BytesHomogeneousBoolBool_a11 = a11;
+
+ final result =
+ passUint8Boolx9Struct10BytesHomogeneousBoolBoolCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passUint8Boolx9Struct10BytesHomogeneousBoolBoolAfterCallback() {
+ final result =
+ passUint8Boolx9Struct10BytesHomogeneousBoolBoolCalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(11, result);
+}
+
+typedef PassUint8Boolx9Struct10BytesInlineArrayBoolBoolType = Int32 Function(
+ Uint8,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Bool,
+ Struct10BytesInlineArrayBool,
+ Bool);
+
+// Global variables to be able to test inputs after callback returned.
+int passUint8Boolx9Struct10BytesInlineArrayBoolBool_a0 = 0;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a1 = false;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a2 = false;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a3 = false;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a4 = false;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a5 = false;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a6 = false;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a7 = false;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a8 = false;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a9 = false;
+Struct10BytesInlineArrayBool
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10 =
+ Pointer<Struct10BytesInlineArrayBool>.fromAddress(0).ref;
+bool passUint8Boolx9Struct10BytesInlineArrayBoolBool_a11 = false;
+
+// Result variable also global, so we can delete it after the callback.
+int passUint8Boolx9Struct10BytesInlineArrayBoolBoolResult = 0;
+
+int passUint8Boolx9Struct10BytesInlineArrayBoolBoolCalculateResult() {
+ int result = 0;
+
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a1 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a2 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a3 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a4 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a5 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a6 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a7 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a8 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a9 ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[0] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[1] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[2] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[3] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[4] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[5] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[6] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[7] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[8] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10.a0[9] ? 1 : 0;
+ result += passUint8Boolx9Struct10BytesInlineArrayBoolBool_a11 ? 1 : 0;
+
+ passUint8Boolx9Struct10BytesInlineArrayBoolBoolResult = result;
+
+ return result;
+}
+
+/// Passing bools and a struct with bools.
+/// Exhausts the registers to test bools and the bool struct alignment on the
+/// stack.
+int passUint8Boolx9Struct10BytesInlineArrayBoolBool(
+ int a0,
+ bool a1,
+ bool a2,
+ bool a3,
+ bool a4,
+ bool a5,
+ bool a6,
+ bool a7,
+ bool a8,
+ bool a9,
+ Struct10BytesInlineArrayBool a10,
+ bool a11) {
+ print(
+ "passUint8Boolx9Struct10BytesInlineArrayBoolBool(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9}, ${a10}, ${a11})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception(
+ "PassUint8Boolx9Struct10BytesInlineArrayBoolBool throwing on purpose!");
+ }
+
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a0 = a0;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a1 = a1;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a2 = a2;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a3 = a3;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a4 = a4;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a5 = a5;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a6 = a6;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a7 = a7;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a8 = a8;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a9 = a9;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a10 = a10;
+ passUint8Boolx9Struct10BytesInlineArrayBoolBool_a11 = a11;
+
+ final result =
+ passUint8Boolx9Struct10BytesInlineArrayBoolBoolCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passUint8Boolx9Struct10BytesInlineArrayBoolBoolAfterCallback() {
+ final result =
+ passUint8Boolx9Struct10BytesInlineArrayBoolBoolCalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(11, result);
+}
+
+typedef PassUint8Struct1ByteBoolType = Bool Function(Uint8, Struct1ByteBool);
+
+// Global variables to be able to test inputs after callback returned.
+int passUint8Struct1ByteBool_a0 = 0;
+Struct1ByteBool passUint8Struct1ByteBool_a1 =
+ Pointer<Struct1ByteBool>.fromAddress(0).ref;
+
+// Result variable also global, so we can delete it after the callback.
+bool passUint8Struct1ByteBoolResult = false;
+
+bool passUint8Struct1ByteBoolCalculateResult() {
+ int result = 0;
+
+ result += passUint8Struct1ByteBool_a0;
+ result += passUint8Struct1ByteBool_a1.a0 ? 1 : 0;
+
+ passUint8Struct1ByteBoolResult = result % 2 != 0;
+
+ return result % 2 != 0;
+}
+
+/// Returning a bool.
+bool passUint8Struct1ByteBool(int a0, Struct1ByteBool a1) {
+ print("passUint8Struct1ByteBool(${a0}, ${a1})");
+
+ // In legacy mode, possibly return null.
+ if (a0 == 84) {
+ print("returning null!");
+ return null;
+ }
+
+ // In both nnbd and legacy mode, possibly throw.
+ if (a0 == 42 || a0 == 84) {
+ print("throwing!");
+ throw Exception("PassUint8Struct1ByteBool throwing on purpose!");
+ }
+
+ passUint8Struct1ByteBool_a0 = a0;
+ passUint8Struct1ByteBool_a1 = a1;
+
+ final result = passUint8Struct1ByteBoolCalculateResult();
+
+ print("result = $result");
+
+ return result;
+}
+
+void passUint8Struct1ByteBoolAfterCallback() {
+ final result = passUint8Struct1ByteBoolCalculateResult();
+
+ print("after callback result = $result");
+
+ Expect.equals(1 % 2 != 0, result);
+}
+
typedef ReturnStruct1ByteIntType = Struct1ByteInt Function(Int8);
// Global variables to be able to test inputs after callback returned.
diff --git a/tests/ffi_2/function_structs_by_value_generated_compounds.dart b/tests/ffi_2/function_structs_by_value_generated_compounds.dart
index ede77a3..8b7931f 100644
--- a/tests/ffi_2/function_structs_by_value_generated_compounds.dart
+++ b/tests/ffi_2/function_structs_by_value_generated_compounds.dart
@@ -9,6 +9,13 @@
import 'dart:ffi';
+class Struct1ByteBool extends Struct {
+ @Bool()
+ bool a0;
+
+ String toString() => "(${a0})";
+}
+
class Struct1ByteInt extends Struct {
@Int8()
int a0;
@@ -179,6 +186,41 @@
String toString() => "(${a0}, ${a1})";
}
+class Struct10BytesHomogeneousBool extends Struct {
+ @Bool()
+ bool a0;
+
+ @Bool()
+ bool a1;
+
+ @Bool()
+ bool a2;
+
+ @Bool()
+ bool a3;
+
+ @Bool()
+ bool a4;
+
+ @Bool()
+ bool a5;
+
+ @Bool()
+ bool a6;
+
+ @Bool()
+ bool a7;
+
+ @Bool()
+ bool a8;
+
+ @Bool()
+ bool a9;
+
+ String toString() =>
+ "(${a0}, ${a1}, ${a2}, ${a3}, ${a4}, ${a5}, ${a6}, ${a7}, ${a8}, ${a9})";
+}
+
class Struct12BytesHomogeneousFloat extends Struct {
@Float()
double a0;
@@ -940,6 +982,13 @@
String toString() => "(${[for (var i0 = 0; i0 < 8; i0 += 1) a0[i0]]})";
}
+class Struct10BytesInlineArrayBool extends Struct {
+ @Array(10)
+ Array<Bool> a0;
+
+ String toString() => "(${[for (var i0 = 0; i0 < 10; i0 += 1) a0[i0]]})";
+}
+
class StructInlineArrayIrregular extends Struct {
@Array(2)
Array<Struct3BytesInt2ByteAligned> a0;
diff --git a/tests/ffi_2/function_structs_by_value_generated_leaf_test.dart b/tests/ffi_2/function_structs_by_value_generated_leaf_test.dart
index 3199ccc..3a75d81 100644
--- a/tests/ffi_2/function_structs_by_value_generated_leaf_test.dart
+++ b/tests/ffi_2/function_structs_by_value_generated_leaf_test.dart
@@ -88,6 +88,9 @@
testPassUnion9BytesNestedIntx10Leaf();
testPassUnion16BytesNestedInlineArrayFloatx10Leaf();
testPassUnion16BytesNestedFloatx10Leaf();
+ testPassUint8Boolx9Struct10BytesHomogeneousBoolBoolLeaf();
+ testPassUint8Boolx9Struct10BytesInlineArrayBoolBoolLeaf();
+ testPassUint8Struct1ByteBoolLeaf();
testReturnStruct1ByteIntLeaf();
testReturnStruct3BytesHomogeneousUint8Leaf();
testReturnStruct3BytesInt2ByteAlignedLeaf();
@@ -5297,6 +5300,169 @@
calloc.free(a9Pointer);
}
+final passUint8Boolx9Struct10BytesHomogeneousBoolBoolLeaf =
+ ffiTestFunctions
+ .lookupFunction<
+ Int32 Function(Uint8, Bool, Bool, Bool, Bool, Bool, Bool, Bool,
+ Bool, Bool, Struct10BytesHomogeneousBool, Bool),
+ int Function(
+ int,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ Struct10BytesHomogeneousBool,
+ bool)>("PassUint8Boolx9Struct10BytesHomogeneousBoolBool",
+ isLeaf: true);
+
+/// Passing bools and a struct with bools.
+/// Exhausts the registers to test bools and the bool struct alignment on the
+/// stack.
+void testPassUint8Boolx9Struct10BytesHomogeneousBoolBoolLeaf() {
+ int a0;
+ bool a1;
+ bool a2;
+ bool a3;
+ bool a4;
+ bool a5;
+ bool a6;
+ bool a7;
+ bool a8;
+ bool a9;
+ final a10Pointer = calloc<Struct10BytesHomogeneousBool>();
+ final Struct10BytesHomogeneousBool a10 = a10Pointer.ref;
+ bool a11;
+
+ a0 = 1;
+ a1 = false;
+ a2 = true;
+ a3 = false;
+ a4 = true;
+ a5 = false;
+ a6 = true;
+ a7 = false;
+ a8 = true;
+ a9 = false;
+ a10.a0 = true;
+ a10.a1 = false;
+ a10.a2 = true;
+ a10.a3 = false;
+ a10.a4 = true;
+ a10.a5 = false;
+ a10.a6 = true;
+ a10.a7 = false;
+ a10.a8 = true;
+ a10.a9 = false;
+ a11 = true;
+
+ final result = passUint8Boolx9Struct10BytesHomogeneousBoolBoolLeaf(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
+
+ print("result = $result");
+
+ Expect.equals(11, result);
+
+ calloc.free(a10Pointer);
+}
+
+final passUint8Boolx9Struct10BytesInlineArrayBoolBoolLeaf =
+ ffiTestFunctions
+ .lookupFunction<
+ Int32 Function(Uint8, Bool, Bool, Bool, Bool, Bool, Bool, Bool,
+ Bool, Bool, Struct10BytesInlineArrayBool, Bool),
+ int Function(
+ int,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ Struct10BytesInlineArrayBool,
+ bool)>("PassUint8Boolx9Struct10BytesInlineArrayBoolBool",
+ isLeaf: true);
+
+/// Passing bools and a struct with bools.
+/// Exhausts the registers to test bools and the bool struct alignment on the
+/// stack.
+void testPassUint8Boolx9Struct10BytesInlineArrayBoolBoolLeaf() {
+ int a0;
+ bool a1;
+ bool a2;
+ bool a3;
+ bool a4;
+ bool a5;
+ bool a6;
+ bool a7;
+ bool a8;
+ bool a9;
+ final a10Pointer = calloc<Struct10BytesInlineArrayBool>();
+ final Struct10BytesInlineArrayBool a10 = a10Pointer.ref;
+ bool a11;
+
+ a0 = 1;
+ a1 = false;
+ a2 = true;
+ a3 = false;
+ a4 = true;
+ a5 = false;
+ a6 = true;
+ a7 = false;
+ a8 = true;
+ a9 = false;
+ a10.a0[0] = true;
+ a10.a0[1] = false;
+ a10.a0[2] = true;
+ a10.a0[3] = false;
+ a10.a0[4] = true;
+ a10.a0[5] = false;
+ a10.a0[6] = true;
+ a10.a0[7] = false;
+ a10.a0[8] = true;
+ a10.a0[9] = false;
+ a11 = true;
+
+ final result = passUint8Boolx9Struct10BytesInlineArrayBoolBoolLeaf(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
+
+ print("result = $result");
+
+ Expect.equals(11, result);
+
+ calloc.free(a10Pointer);
+}
+
+final passUint8Struct1ByteBoolLeaf = ffiTestFunctions.lookupFunction<
+ Bool Function(Uint8, Struct1ByteBool),
+ bool Function(
+ int, Struct1ByteBool)>("PassUint8Struct1ByteBool", isLeaf: true);
+
+/// Returning a bool.
+void testPassUint8Struct1ByteBoolLeaf() {
+ int a0;
+ final a1Pointer = calloc<Struct1ByteBool>();
+ final Struct1ByteBool a1 = a1Pointer.ref;
+
+ a0 = 1;
+ a1.a0 = false;
+
+ final result = passUint8Struct1ByteBoolLeaf(a0, a1);
+
+ print("result = $result");
+
+ Expect.equals(1 % 2 != 0, result);
+
+ calloc.free(a1Pointer);
+}
+
final returnStruct1ByteIntLeaf = ffiTestFunctions.lookupFunction<
Struct1ByteInt Function(Int8),
Struct1ByteInt Function(int)>("ReturnStruct1ByteInt", isLeaf: true);
diff --git a/tests/ffi_2/function_structs_by_value_generated_test.dart b/tests/ffi_2/function_structs_by_value_generated_test.dart
index 3c3f791..f817df0 100644
--- a/tests/ffi_2/function_structs_by_value_generated_test.dart
+++ b/tests/ffi_2/function_structs_by_value_generated_test.dart
@@ -88,6 +88,9 @@
testPassUnion9BytesNestedIntx10();
testPassUnion16BytesNestedInlineArrayFloatx10();
testPassUnion16BytesNestedFloatx10();
+ testPassUint8Boolx9Struct10BytesHomogeneousBoolBool();
+ testPassUint8Boolx9Struct10BytesInlineArrayBoolBool();
+ testPassUint8Struct1ByteBool();
testReturnStruct1ByteInt();
testReturnStruct3BytesHomogeneousUint8();
testReturnStruct3BytesInt2ByteAligned();
@@ -5226,6 +5229,164 @@
calloc.free(a9Pointer);
}
+final passUint8Boolx9Struct10BytesHomogeneousBoolBool =
+ ffiTestFunctions.lookupFunction<
+ Int32 Function(Uint8, Bool, Bool, Bool, Bool, Bool, Bool, Bool, Bool,
+ Bool, Struct10BytesHomogeneousBool, Bool),
+ int Function(
+ int,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ Struct10BytesHomogeneousBool,
+ bool)>("PassUint8Boolx9Struct10BytesHomogeneousBoolBool");
+
+/// Passing bools and a struct with bools.
+/// Exhausts the registers to test bools and the bool struct alignment on the
+/// stack.
+void testPassUint8Boolx9Struct10BytesHomogeneousBoolBool() {
+ int a0;
+ bool a1;
+ bool a2;
+ bool a3;
+ bool a4;
+ bool a5;
+ bool a6;
+ bool a7;
+ bool a8;
+ bool a9;
+ final a10Pointer = calloc<Struct10BytesHomogeneousBool>();
+ final Struct10BytesHomogeneousBool a10 = a10Pointer.ref;
+ bool a11;
+
+ a0 = 1;
+ a1 = false;
+ a2 = true;
+ a3 = false;
+ a4 = true;
+ a5 = false;
+ a6 = true;
+ a7 = false;
+ a8 = true;
+ a9 = false;
+ a10.a0 = true;
+ a10.a1 = false;
+ a10.a2 = true;
+ a10.a3 = false;
+ a10.a4 = true;
+ a10.a5 = false;
+ a10.a6 = true;
+ a10.a7 = false;
+ a10.a8 = true;
+ a10.a9 = false;
+ a11 = true;
+
+ final result = passUint8Boolx9Struct10BytesHomogeneousBoolBool(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
+
+ print("result = $result");
+
+ Expect.equals(11, result);
+
+ calloc.free(a10Pointer);
+}
+
+final passUint8Boolx9Struct10BytesInlineArrayBoolBool =
+ ffiTestFunctions.lookupFunction<
+ Int32 Function(Uint8, Bool, Bool, Bool, Bool, Bool, Bool, Bool, Bool,
+ Bool, Struct10BytesInlineArrayBool, Bool),
+ int Function(
+ int,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ bool,
+ Struct10BytesInlineArrayBool,
+ bool)>("PassUint8Boolx9Struct10BytesInlineArrayBoolBool");
+
+/// Passing bools and a struct with bools.
+/// Exhausts the registers to test bools and the bool struct alignment on the
+/// stack.
+void testPassUint8Boolx9Struct10BytesInlineArrayBoolBool() {
+ int a0;
+ bool a1;
+ bool a2;
+ bool a3;
+ bool a4;
+ bool a5;
+ bool a6;
+ bool a7;
+ bool a8;
+ bool a9;
+ final a10Pointer = calloc<Struct10BytesInlineArrayBool>();
+ final Struct10BytesInlineArrayBool a10 = a10Pointer.ref;
+ bool a11;
+
+ a0 = 1;
+ a1 = false;
+ a2 = true;
+ a3 = false;
+ a4 = true;
+ a5 = false;
+ a6 = true;
+ a7 = false;
+ a8 = true;
+ a9 = false;
+ a10.a0[0] = true;
+ a10.a0[1] = false;
+ a10.a0[2] = true;
+ a10.a0[3] = false;
+ a10.a0[4] = true;
+ a10.a0[5] = false;
+ a10.a0[6] = true;
+ a10.a0[7] = false;
+ a10.a0[8] = true;
+ a10.a0[9] = false;
+ a11 = true;
+
+ final result = passUint8Boolx9Struct10BytesInlineArrayBoolBool(
+ a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
+
+ print("result = $result");
+
+ Expect.equals(11, result);
+
+ calloc.free(a10Pointer);
+}
+
+final passUint8Struct1ByteBool = ffiTestFunctions.lookupFunction<
+ Bool Function(Uint8, Struct1ByteBool),
+ bool Function(int, Struct1ByteBool)>("PassUint8Struct1ByteBool");
+
+/// Returning a bool.
+void testPassUint8Struct1ByteBool() {
+ int a0;
+ final a1Pointer = calloc<Struct1ByteBool>();
+ final Struct1ByteBool a1 = a1Pointer.ref;
+
+ a0 = 1;
+ a1.a0 = false;
+
+ final result = passUint8Struct1ByteBool(a0, a1);
+
+ print("result = $result");
+
+ Expect.equals(1 % 2 != 0, result);
+
+ calloc.free(a1Pointer);
+}
+
final returnStruct1ByteInt = ffiTestFunctions.lookupFunction<
Struct1ByteInt Function(Int8),
Struct1ByteInt Function(int)>("ReturnStruct1ByteInt");
diff --git a/tools/VERSION b/tools/VERSION
index c4e82d3..f8b3ab0 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 15
PATCH 0
-PRERELEASE 232
+PRERELEASE 233
PRERELEASE_PATCH 0
\ No newline at end of file