532c116cd2
This CL implements `NativeFinalizer` in the GC. `FinalizerEntry`s are extended to track `external_size` and in which `Heap::Space` the finalizable value is. On attaching a native finalizer, the external size is added to the relevant heap. When the finalizable value is promoted from new to old space, the external size is promoted as well. And when a native finalizer is run or is detached, the external size is removed from the relevant heap again. In contrast to Dart `Finalizer`s, `NativeFinalizer`s are run on isolate shutdown. When the `NativeFinalizer`s themselves are collected, the finalizers are not run. Users should stick the native finalizer in a global variable to ensure finalization. We will revisit this design when we add send and exit support, because there is a design space to explore what to do in that case. This current solution promises the least to users. In this implementation native finalizers have a Dart entry to clean up the entries from the `all_entries` field of the finalizer. We should consider using another data structure that avoids the need for this Dart entry. See the TODO left in the code. Bug: https://github.com/dart-lang/sdk/issues/47777 TEST=runtime/tests/vm/dart(_2)/isolates/fast_object_copy_test.dart TEST=runtime/vm/object_test.cc TEST=tests/ffi(_2)/vmspecific_native_finalizer_* Change-Id: I8f594c80c3c344ad83e1f2de10de028eb8456121 Cq-Include-Trybots: luci.dart.try:vm-kernel-reload-rollback-linux-debug-x64-try,vm-kernel-reload-linux-debug-x64-try,vm-ffi-android-debug-arm64c-try,dart-sdk-mac-arm64-try,vm-kernel-mac-release-arm64-try,pkg-mac-release-arm64-try,vm-kernel-precomp-nnbd-mac-release-arm64-try,vm-kernel-win-debug-x64c-try,vm-kernel-win-debug-x64-try,vm-kernel-precomp-win-debug-x64c-try,vm-kernel-nnbd-win-release-ia32-try,vm-ffi-android-debug-arm-try,vm-precomp-ffi-qemu-linux-release-arm-try,vm-kernel-mac-debug-x64-try,vm-kernel-nnbd-mac-debug-x64-try,vm-kernel-nnbd-linux-debug-ia32-try,benchmark-linux-try,flutter-frontend-try,pkg-linux-debug-try,vm-kernel-asan-linux-release-x64-try,vm-kernel-gcc-linux-try,vm-kernel-optcounter-threshold-linux-release-x64-try,vm-kernel-precomp-linux-debug-simarm_x64-try,vm-kernel-precomp-obfuscate-linux-release-x64-try,vm-kernel-precomp-linux-debug-x64-try,vm-kernel-precomp-linux-debug-x64c-try Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/236320 Reviewed-by: Martin Kustermann <kustermann@google.com> Reviewed-by: Slava Egorov <vegorov@google.com> Commit-Queue: Daco Harkes <dacoharkes@google.com>
1877 lines
50 KiB
Dart
1877 lines
50 KiB
Dart
// 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.
|
|
|
|
// THIS FILE IS GENERATED. DO NOT EDIT.
|
|
//
|
|
// Instead modify 'pkg/analyzer/messages.yaml' and run
|
|
// 'dart run pkg/analyzer/tool/messages/generate.dart' to update.
|
|
|
|
import "package:analyzer/error/error.dart";
|
|
import "package:analyzer/src/error/analyzer_error_code.dart";
|
|
|
|
// It is hard to visually separate each code's _doc comment_ from its published
|
|
// _documentation comment_ when each is written as an end-of-line comment.
|
|
// ignore_for_file: slash_for_doc_comments
|
|
|
|
class FfiCode extends AnalyzerErrorCode {
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
static const FfiCode ABI_SPECIFIC_INTEGER_INVALID = FfiCode(
|
|
'ABI_SPECIFIC_INTEGER_INVALID',
|
|
"Classes extending 'AbiSpecificInteger' must have exactly one const "
|
|
"constructor, no other members, and no type arguments.",
|
|
correctionMessage:
|
|
"Try removing all type arguments, removing all members, and adding one "
|
|
"const constructor.",
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
static const FfiCode ABI_SPECIFIC_INTEGER_MAPPING_EXTRA = FfiCode(
|
|
'ABI_SPECIFIC_INTEGER_MAPPING_EXTRA',
|
|
"Classes extending 'AbiSpecificInteger' must have exactly one "
|
|
"'AbiSpecificIntegerMapping' annotation specifying the mapping from "
|
|
"ABI to a 'NativeType' integer with a fixed size.",
|
|
correctionMessage: "Try removing the extra annotation.",
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
static const FfiCode ABI_SPECIFIC_INTEGER_MAPPING_MISSING = FfiCode(
|
|
'ABI_SPECIFIC_INTEGER_MAPPING_MISSING',
|
|
"Classes extending 'AbiSpecificInteger' must have exactly one "
|
|
"'AbiSpecificIntegerMapping' annotation specifying the mapping from "
|
|
"ABI to a 'NativeType' integer with a fixed size.",
|
|
correctionMessage: "Try adding an annotation.",
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
static const FfiCode ABI_SPECIFIC_INTEGER_MAPPING_UNSUPPORTED = FfiCode(
|
|
'ABI_SPECIFIC_INTEGER_MAPPING_UNSUPPORTED',
|
|
"Only mappings to 'Int8', 'Int16', 'Int32', 'Int64', 'Uint8', 'Uint16', "
|
|
"'UInt32', and 'Uint64' are supported.",
|
|
correctionMessage:
|
|
"Try changing the value to 'Int8', 'Int16', 'Int32', 'Int64', 'Uint8', "
|
|
"'Uint16', 'UInt32', or 'Uint64'.",
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when a field that's declared in a
|
|
// subclass of `Struct` and has the type `Pointer` also has an annotation
|
|
// associated with it.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the field `p`, which
|
|
// has the type `Pointer` and is declared in a subclass of `Struct`, has the
|
|
// annotation `@Double()`:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// [!@Double()!]
|
|
// external Pointer<Int8> p;
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Remove the annotations from the field:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// external Pointer<Int8> p;
|
|
// }
|
|
// ```
|
|
static const FfiCode ANNOTATION_ON_POINTER_FIELD = FfiCode(
|
|
'ANNOTATION_ON_POINTER_FIELD',
|
|
"Fields in a struct class whose type is 'Pointer' shouldn't have any "
|
|
"annotations.",
|
|
correctionMessage: "Try removing the annotation.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the name of the argument
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when an invocation of either
|
|
// `Pointer.asFunction` or `DynamicLibrary.lookupFunction` has an `isLeaf`
|
|
// argument whose value isn't a constant expression.
|
|
//
|
|
// The analyzer also produces this diagnostic when the value of the
|
|
// `exceptionalReturn` argument of `Pointer.fromFunction`.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the value of the
|
|
// `isLeaf` argument is a parameter, and hence isn't a constant:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// int Function(int) fromPointer(
|
|
// Pointer<NativeFunction<Int8 Function(Int8)>> p, bool isLeaf) {
|
|
// return p.asFunction(isLeaf: [!isLeaf!]);
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// If there's a suitable constant that can be used, then replace the argument
|
|
// with a constant:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// const isLeaf = false;
|
|
//
|
|
// int Function(int) fromPointer(Pointer<NativeFunction<Int8 Function(Int8)>> p) {
|
|
// return p.asFunction(isLeaf: isLeaf);
|
|
// }
|
|
// ```
|
|
//
|
|
// If there isn't a suitable constant, then replace the argument with a
|
|
// boolean literal:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// int Function(int) fromPointer(Pointer<NativeFunction<Int8 Function(Int8)>> p) {
|
|
// return p.asFunction(isLeaf: true);
|
|
// }
|
|
// ```
|
|
static const FfiCode ARGUMENT_MUST_BE_A_CONSTANT = FfiCode(
|
|
'ARGUMENT_MUST_BE_A_CONSTANT',
|
|
"Argument '{0}' must be a constant.",
|
|
correctionMessage: "Try replacing the value with a literal or const.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the name of the struct or union class
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when a subclass of either `Struct`
|
|
// or `Union` implements `Finalizable`.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the class `S`
|
|
// implements `Finalizable`:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class [!S!] extends Struct implements Finalizable {
|
|
// external Pointer notEmpty;
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Try removing the implements clause from the class:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class S extends Struct {
|
|
// external Pointer notEmpty;
|
|
// }
|
|
// ```
|
|
static const FfiCode COMPOUND_IMPLEMENTS_FINALIZABLE = FfiCode(
|
|
'COMPOUND_IMPLEMENTS_FINALIZABLE',
|
|
"The class '{0}' can't implement Finalizable.",
|
|
correctionMessage: "Try removing the implements clause from '{0}'.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when a subclass of either `Struct`
|
|
// or `Union` is instantiated using a generative constructor.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the class `C` is being
|
|
// instantiated using a generative constructor:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// @Int32()
|
|
// external int a;
|
|
// }
|
|
//
|
|
// void f() {
|
|
// [!C!]();
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// If you need to allocate the structure described by the class, then use the
|
|
// `ffi` package to do so:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
// import 'package:ffi/ffi.dart';
|
|
//
|
|
// class C extends Struct {
|
|
// @Int32()
|
|
// external int a;
|
|
// }
|
|
//
|
|
// void f() {
|
|
// final pointer = calloc.allocate<C>(4);
|
|
// final c = pointer.ref;
|
|
// print(c);
|
|
// calloc.free(pointer);
|
|
// }
|
|
// ```
|
|
static const FfiCode CREATION_OF_STRUCT_OR_UNION = FfiCode(
|
|
'CREATION_OF_STRUCT_OR_UNION',
|
|
"Subclasses of 'Struct' and 'Union' are backed by native memory, and can't "
|
|
"be instantiated by a generative constructor.",
|
|
correctionMessage:
|
|
"Try allocating it via allocation, or load from a 'Pointer'.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the name of the subclass
|
|
* 1: the name of the superclass
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when a subclass of `Struct` or
|
|
// `Union` doesn't have any fields. Having an empty `Struct` or `Union`
|
|
// isn't supported.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the class `C`, which
|
|
// extends `Struct`, doesn't declare any fields:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class [!C!] extends Struct {}
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// If the class is intended to be a struct, then declare one or more fields:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// @Int32()
|
|
// external int x;
|
|
// }
|
|
// ```
|
|
//
|
|
// If the class is intended to be used as a type argument to `Pointer`, then
|
|
// make it a subclass of `Opaque`:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Opaque {}
|
|
// ```
|
|
//
|
|
// If the class isn't intended to be a struct, then remove or change the
|
|
// extends clause:
|
|
//
|
|
// ```dart
|
|
// class C {}
|
|
// ```
|
|
static const FfiCode EMPTY_STRUCT = FfiCode(
|
|
'EMPTY_STRUCT',
|
|
"The class '{0}' can't be empty because it's a subclass of '{1}'.",
|
|
correctionMessage:
|
|
"Try adding a field to '{0}' or use a different superclass.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when a field in a subclass of
|
|
// `Struct` has more than one annotation describing the native type of the
|
|
// field.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the field `x` has two
|
|
// annotations describing the native type of the field:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// @Int32()
|
|
// [!@Int16()!]
|
|
// external int x;
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Remove all but one of the annotations:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
// class C extends Struct {
|
|
// @Int32()
|
|
// external int x;
|
|
// }
|
|
// ```
|
|
static const FfiCode EXTRA_ANNOTATION_ON_STRUCT_FIELD = FfiCode(
|
|
'EXTRA_ANNOTATION_ON_STRUCT_FIELD',
|
|
"Fields in a struct class must have exactly one annotation indicating the "
|
|
"native type.",
|
|
correctionMessage: "Try removing the extra annotation.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when a field in a subclass of
|
|
// `Struct` has more than one annotation describing the size of the native
|
|
// array.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the field `a0` has two
|
|
// annotations that specify the size of the native array:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// @Array(4)
|
|
// [!@Array(8)!]
|
|
// external Array<Uint8> a0;
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Remove all but one of the annotations:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// @Array(8)
|
|
// external Array<Uint8> a0;
|
|
// }
|
|
// ```
|
|
static const FfiCode EXTRA_SIZE_ANNOTATION_CARRAY = FfiCode(
|
|
'EXTRA_SIZE_ANNOTATION_CARRAY',
|
|
"'Array's must have exactly one 'Array' annotation.",
|
|
correctionMessage: "Try removing the extra annotation.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
static const FfiCode FFI_NATIVE_MUST_BE_EXTERNAL = FfiCode(
|
|
'FFI_NATIVE_MUST_BE_EXTERNAL',
|
|
"FfiNative functions must be declared external.",
|
|
correctionMessage: "Add the `external` keyword to the function.",
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
static const FfiCode
|
|
FFI_NATIVE_ONLY_CLASSES_EXTENDING_NATIVEFIELDWRAPPERCLASS1_CAN_BE_POINTER =
|
|
FfiCode(
|
|
'FFI_NATIVE_ONLY_CLASSES_EXTENDING_NATIVEFIELDWRAPPERCLASS1_CAN_BE_POINTER',
|
|
"Only classes extending NativeFieldWrapperClass1 can be passed as Pointer.",
|
|
correctionMessage: "Pass as Handle instead.",
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the expected number of parameters
|
|
* 1: the actual number of parameters
|
|
*/
|
|
static const FfiCode FFI_NATIVE_UNEXPECTED_NUMBER_OF_PARAMETERS = FfiCode(
|
|
'FFI_NATIVE_UNEXPECTED_NUMBER_OF_PARAMETERS',
|
|
"Unexpected number of FfiNative annotation parameters. Expected {0} but "
|
|
"has {1}.",
|
|
correctionMessage: "Make sure parameters match the function annotated.",
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the expected number of parameters
|
|
* 1: the actual number of parameters
|
|
*/
|
|
static const FfiCode
|
|
FFI_NATIVE_UNEXPECTED_NUMBER_OF_PARAMETERS_WITH_RECEIVER = FfiCode(
|
|
'FFI_NATIVE_UNEXPECTED_NUMBER_OF_PARAMETERS_WITH_RECEIVER',
|
|
"Unexpected number of FfiNative annotation parameters. Expected {0} but "
|
|
"has {1}. FfiNative instance method annotation must have receiver as "
|
|
"first argument.",
|
|
correctionMessage:
|
|
"Make sure parameters match the function annotated, including an extra "
|
|
"first parameter for the receiver.",
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when a constructor in a subclass of
|
|
// either `Struct` or `Union` has one or more field initializers.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the class `C` has a
|
|
// constructor with an initializer for the field `f`:
|
|
//
|
|
// ```dart
|
|
// // @dart = 2.9
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// @Int32()
|
|
// int f;
|
|
//
|
|
// C() : [!f = 0!];
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Remove the field initializer:
|
|
//
|
|
// ```dart
|
|
// // @dart = 2.9
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// @Int32()
|
|
// int f;
|
|
//
|
|
// C();
|
|
// }
|
|
// ```
|
|
static const FfiCode FIELD_INITIALIZER_IN_STRUCT = FfiCode(
|
|
'FIELD_INITIALIZER_IN_STRUCT',
|
|
"Constructors in subclasses of 'Struct' and 'Union' can't have field "
|
|
"initializers.",
|
|
correctionMessage:
|
|
"Try removing the field initializer and marking the field as external.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when a field in a subclass of
|
|
// `Struct` has an initializer.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the field `p` has an
|
|
// initializer:
|
|
//
|
|
// ```dart
|
|
// // @dart = 2.9
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// Pointer [!p!] = nullptr;
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Remove the initializer:
|
|
//
|
|
// ```dart
|
|
// // @dart = 2.9
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// Pointer p;
|
|
// }
|
|
// ```
|
|
static const FfiCode FIELD_IN_STRUCT_WITH_INITIALIZER = FfiCode(
|
|
'FIELD_IN_STRUCT_WITH_INITIALIZER',
|
|
"Fields in subclasses of 'Struct' and 'Union' can't have initializers.",
|
|
correctionMessage:
|
|
"Try removing the initializer and marking the field as external.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when a field in a subclass of either
|
|
// `Struct` or `Union` isn't marked as being `external`.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the field `a` isn't
|
|
// marked as being `external`:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// @Int16()
|
|
// int [!a!];
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Add the required `external` modifier:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// @Int16()
|
|
// external int a;
|
|
// }
|
|
// ```
|
|
static const FfiCode FIELD_MUST_BE_EXTERNAL_IN_STRUCT = FfiCode(
|
|
'FIELD_MUST_BE_EXTERNAL_IN_STRUCT',
|
|
"Fields of 'Struct' and 'Union' subclasses must be marked external.",
|
|
correctionMessage: "Try adding the 'external' modifier.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the name of the struct class
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when a subclass of either `Struct`
|
|
// or `Union` has a type parameter.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the class `S` defines
|
|
// the type parameter `T`:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class [!S!]<T> extends Struct {
|
|
// external Pointer notEmpty;
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Remove the type parameters from the class:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class S extends Struct {
|
|
// external Pointer notEmpty;
|
|
// }
|
|
// ```
|
|
static const FfiCode GENERIC_STRUCT_SUBCLASS = FfiCode(
|
|
'GENERIC_STRUCT_SUBCLASS',
|
|
"The class '{0}' can't extend 'Struct' or 'Union' because '{0}' is "
|
|
"generic.",
|
|
correctionMessage: "Try removing the type parameters from '{0}'.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when an invocation of the method
|
|
// `Pointer.fromFunction` has a second argument (the exceptional return
|
|
// value) and the type to be returned from the invocation is either `void`,
|
|
// `Handle` or `Pointer`.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because a second argument is
|
|
// provided when the return type of `f` is `void`:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// typedef T = Void Function(Int8);
|
|
//
|
|
// void f(int i) {}
|
|
//
|
|
// void g() {
|
|
// Pointer.fromFunction<T>(f, [!42!]);
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Remove the exception value:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// typedef T = Void Function(Int8);
|
|
//
|
|
// void f(int i) {}
|
|
//
|
|
// void g() {
|
|
// Pointer.fromFunction<T>(f);
|
|
// }
|
|
// ```
|
|
static const FfiCode INVALID_EXCEPTION_VALUE = FfiCode(
|
|
'INVALID_EXCEPTION_VALUE',
|
|
"The method 'Pointer.fromFunction' can't have an exceptional return value "
|
|
"(the second argument) when the return type of the function is either "
|
|
"'void', 'Handle' or 'Pointer'.",
|
|
correctionMessage: "Try removing the exceptional return value.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the type of the field
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when a field in a subclass of
|
|
// `Struct` has a type other than `int`, `double`, `Array`, `Pointer`, or
|
|
// subtype of `Struct` or `Union`.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the field `str` has
|
|
// the type `String`, which isn't one of the allowed types for fields in a
|
|
// subclass of `Struct`:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// external [!String!] s;
|
|
//
|
|
// @Int32()
|
|
// external int i;
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Use one of the allowed types for the field:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
// import 'package:ffi/ffi.dart';
|
|
//
|
|
// class C extends Struct {
|
|
// external Pointer<Utf8> s;
|
|
//
|
|
// @Int32()
|
|
// external int i;
|
|
// }
|
|
// ```
|
|
static const FfiCode INVALID_FIELD_TYPE_IN_STRUCT = FfiCode(
|
|
'INVALID_FIELD_TYPE_IN_STRUCT',
|
|
"Fields in struct classes can't have the type '{0}'. They can only be "
|
|
"declared as 'int', 'double', 'Array', 'Pointer', or subtype of "
|
|
"'Struct' or 'Union'.",
|
|
correctionMessage:
|
|
"Try using 'int', 'double', 'Array', 'Pointer', or subtype of 'Struct' "
|
|
"or 'Union'.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when the value of the `isLeaf`
|
|
// argument in an invocation of either `Pointer.asFunction` or
|
|
// `DynamicLibrary.lookupFunction` is `true` and the function that would be
|
|
// returned would have a return type of `Handle`.
|
|
//
|
|
// The analyzer also produces this diagnostic when the value of the `isLeaf`
|
|
// argument in an `FfiNative` annotation is `true` and the type argument on
|
|
// the annotation is a function type whose return type is `Handle`.
|
|
//
|
|
// In all of these cases, leaf calls are only supported for the types `bool`,
|
|
// `int`, `float`, `double`, and, as a return type `void`.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the function `p`
|
|
// returns a `Handle`, but the `isLeaf` argument is `true`:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// void f(Pointer<NativeFunction<Handle Function()>> p) {
|
|
// [!p.asFunction<Object Function()>(isLeaf: true)!];
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// If the function returns a handle, then remove the `isLeaf` argument:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// void f(Pointer<NativeFunction<Handle Function()>> p) {
|
|
// p.asFunction<Object Function()>();
|
|
// }
|
|
// ```
|
|
//
|
|
// If the function returns one of the supported types, then correct the type
|
|
// information:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// void f(Pointer<NativeFunction<Int32 Function()>> p) {
|
|
// p.asFunction<int Function()>(isLeaf: true);
|
|
// }
|
|
// ```
|
|
static const FfiCode LEAF_CALL_MUST_NOT_RETURN_HANDLE = FfiCode(
|
|
'LEAF_CALL_MUST_NOT_RETURN_HANDLE',
|
|
"FFI leaf call can't return a 'Handle'.",
|
|
correctionMessage: "Try changing the return type to primitive or struct.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when the value of the `isLeaf`
|
|
// argument in an invocation of either `Pointer.asFunction` or
|
|
// `DynamicLibrary.lookupFunction` is `true` and the function that would be
|
|
// returned would have a parameter of type `Handle`.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the function `p` has a
|
|
// parameter of type `Handle`, but the `isLeaf` argument is `true`:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// void f(Pointer<NativeFunction<Void Function(Handle)>> p) {
|
|
// [!p.asFunction<void Function(Object)>(isLeaf: true)!];
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// If the function has at least one parameter of type `Handle`, then remove
|
|
// the `isLeaf` argument:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// void f(Pointer<NativeFunction<Void Function(Handle)>> p) {
|
|
// p.asFunction<void Function(Object)>();
|
|
// }
|
|
// ```
|
|
//
|
|
// If none of the function's parameters are `Handle`s, then correct the type
|
|
// information:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// void f(Pointer<NativeFunction<Void Function(Int8)>> p) {
|
|
// p.asFunction<void Function(int)>(isLeaf: true);
|
|
// }
|
|
// ```
|
|
static const FfiCode LEAF_CALL_MUST_NOT_TAKE_HANDLE = FfiCode(
|
|
'LEAF_CALL_MUST_NOT_TAKE_HANDLE',
|
|
"FFI leaf call can't take arguments of type 'Handle'.",
|
|
correctionMessage: "Try changing the argument type to primitive or struct.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when the annotation on a field in a
|
|
// subclass of `Struct` or `Union` doesn't match the Dart type of the field.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the annotation
|
|
// `Double` doesn't match the Dart type `int`:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// [!@Double()!]
|
|
// external int x;
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// If the type of the field is correct, then change the annotation to match:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// @Int32()
|
|
// external int x;
|
|
// }
|
|
// ```
|
|
//
|
|
// If the annotation is correct, then change the type of the field to match:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// @Double()
|
|
// external double x;
|
|
// }
|
|
// ```
|
|
static const FfiCode MISMATCHED_ANNOTATION_ON_STRUCT_FIELD = FfiCode(
|
|
'MISMATCHED_ANNOTATION_ON_STRUCT_FIELD',
|
|
"The annotation doesn't match the declared type of the field.",
|
|
correctionMessage:
|
|
"Try using a different annotation or changing the declared type to "
|
|
"match.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when a field in a subclass of
|
|
// `Struct` or `Union` whose type requires an annotation doesn't have one.
|
|
// The Dart types `int`, `double`, and `Array` are used to represent multiple
|
|
// C types, and the annotation specifies which of the compatible C types the
|
|
// field represents.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the field `x` doesn't
|
|
// have an annotation indicating the underlying width of the integer value:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// external [!int!] x;
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Add an appropriate annotation to the field:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// @Int64()
|
|
// external int x;
|
|
// }
|
|
// ```
|
|
static const FfiCode MISSING_ANNOTATION_ON_STRUCT_FIELD = FfiCode(
|
|
'MISSING_ANNOTATION_ON_STRUCT_FIELD',
|
|
"Fields in a struct class must either have the type 'Pointer' or an "
|
|
"annotation indicating the native type.",
|
|
correctionMessage: "Try adding an annotation.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when an invocation of the method
|
|
// `Pointer.fromFunction` doesn't have a second argument (the exceptional
|
|
// return value) when the type to be returned from the invocation is neither
|
|
// `void`, `Handle`, nor `Pointer`.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the type returned by
|
|
// `f` is expected to be an 8-bit integer but the call to `fromFunction`
|
|
// doesn't include an exceptional return argument:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// int f(int i) => i * 2;
|
|
//
|
|
// void g() {
|
|
// Pointer.[!fromFunction!]<Int8 Function(Int8)>(f);
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Add an exceptional return type:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// int f(int i) => i * 2;
|
|
//
|
|
// void g() {
|
|
// Pointer.fromFunction<Int8 Function(Int8)>(f, 0);
|
|
// }
|
|
// ```
|
|
static const FfiCode MISSING_EXCEPTION_VALUE = FfiCode(
|
|
'MISSING_EXCEPTION_VALUE',
|
|
"The method 'Pointer.fromFunction' must have an exceptional return value "
|
|
"(the second argument) when the return type of the function is neither "
|
|
"'void', 'Handle', nor 'Pointer'.",
|
|
correctionMessage: "Try adding an exceptional return value.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the type of the field
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when a field in a subclass of
|
|
// `Struct` or `Union` doesn't have a type annotation. Every field must have
|
|
// an explicit type, and the type must either be `int`, `double`, `Pointer`,
|
|
// or a subclass of either `Struct` or `Union`.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the field `str`
|
|
// doesn't have a type annotation:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// external var [!str!];
|
|
//
|
|
// @Int32()
|
|
// external int i;
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Explicitly specify the type of the field:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
// import 'package:ffi/ffi.dart';
|
|
//
|
|
// class C extends Struct {
|
|
// external Pointer<Utf8> str;
|
|
//
|
|
// @Int32()
|
|
// external int i;
|
|
// }
|
|
// ```
|
|
static const FfiCode MISSING_FIELD_TYPE_IN_STRUCT = FfiCode(
|
|
'MISSING_FIELD_TYPE_IN_STRUCT',
|
|
"Fields in struct classes must have an explicitly declared type of 'int', "
|
|
"'double' or 'Pointer'.",
|
|
correctionMessage: "Try using 'int', 'double' or 'Pointer'.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when a field in a subclass of either
|
|
// `Struct` or `Union` has a type of `Array` but doesn't have a single
|
|
// `Array` annotation indicating the dimensions of the array.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the field `a0` doesn't
|
|
// have an `Array` annotation:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// external [!Array<Uint8>!] a0;
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Ensure that there's exactly one `Array` annotation on the field:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// @Array(8)
|
|
// external Array<Uint8> a0;
|
|
// }
|
|
// ```
|
|
static const FfiCode MISSING_SIZE_ANNOTATION_CARRAY = FfiCode(
|
|
'MISSING_SIZE_ANNOTATION_CARRAY',
|
|
"Fields of type 'Array' must have exactly one 'Array' annotation.",
|
|
correctionMessage:
|
|
"Try adding an 'Array' annotation, or removing all but one of the "
|
|
"annotations.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the type that should be a valid dart:ffi native type.
|
|
* 1: the name of the function whose invocation depends on this relationship
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when an invocation of either
|
|
// `Pointer.fromFunction` or `DynamicLibrary.lookupFunction` has a type
|
|
// argument(whether explicit or inferred) that isn't a native function type.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the type `T` can be
|
|
// any subclass of `Function` but the type argument for `fromFunction` is
|
|
// required to be a native function type:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// int f(int i) => i * 2;
|
|
//
|
|
// class C<T extends Function> {
|
|
// void g() {
|
|
// Pointer.fromFunction<[!T!]>(f, 0);
|
|
// }
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Use a native function type as the type argument to the invocation:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// int f(int i) => i * 2;
|
|
//
|
|
// class C<T extends Function> {
|
|
// void g() {
|
|
// Pointer.fromFunction<Int32 Function(Int32)>(f, 0);
|
|
// }
|
|
// }
|
|
// ```
|
|
static const FfiCode MUST_BE_A_NATIVE_FUNCTION_TYPE = FfiCode(
|
|
'MUST_BE_A_NATIVE_FUNCTION_TYPE',
|
|
"The type '{0}' given to '{1}' must be a valid 'dart:ffi' native function "
|
|
"type.",
|
|
correctionMessage:
|
|
"Try changing the type to only use members for 'dart:ffi'.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the type that should be a subtype
|
|
* 1: the supertype that the subtype is compared to
|
|
* 2: the name of the function whose invocation depends on this relationship
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic in two cases:
|
|
// - In an invocation of `Pointer.fromFunction` where the type argument
|
|
// (whether explicit or inferred) isn't a supertype of the type of the
|
|
// function passed as the first argument to the method.
|
|
// - In an invocation of `DynamicLibrary.lookupFunction` where the first type
|
|
// argument isn't a supertype of the second type argument.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the type of the
|
|
// function `f` (`String Function(int)`) isn't a subtype of the type
|
|
// argument `T` (`Int8 Function(Int8)`):
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// typedef T = Int8 Function(Int8);
|
|
//
|
|
// double f(double i) => i;
|
|
//
|
|
// void g() {
|
|
// Pointer.fromFunction<T>([!f!], 5.0);
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// If the function is correct, then change the type argument to match:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// typedef T = Float Function(Float);
|
|
//
|
|
// double f(double i) => i;
|
|
//
|
|
// void g() {
|
|
// Pointer.fromFunction<T>(f, 5.0);
|
|
// }
|
|
// ```
|
|
//
|
|
// If the type argument is correct, then change the function to match:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// typedef T = Int8 Function(Int8);
|
|
//
|
|
// int f(int i) => i;
|
|
//
|
|
// void g() {
|
|
// Pointer.fromFunction<T>(f, 5);
|
|
// }
|
|
// ```
|
|
static const FfiCode MUST_BE_A_SUBTYPE = FfiCode(
|
|
'MUST_BE_A_SUBTYPE',
|
|
"The type '{0}' must be a subtype of '{1}' for '{2}'.",
|
|
correctionMessage: "Try changing one or both of the type arguments.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the name of the function, method, or constructor having type arguments
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when the type arguments to a method
|
|
// are required to be known at compile time, but a type parameter, whose
|
|
// value can't be known at compile time, is used as a type argument.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the type argument to
|
|
// `Pointer.asFunction` must be known at compile time, but the type parameter
|
|
// `R`, which isn't known at compile time, is being used as the type
|
|
// argument:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// typedef T = int Function(int);
|
|
//
|
|
// class C<R extends T> {
|
|
// void m(Pointer<NativeFunction<T>> p) {
|
|
// p.asFunction<[!R!]>();
|
|
// }
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Remove any uses of type parameters:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C {
|
|
// void m(Pointer<NativeFunction<Int64 Function(Int64)>> p) {
|
|
// p.asFunction<int Function(int)>();
|
|
// }
|
|
// }
|
|
// ```
|
|
static const FfiCode NON_CONSTANT_TYPE_ARGUMENT = FfiCode(
|
|
'NON_CONSTANT_TYPE_ARGUMENT',
|
|
"The type arguments to '{0}' must be known at compile time, so they can't "
|
|
"be type parameters.",
|
|
correctionMessage: "Try changing the type argument to be a constant type.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the type that should be a valid dart:ffi native type.
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when the method `asFunction` is
|
|
// invoked on a pointer to a native function, but the signature of the native
|
|
// function isn't a valid C function signature.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because function signature
|
|
// associated with the pointer `p` (`FNative`) isn't a valid C function
|
|
// signature:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// typedef FNative = int Function(int);
|
|
// typedef F = int Function(int);
|
|
//
|
|
// class C {
|
|
// void f(Pointer<NativeFunction<FNative>> p) {
|
|
// p.asFunction<[!F!]>();
|
|
// }
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Make the `NativeFunction` signature a valid C signature:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// typedef FNative = Int8 Function(Int8);
|
|
// typedef F = int Function(int);
|
|
//
|
|
// class C {
|
|
// void f(Pointer<NativeFunction<FNative>> p) {
|
|
// p.asFunction<F>();
|
|
// }
|
|
// }
|
|
// ```
|
|
static const FfiCode NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER = FfiCode(
|
|
'NON_NATIVE_FUNCTION_TYPE_ARGUMENT_TO_POINTER',
|
|
"Can't invoke 'asFunction' because the function signature '{0}' for the "
|
|
"pointer isn't a valid C function signature.",
|
|
correctionMessage:
|
|
"Try changing the function argument in 'NativeFunction' to only use "
|
|
"NativeTypes.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when a dimension given in an `Array`
|
|
// annotation is less than or equal to zero (`0`).
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because an array dimension of
|
|
// `-1` was provided:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class MyStruct extends Struct {
|
|
// @Array([!-8!])
|
|
// external Array<Uint8> a0;
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Change the dimension to be a positive integer:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class MyStruct extends Struct {
|
|
// @Array(8)
|
|
// external Array<Uint8> a0;
|
|
// }
|
|
// ```
|
|
static const FfiCode NON_POSITIVE_ARRAY_DIMENSION = FfiCode(
|
|
'NON_POSITIVE_ARRAY_DIMENSION',
|
|
"Array dimensions must be positive numbers.",
|
|
correctionMessage: "Try changing the input to a positive number.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the type of the field
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when the type argument for the class
|
|
// `Array` isn't one of the valid types: either a native integer, `Float`,
|
|
// `Double`, `Pointer`, or subtype of `Struct`, `Union`, or
|
|
// `AbiSpecificInteger`.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the type argument to
|
|
// `Array` is `Void`, and `Void` isn't one of the valid types:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// @Array(8)
|
|
// external Array<[!Void!]> a0;
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Change the type argument to one of the valid types:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// @Array(8)
|
|
// external Array<Uint8> a0;
|
|
// }
|
|
// ```
|
|
static const FfiCode NON_SIZED_TYPE_ARGUMENT = FfiCode(
|
|
'NON_SIZED_TYPE_ARGUMENT',
|
|
"The type '{1}' isn't a valid type argument for '{0}'. The type argument "
|
|
"must be a native integer, 'Float', 'Double', 'Pointer', or subtype of "
|
|
"'Struct', 'Union', or 'AbiSpecificInteger'.",
|
|
correctionMessage:
|
|
"Try using a native integer, 'Float', 'Double', 'Pointer', or subtype "
|
|
"of 'Struct', 'Union', or 'AbiSpecificInteger'.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when a subclass of `Struct` has more
|
|
// than one `Packed` annotation.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the class `C`, which
|
|
// is a subclass of `Struct`, has two `Packed` annotations:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// @Packed(1)
|
|
// [!@Packed(1)!]
|
|
// class C extends Struct {
|
|
// external Pointer<Uint8> notEmpty;
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Remove all but one of the annotations:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// @Packed(1)
|
|
// class C extends Struct {
|
|
// external Pointer<Uint8> notEmpty;
|
|
// }
|
|
// ```
|
|
static const FfiCode PACKED_ANNOTATION = FfiCode(
|
|
'PACKED_ANNOTATION',
|
|
"Structs must have at most one 'Packed' annotation.",
|
|
correctionMessage: "Try removing extra 'Packed' annotations.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when the argument to the `Packed`
|
|
// annotation isn't one of the allowed values: 1, 2, 4, 8, or 16.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the argument to the
|
|
// `Packed` annotation (`3`) isn't one of the allowed values:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// @Packed([!3!])
|
|
// class C extends Struct {
|
|
// external Pointer<Uint8> notEmpty;
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// Change the alignment to be one of the allowed values:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// @Packed(4)
|
|
// class C extends Struct {
|
|
// external Pointer<Uint8> notEmpty;
|
|
// }
|
|
// ```
|
|
static const FfiCode PACKED_ANNOTATION_ALIGNMENT = FfiCode(
|
|
'PACKED_ANNOTATION_ALIGNMENT',
|
|
"Only packing to 1, 2, 4, 8, and 16 bytes is supported.",
|
|
correctionMessage:
|
|
"Try changing the 'Packed' annotation alignment to 1, 2, 4, 8, or 16.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the name of the outer struct
|
|
* 1: the name of the struct being nested
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when a subclass of `Struct` that is
|
|
// annotated as being `Packed` declares a field whose type is also a subclass
|
|
// of `Struct` and the field's type is either not packed or is packed less
|
|
// tightly.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the class `Outer`,
|
|
// which is a subclass of `Struct` and is packed on 1-byte boundaries,
|
|
// declared a field whose type (`Inner`) is packed on 8-byte boundaries:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// @Packed(8)
|
|
// class Inner extends Struct {
|
|
// external Pointer<Uint8> notEmpty;
|
|
// }
|
|
//
|
|
// @Packed(1)
|
|
// class Outer extends Struct {
|
|
// external Pointer<Uint8> notEmpty;
|
|
//
|
|
// external [!Inner!] nestedLooselyPacked;
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// If the inner struct should be packed more tightly, then change the
|
|
// argument to the inner struct's `Packed` annotation:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// @Packed(1)
|
|
// class Inner extends Struct {
|
|
// external Pointer<Uint8> notEmpty;
|
|
// }
|
|
//
|
|
// @Packed(1)
|
|
// class Outer extends Struct {
|
|
// external Pointer<Uint8> notEmpty;
|
|
//
|
|
// external Inner nestedLooselyPacked;
|
|
// }
|
|
// ```
|
|
//
|
|
// If the outer struct should be packed less tightly, then change the
|
|
// argument to the outer struct's `Packed` annotation:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// @Packed(8)
|
|
// class Inner extends Struct {
|
|
// external Pointer<Uint8> notEmpty;
|
|
// }
|
|
//
|
|
// @Packed(8)
|
|
// class Outer extends Struct {
|
|
// external Pointer<Uint8> notEmpty;
|
|
//
|
|
// external Inner nestedLooselyPacked;
|
|
// }
|
|
// ```
|
|
//
|
|
// If the inner struct doesn't have an annotation and should be packed, then
|
|
// add an annotation.
|
|
//
|
|
// If the inner struct doesn't have an annotation and the outer struct
|
|
// shouldn't be packed, then remove its annotation.
|
|
static const FfiCode PACKED_NESTING_NON_PACKED = FfiCode(
|
|
'PACKED_NESTING_NON_PACKED',
|
|
"Nesting the non-packed or less tightly packed struct '{0}' in a packed "
|
|
"struct '{1}' isn't supported.",
|
|
correctionMessage:
|
|
"Try packing the nested struct or packing the nested struct more "
|
|
"tightly.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* No parameters.
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when the number of dimensions
|
|
// specified in an `Array` annotation doesn't match the number of nested
|
|
// arrays specified by the type of a field.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the field `a0` has a
|
|
// type with three nested arrays, but only two dimensions are given in the
|
|
// `Array` annotation:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// [!@Array(8, 8)!]
|
|
// external Array<Array<Array<Uint8>>> a0;
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// If the type of the field is correct, then fix the annotation to have the
|
|
// required number of dimensions:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// @Array(8, 8, 4)
|
|
// external Array<Array<Array<Uint8>>> a0;
|
|
// }
|
|
// ```
|
|
//
|
|
// If the type of the field is wrong, then fix the type of the field:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// @Array(8, 8)
|
|
// external Array<Array<Uint8>> a0;
|
|
// }
|
|
// ```
|
|
static const FfiCode SIZE_ANNOTATION_DIMENSIONS = FfiCode(
|
|
'SIZE_ANNOTATION_DIMENSIONS',
|
|
"'Array's must have an 'Array' annotation that matches the dimensions.",
|
|
correctionMessage: "Try adjusting the arguments in the 'Array' annotation.",
|
|
hasPublishedDocs: true,
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the name of the subclass
|
|
* 1: the name of the class being extended, implemented, or mixed in
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when a class extends any FFI class
|
|
// other than `Struct` or `Union`, or implements or mixes in any FFI class.
|
|
// `Struct` and `Union` are the only FFI classes that can be subtyped, and
|
|
// then only by extending them.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the class `C` extends
|
|
// `Double`:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends [!Double!] {}
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// If the class should extend either `Struct` or `Union`, then change the
|
|
// declaration of the class:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class C extends Struct {
|
|
// @Int32()
|
|
// external int i;
|
|
// }
|
|
// ```
|
|
//
|
|
// If the class shouldn't extend either `Struct` or `Union`, then remove any
|
|
// references to FFI classes:
|
|
//
|
|
// ```dart
|
|
// class C {}
|
|
// ```
|
|
static const FfiCode SUBTYPE_OF_FFI_CLASS_IN_EXTENDS = FfiCode(
|
|
'SUBTYPE_OF_FFI_CLASS',
|
|
"The class '{0}' can't extend '{1}'.",
|
|
correctionMessage: "Try extending 'Struct' or 'Union'.",
|
|
hasPublishedDocs: true,
|
|
uniqueName: 'SUBTYPE_OF_FFI_CLASS_IN_EXTENDS',
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the name of the subclass
|
|
* 1: the name of the class being extended, implemented, or mixed in
|
|
*/
|
|
static const FfiCode SUBTYPE_OF_FFI_CLASS_IN_IMPLEMENTS = FfiCode(
|
|
'SUBTYPE_OF_FFI_CLASS',
|
|
"The class '{0}' can't implement '{1}'.",
|
|
correctionMessage: "Try implementing 'Allocator' or 'Finalizable'.",
|
|
hasPublishedDocs: true,
|
|
uniqueName: 'SUBTYPE_OF_FFI_CLASS_IN_IMPLEMENTS',
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the name of the subclass
|
|
* 1: the name of the class being extended, implemented, or mixed in
|
|
*/
|
|
static const FfiCode SUBTYPE_OF_FFI_CLASS_IN_WITH = FfiCode(
|
|
'SUBTYPE_OF_FFI_CLASS',
|
|
"The class '{0}' can't mix in '{1}'.",
|
|
correctionMessage: "Try extending 'Struct' or 'Union'.",
|
|
hasPublishedDocs: true,
|
|
uniqueName: 'SUBTYPE_OF_FFI_CLASS_IN_WITH',
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the name of the subclass
|
|
* 1: the name of the class being extended, implemented, or mixed in
|
|
*/
|
|
// #### Description
|
|
//
|
|
// The analyzer produces this diagnostic when a class extends, implements, or
|
|
// mixes in a class that extends either `Struct` or `Union`. Classes can only
|
|
// extend either `Struct` or `Union` directly.
|
|
//
|
|
// For more information about FFI, see [C interop using dart:ffi][].
|
|
//
|
|
// #### Example
|
|
//
|
|
// The following code produces this diagnostic because the class `C` extends
|
|
// `S`, and `S` extends `Struct`:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class S extends Struct {
|
|
// external Pointer f;
|
|
// }
|
|
//
|
|
// class C extends [!S!] {
|
|
// external Pointer g;
|
|
// }
|
|
// ```
|
|
//
|
|
// #### Common fixes
|
|
//
|
|
// If you're trying to define a struct or union that shares some fields
|
|
// declared by a different struct or union, then extend `Struct` or `Union`
|
|
// directly and copy the shared fields:
|
|
//
|
|
// ```dart
|
|
// import 'dart:ffi';
|
|
//
|
|
// class S extends Struct {
|
|
// external Pointer f;
|
|
// }
|
|
//
|
|
// class C extends Struct {
|
|
// external Pointer f;
|
|
//
|
|
// external Pointer g;
|
|
// }
|
|
// ```
|
|
static const FfiCode SUBTYPE_OF_STRUCT_CLASS_IN_EXTENDS = FfiCode(
|
|
'SUBTYPE_OF_STRUCT_CLASS',
|
|
"The class '{0}' can't extend '{1}' because '{1}' is a subtype of "
|
|
"'Struct', 'Union', or 'AbiSpecificInteger'.",
|
|
correctionMessage:
|
|
"Try extending 'Struct', 'Union', or 'AbiSpecificInteger' directly.",
|
|
hasPublishedDocs: true,
|
|
uniqueName: 'SUBTYPE_OF_STRUCT_CLASS_IN_EXTENDS',
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the name of the subclass
|
|
* 1: the name of the class being extended, implemented, or mixed in
|
|
*/
|
|
static const FfiCode SUBTYPE_OF_STRUCT_CLASS_IN_IMPLEMENTS = FfiCode(
|
|
'SUBTYPE_OF_STRUCT_CLASS',
|
|
"The class '{0}' can't implement '{1}' because '{1}' is a subtype of "
|
|
"'Struct', 'Union', or 'AbiSpecificInteger'.",
|
|
correctionMessage:
|
|
"Try extending 'Struct', 'Union', or 'AbiSpecificInteger' directly.",
|
|
hasPublishedDocs: true,
|
|
uniqueName: 'SUBTYPE_OF_STRUCT_CLASS_IN_IMPLEMENTS',
|
|
);
|
|
|
|
/**
|
|
* Parameters:
|
|
* 0: the name of the subclass
|
|
* 1: the name of the class being extended, implemented, or mixed in
|
|
*/
|
|
static const FfiCode SUBTYPE_OF_STRUCT_CLASS_IN_WITH = FfiCode(
|
|
'SUBTYPE_OF_STRUCT_CLASS',
|
|
"The class '{0}' can't mix in '{1}' because '{1}' is a subtype of "
|
|
"'Struct', 'Union', or 'AbiSpecificInteger'.",
|
|
correctionMessage:
|
|
"Try extending 'Struct', 'Union', or 'AbiSpecificInteger' directly.",
|
|
hasPublishedDocs: true,
|
|
uniqueName: 'SUBTYPE_OF_STRUCT_CLASS_IN_WITH',
|
|
);
|
|
|
|
/// Initialize a newly created error code to have the given [name].
|
|
const FfiCode(
|
|
String name,
|
|
String problemMessage, {
|
|
String? correctionMessage,
|
|
bool hasPublishedDocs = false,
|
|
bool isUnresolvedIdentifier = false,
|
|
String? uniqueName,
|
|
}) : super(
|
|
correctionMessage: correctionMessage,
|
|
hasPublishedDocs: hasPublishedDocs,
|
|
isUnresolvedIdentifier: isUnresolvedIdentifier,
|
|
name: name,
|
|
problemMessage: problemMessage,
|
|
uniqueName: 'FfiCode.${uniqueName ?? name}',
|
|
);
|
|
|
|
@override
|
|
ErrorSeverity get errorSeverity => ErrorType.COMPILE_TIME_ERROR.severity;
|
|
|
|
@override
|
|
ErrorType get type => ErrorType.COMPILE_TIME_ERROR;
|
|
}
|