Skip to content
This repository has been archived by the owner on Sep 16, 2024. It is now read-only.

Commit

Permalink
feat(winrtgen): support constant reference parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
halildurmus committed Sep 14, 2023
1 parent 42eb926 commit 291b709
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 8 deletions.
4 changes: 3 additions & 1 deletion packages/winrtgen/bin/add_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,10 @@ void printUsage(ArgParser argParser) {
}

void main(List<String> args) async {
final argParser = buildParser();
print('Loading WinRT Metadata...');
await WinRTMetadataStore.loadMetadata();

final argParser = buildParser();
try {
final results = argParser.parse(args);

Expand Down
11 changes: 10 additions & 1 deletion packages/winrtgen/lib/src/extensions/type_identifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ extension TypeIdentifierHelpers on TypeIdentifier {

bool get isCharType => baseType == BaseType.charType;

bool get isCLanguageOptionalModifier =>
baseType == BaseType.cLanguageOptionalModifier;

bool get isCLanguageRequiredModifier =>
baseType == BaseType.cLanguageRequiredModifier;

bool get isClassType => baseType == BaseType.classTypeModifier;

bool get isClassVariableType =>
Expand Down Expand Up @@ -179,7 +185,10 @@ extension TypeIdentifierHelpers on TypeIdentifier {
name.lastComponent,
BaseType.genericTypeModifier => _parseGenericTypeIdentifierName(this),
BaseType.objectType => 'Object',
BaseType.referenceTypeModifier => dereference().shortName,
BaseType.cLanguageOptionalModifier ||
BaseType.cLanguageRequiredModifier ||
BaseType.referenceTypeModifier =>
dereference().shortName,
_ => baseType.dartType,
};
}
Expand Down
4 changes: 3 additions & 1 deletion packages/winrtgen/lib/src/models/projection_kind.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ enum ProjectionKind {

/// Returns the appropriate [ProjectionKind] for the [projection].
factory ProjectionKind.fromTypeProjection(TypeProjection projection) {
if (projection.isReferenceType) {
if (projection.isCLanguageOptionalModifier ||
projection.isCLanguageRequiredModifier ||
projection.isReferenceType) {
final projectionKind =
ProjectionKind.fromTypeProjection(projection.dereference());
return projectionKind == ProjectionKind.dartPrimitive
Expand Down
16 changes: 16 additions & 0 deletions packages/winrtgen/lib/src/projections/type.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ final class TypeProjection {

bool get isCharType => typeIdentifier.isCharType;

bool get isCLanguageOptionalModifier =>
typeIdentifier.isCLanguageOptionalModifier;

bool get isCLanguageRequiredModifier =>
typeIdentifier.isCLanguageRequiredModifier;

bool get isClassVariableType => typeIdentifier.isClassVariableType;

bool get isDartPrimitive => switch (dartType) {
Expand Down Expand Up @@ -159,6 +165,8 @@ final class TypeProjection {
TypeProjection dereference() =>
TypeProjection(typeIdentifier.dereference(), isInParam: isInParam);

TypeTuple _unwrapCustomModifier() => dereference().projection;

TypeTuple _unwrapGenericTypeArg() {
final typeArgKind = TypeArgKind.fromName(typeIdentifier.name);
return switch (typeArgKind) {
Expand Down Expand Up @@ -226,6 +234,9 @@ final class TypeProjection {
return TypeTuple(type, type);
}

// Handle custom modifiers (e.g., BaseType.cLanguageOptionalModifier)
if (isCLanguageOptionalModifier) return _unwrapCustomModifier();

// Handle generic type argument (e.g., TypeArgKind.inspectable,
// TypeArgKind.nullableInspectable, TypeArgKind.winrtEnum, or
// TypeArgKind.winrtFlagsEnum)
Expand All @@ -250,6 +261,11 @@ final class TypeTuple {

/// The type, as represented as a struct attribute (e.g., `@Int64()`)
final String? attribute;

@override
String toString() =>
'TypeTuple(nativeType: $nativeType, dartType: $dartType, '
'attribute: $attribute)';
}

const _baseNativeMapping = <BaseType, TypeTuple>{
Expand Down
18 changes: 14 additions & 4 deletions packages/winrtgen/lib/src/projections/types/struct.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,16 @@ final class StructParameterProjection extends ParameterProjection {
fieldProjections.any((fieldProjection) =>
fieldProjection.isIReference || fieldProjection.exposedAsStruct);

TypeIdentifier get typeIdentifier => parameter.isReferenceType
? parameter.typeIdentifier.dereference()
: parameter.typeIdentifier;
TypeIdentifier get typeIdentifier {
if (parameter.typeIdentifier.isCLanguageOptionalModifier &&
parameter.typeIdentifier.typeArg!.isReferenceType) {
return parameter.typeIdentifier.dereference().dereference();
}

return parameter.isReferenceType
? parameter.typeIdentifier.dereference()
: parameter.typeIdentifier;
}

@override
String get type => shortTypeName;
Expand All @@ -39,7 +46,10 @@ final class StructParameterProjection extends ParameterProjection {
isGuid ? '$identifier.toDartGuid()' : '$identifier.toDart()';

@override
String get into => '${identifier}NativeStructPtr.ref';
String get into => parameter.typeIdentifier.isCLanguageOptionalModifier &&
parameter.typeIdentifier.typeArg!.isReferenceType
? '${identifier}NativeStructPtr'
: '${identifier}NativeStructPtr.ref';

@override
List<String> get preambles {
Expand Down
22 changes: 22 additions & 0 deletions packages/winrtgen/test/projections/parameter_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,28 @@ void main() {
expect(projection.localIdentifier, equals('other.lpVtbl'));
});

test('projects constant reference type', () {
final methodProjection = MethodProjection.fromTypeAndMethodName(
'Windows.Foundation.GuidHelper', 'Equals');
final projection = methodProjection.parameters.first;
expect(projection, isA<StructParameterProjection>());
expect(projection.isInParam, isTrue);
expect(projection.isOutParam, isFalse);
expect(projection.isNullable, isFalse);
expect(projection.type, equals('Guid'));
expect(projection.needsAllocation, isTrue);
expect(projection.needsDeallocation, isTrue);
expect(projection.creatorPreamble, isEmpty);
expect(projection.creator, equals('target.toDartGuid()'));
expect(projection.into, equals('targetNativeStructPtr'));
expect(projection.preambles,
equals(['final targetNativeStructPtr = target.toNativeGUID();']));
expect(projection.nullCheck, isEmpty);
expect(projection.postambles, equals(['free(targetNativeStructPtr);']));
expect(projection.identifier, equals('target'));
expect(projection.localIdentifier, equals('targetNativeStructPtr'));
});

test('projects DateTime', () {
final methodProjection = MethodProjection.fromTypeAndMethodName(
'Windows.Globalization.ICalendar', 'SetDateTime');
Expand Down
2 changes: 1 addition & 1 deletion packages/winrtgen/test/projections/type_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ void main() {
expect(
typeProjection.toString(),
equals(
"TypeProjection(Calendar, isInParam: false, nativeType: COMObject, dartType: COMObject, pointer: Instance of 'TypeTuple')"));
'TypeProjection(Calendar, isInParam: false, nativeType: COMObject, dartType: COMObject, pointer: TypeTuple(nativeType: Pointer<COMObject>, dartType: Pointer<COMObject>, attribute: null))'));
});
});
}

0 comments on commit 291b709

Please sign in to comment.