Skip to content

Commit

Permalink
[analyzer/ffi] Native static checks
Browse files Browse the repository at this point in the history
Bug: #49803
Bug: #50097

Change-Id: Id5b52be88937bcf9245f98e71afa56f079f288f0
Cq-Include-Trybots: luci.dart.try:analyzer-linux-release-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/265085
Reviewed-by: Brian Wilkerson <[email protected]>
Commit-Queue: Daco Harkes <[email protected]>
  • Loading branch information
dcharkes authored and Commit Queue committed Oct 24, 2022
1 parent ea70de3 commit a67c79b
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 1 deletion.
3 changes: 2 additions & 1 deletion pkg/analyzer/lib/src/generated/ffi_verifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1323,7 +1323,8 @@ extension on Annotation {
final element = this.element;
return element is ConstructorElement &&
element.ffiClass != null &&
element.enclosingElement.name == 'FfiNative';
(element.enclosingElement.name == 'Native' ||
element.enclosingElement.name == 'FfiNative');
}

bool get isPacked {
Expand Down
17 changes: 17 additions & 0 deletions pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,23 @@ class FfiNative<T> {
const FfiNative(this.nativeName, {this.isLeaf: false});
}
class Native<T> {
final String? symbol;
final String? asset;
final bool isLeaf;
const Native({
this.asset,
this.isLeaf: false,
this.symbol,
});
}
class Asset {
final String asset;
const Asset(this.asset);
}
class Abi {
static const androidArm = _androidArm;
static const androidArm64 = _androidArm64;
Expand Down
158 changes: 158 additions & 0 deletions pkg/analyzer/test/src/diagnostics/ffi_native_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import '../dart/resolution/context_collection_resolution.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(FfiNativeTest);
defineReflectiveTests(NativeTest);
});
}

Expand Down Expand Up @@ -182,3 +183,160 @@ external double wrongFfiReturnType(int v);
]);
}
}

@reflectiveTest
class NativeTest extends PubPackageResolutionTest {
test_annotation_Native_getters() async {
await assertNoErrorsInCode(r'''
import 'dart:ffi';
class NativeFieldWrapperClass1 {}
class Paragraph extends NativeFieldWrapperClass1 {
@Native<Double Function(Pointer<Void>)>(isLeaf: true)
external double get ideographicBaseline;
@Native<Void Function(Pointer<Void>, Double)>(isLeaf: true)
external set ideographicBaseline(double d);
}
''');
}

test_annotation_Native_noArguments() async {
await assertErrorsInCode(r'''
import 'dart:ffi';
@Native
external int foo();
''', [
error(CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS, 20, 7),
]);
}

test_NativeCanUseHandles() async {
await assertErrorsInCode(r'''
import 'dart:ffi';
@Native<Handle Function(Handle)>()
external Object doesntMatter(Object);
''', []);
}

test_NativeCanUseLeaf() async {
await assertErrorsInCode(r'''
import 'dart:ffi';
@Native<Int8 Function(Int64)>(isLeaf:true)
external int doesntMatter(int x);
''', []);
}

test_NativeInstanceMethodsMustHaveReceiver() async {
await assertErrorsInCode(r'''
import 'dart:ffi';
class K {
@Native<Void Function(Double)>()
external void doesntMatter(double x);
}
''', [
error(FfiCode.FFI_NATIVE_UNEXPECTED_NUMBER_OF_PARAMETERS_WITH_RECEIVER,
31, 72),
]);
}

test_NativeLeafMustNotReturnHandle() async {
await assertErrorsInCode(r'''
import 'dart:ffi';
@Native<Handle Function()>(isLeaf:true)
external Object doesntMatter();
''', [
error(FfiCode.LEAF_CALL_MUST_NOT_RETURN_HANDLE, 19, 71),
]);
}

test_NativeLeafMustNotTakeHandles() async {
await assertErrorsInCode(r'''
import 'dart:ffi';
@Native<Void Function(Handle)>(symbol: 'DoesntMatter', isLeaf:true)
external void doesntMatter(Object o);
''', [
error(FfiCode.LEAF_CALL_MUST_NOT_TAKE_HANDLE, 19, 105),
]);
}

test_NativeNonFfiParameter() async {
await assertErrorsInCode(r'''
import 'dart:ffi';
@Native<IntPtr Function(int)>()
external int nonFfiParameter(int v);
''', [
error(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE, 19, 68),
]);
}

test_NativeNonFfiReturnType() async {
await assertErrorsInCode(r'''
import 'dart:ffi';
@Native<double Function(IntPtr)>()
external double nonFfiReturnType(int v);
''', [
error(FfiCode.MUST_BE_A_NATIVE_FUNCTION_TYPE, 19, 75),
]);
}

test_NativePointerParameter() async {
await assertNoErrorsInCode(r'''
import 'dart:ffi';
@Native<Void Function(Pointer)>()
external void free(Pointer pointer);
''');
}

test_NativeTooFewParameters() async {
await assertErrorsInCode(r'''
import 'dart:ffi';
@Native<Void Function(Double)>()
external void doesntMatter(double x, double y);
''', [
error(FfiCode.FFI_NATIVE_UNEXPECTED_NUMBER_OF_PARAMETERS, 19, 80),
]);
}

test_NativeTooManyParameters() async {
await assertErrorsInCode(r'''
import 'dart:ffi';
@Native<Void Function(Double, Double)>()
external void doesntMatter(double x);
''', [
error(FfiCode.FFI_NATIVE_UNEXPECTED_NUMBER_OF_PARAMETERS, 19, 78),
]);
}

test_NativeVoidReturn() async {
await assertErrorsInCode(r'''
import 'dart:ffi';
@Native<Handle Function(Uint32, Uint32, Handle)>()
external void voidReturn(int width, int height, Object outImage);
''', [
error(FfiCode.MUST_BE_A_SUBTYPE, 19, 116),
]);
}

test_NativeWrongFfiParameter() async {
await assertErrorsInCode(r'''
import 'dart:ffi';
@Native<IntPtr Function(Double)>()
external int wrongFfiParameter(int v);
''', [
error(FfiCode.MUST_BE_A_SUBTYPE, 19, 73),
]);
}

test_NativeWrongFfiReturnType() async {
await assertErrorsInCode(r'''
import 'dart:ffi';
@Native<IntPtr Function(IntPtr)>()
external double wrongFfiReturnType(int v);
''', [
error(FfiCode.MUST_BE_A_SUBTYPE, 19, 77),
]);
}
}

0 comments on commit a67c79b

Please sign in to comment.