Skip to content

Commit

Permalink
Generate type aliases in Dart
Browse files Browse the repository at this point in the history
Added dedicated DartTypeAlias template, as type aliases (typedefs) are now
supported in Dart language (since Dart version 2.13). Updated other Dart
tempates and resolvers to treat type aliases as a normal type, instead of
skipping it through to the target type.

Added/updated related smoke and functional tests.

Unrelated smoke tests are updated in a separate commit.

Resolves: #907
Signed-off-by: Daniel Kamkha <[email protected]>
  • Loading branch information
DanielKamkha committed Aug 3, 2022
1 parent dc15d25 commit 9e6882b
Show file tree
Hide file tree
Showing 16 changed files with 141 additions and 40 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/functional-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ jobs:
- name: Install Dart SDK
run: |
DART_RELEASE_CHANNEL=stable
DART_VERSION=2.12.0
DART_VERSION=2.13.3
wget -nv https://storage.googleapis.com/dart-archive/channels/${DART_RELEASE_CHANNEL}/release/${DART_VERSION}/linux_packages/dart_${DART_VERSION}-1_amd64.deb
sudo apt -y install ./dart_${DART_VERSION}-1_amd64.deb
- name: Build and run functional tests
Expand Down Expand Up @@ -365,7 +365,7 @@ jobs:
- name: Install Dart SDK
run: |
DART_RELEASE_CHANNEL=stable
DART_VERSION=2.12.0
DART_VERSION=2.13.3
wget -nv https://storage.googleapis.com/dart-archive/channels/${DART_RELEASE_CHANNEL}/release/${DART_VERSION}/linux_packages/dart_${DART_VERSION}-1_amd64.deb
sudo apt -y install ./dart_${DART_VERSION}-1_amd64.deb
- name: Build and run functional tests
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Gluecodium project Release Notes

## Unreleased
### Features:
* Added support for type aliases (typedefs) in Dart
### Breaking changes:
* Generated Dart code now requires minimum Dart version 2.13.0.

## 13.1.0
Release date: 2022-08-02
### Breaking changes:
Expand Down
4 changes: 3 additions & 1 deletion functional-tests/functional/dart/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ import "test/StaticIntMethods_test.dart" as StaticIntMethodsTests;
import "test/StaticStringMethods_test.dart" as StaticStringMethodsTests;
import "test/StructsWithConstants_test.dart" as StructsWithConstantsTests;
import "test/StructsWithMethods_test.dart" as StructsWithMethodsTests;
import "test/TypeAliases_test.dart" as TypeAliasesTests;

final _allTests = [
AsyncTests.main,
Expand Down Expand Up @@ -117,7 +118,8 @@ final _allTests = [
StaticIntMethodsTests.main,
StaticStringMethodsTests.main,
StructsWithConstantsTests.main,
StructsWithMethodsTests.main
StructsWithMethodsTests.main,
TypeAliasesTests.main
];

String _getLibraryPath(String nativeLibraryName) {
Expand Down
2 changes: 1 addition & 1 deletion functional-tests/functional/dart/pubspec.yaml.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: FunctionalDartTests
environment:
sdk: '>=2.12.0 <3.0.0'
sdk: '>=2.13.0 <3.0.0'
dependencies:
test:
functional:
Expand Down
55 changes: 55 additions & 0 deletions functional-tests/functional/dart/test/TypeAliases_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// -------------------------------------------------------------------------------------------------
// Copyright (C) 2016-2021 HERE Europe B.V.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0
// License-Filename: LICENSE
//
// -------------------------------------------------------------------------------------------------

import "package:test/test.dart";
import "package:functional/test.dart";
import "../test_suite.dart";

final _testSuite = TestSuite("Type Aliases");

void main() {
_testSuite.test("Type alias to struct", () {
final result = StaticTypedefExampleStructTypedef("nonsense");

expect(result is StaticTypedefExampleStruct, isTrue);
expect(result.exampleString, "nonsense");
});
_testSuite.test("Type alias used by a function", () {
final result = StaticTypedef.returnIntTypedef(2);

expect(result is int, isTrue);
expect(result, 3);
});
_testSuite.test("Type alias points to a type alias", () {
final result = StaticTypedef.returnNestedIntTypedef(4);

expect(result is int, isTrue);
expect(result, 5);
});
_testSuite.test("Type alias from type collection", () {
final result = StaticTypedef.returnTypedefPointFromTypeCollection(
TypeCollectionPointTypedef(1.0, 3.0)
);

expect(result is TypeCollectionPoint, isTrue);
expect(result.x, 1.0);
expect(result.y, 3.0);
});
}
3 changes: 3 additions & 0 deletions functional-tests/functional/input/lime/StaticTypedef.lime
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ class StaticTypedef {
// Example struct
struct ExampleStruct {
exampleString: String = ""
@Skip(Dart)
field constructor()
field constructor(exampleString)
}
typealias IntTypedef = Int
typealias NestedIntTypedef = IntTypedef
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ internal class DartGenerator : Generator {
injectAsyncHelpers(ffiReferenceMap, asyncHelpers)

val generatedFiles = dartFilteredModel.topElements.flatMap {
listOfNotNull(
listOf(
generateDart(
it, dartResolvers, dartNameResolver, listOf(importsCollector, declarationImportsCollector),
exportsCollector, typeRepositoriesCollector, predicatesMap, descendantInterfaces,
Expand Down Expand Up @@ -214,15 +214,15 @@ internal class DartGenerator : Generator {
predicates: Map<String, (Any) -> Boolean>,
descendantInterfaces: Map<String, List<LimeInterface>>,
asyncHelpers: DartAsyncHelpers.AsyncHelpersGroup?
): GeneratedFile? {
val contentTemplateName = selectTemplate(rootElement) ?: return null
): GeneratedFile {
val contentTemplateName = selectTemplate(rootElement)

val packagePath = rootElement.path.head.joinToString(separator = "/")
val fileName = dartNameResolver.resolveFileName(rootElement)
val filePath = "$packagePath/$fileName"
val relativePath = "$SRC_DIR_SUFFIX/$filePath.dart"

val allTypes = LimeTypeHelper.getAllTypes(rootElement).filterNot { it is LimeTypeAlias }
val allTypes = LimeTypeHelper.getAllTypes(rootElement)
val nonExternalTypes = allTypes.filter { it.external?.dart == null }
val allSymbols = nonExternalTypes.filter { it.visibility.isPublic }
if (allSymbols.isNotEmpty()) {
Expand Down Expand Up @@ -527,7 +527,7 @@ internal class DartGenerator : Generator {
is LimeEnumeration -> "dart/DartEnumeration"
is LimeException -> "dart/DartException"
is LimeLambda -> "dart/DartLambda"
is LimeTypeAlias -> null
is LimeTypeAlias -> "dart/DartTypeAlias"
else -> throw GluecodiumExecutionException(
"Unsupported top-level element: " +
limeElement::class.java.name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,16 @@ internal class DartImportResolver(
}

private fun resolveTypeImports(limeType: LimeType, skipHelpers: Boolean = false): List<DartImport> {
val actualType = limeType.actualType
when (actualType) {
is LimeBasicType -> return resolveBasicTypeImports(actualType)
is LimeGenericType -> return resolveGenericTypeImports(actualType)
when (limeType) {
is LimeBasicType -> return resolveBasicTypeImports(limeType)
is LimeGenericType -> return resolveGenericTypeImports(limeType)
}

val externalImport = resolveExternalImport(actualType, IMPORT_PATH_NAME, useAlias = true)
val externalImport = resolveExternalImport(limeType, IMPORT_PATH_NAME, useAlias = true)
return when {
externalImport == null -> listOf(createImport(actualType))
externalImport == null -> listOf(createImport(limeType))
skipHelpers -> listOf(externalImport)
else -> listOf(createImport(actualType), externalImport)
else -> listOf(createImport(limeType), externalImport)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ internal class DartImportsCollector(importsResolver: ImportsResolver<DartImport>
importsResolver,
collectTypeRefImports = true,
collectValueImports = true,
parentTypeFilter = { true }
parentTypeFilter = { true },
collectTypeAliasImports = true
) {

override fun collectParentTypeRefs(limeContainer: LimeContainerWithInheritance) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ import com.here.gluecodium.model.lime.LimeReturnType
import com.here.gluecodium.model.lime.LimeSet
import com.here.gluecodium.model.lime.LimeStruct
import com.here.gluecodium.model.lime.LimeType
import com.here.gluecodium.model.lime.LimeTypeAlias
import com.here.gluecodium.model.lime.LimeTypeHelper
import com.here.gluecodium.model.lime.LimeTypeRef
import com.here.gluecodium.model.lime.LimeValue
Expand Down Expand Up @@ -85,7 +84,6 @@ internal class DartNameResolver(
is LimeValue -> resolveValue(element)
is LimeGenericType -> resolveGenericType(element)
is LimeTypeRef -> resolveTypeRefName(element)
is LimeTypeAlias -> resolveName(element.typeRef)
is LimeType -> resolveTypeName(element)
is LimeNamedElement -> getPlatformName(element)
else ->
Expand Down Expand Up @@ -269,11 +267,11 @@ internal class DartNameResolver(

private fun resolveTypeRefName(limeTypeRef: LimeTypeRef, ignoreDuplicates: Boolean = false): String {
val typeName = resolveName(limeTypeRef.type)
val importPath = limeTypeRef.type.actualType.external?.dart?.get(IMPORT_PATH_NAME)
val importPath = limeTypeRef.type.external?.dart?.get(IMPORT_PATH_NAME)
val alias = when {
importPath != null -> computeAlias(importPath)
ignoreDuplicates -> null
duplicateNames.contains(typeName) -> limeTypeRef.type.actualType.path.head.joinToString("_")
duplicateNames.contains(typeName) -> limeTypeRef.type.path.head.joinToString("_")
else -> null
}
val suffix = if (limeTypeRef.isNullable) "?" else ""
Expand Down Expand Up @@ -311,7 +309,7 @@ internal class DartNameResolver(
private fun buildDuplicateNames() =
limeReferenceMap.values
.filterIsInstance<LimeType>()
.filterNot { it is LimeTypeAlias || it is LimeGenericType || it is LimeBasicType }
.filterNot { it is LimeGenericType || it is LimeBasicType }
.filter { it.external?.dart == null }
.groupBy { resolveTypeName(it) }
.filterValues { it.size > 1 }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ abstract class {{resolveName}}{{!!
{{/ifPredicate}}
}

{{#typeAliases}}
{{>dart/DartTypeAlias}}
{{/typeAliases}}
{{#enumerations}}
{{>dart/DartEnumeration}}
{{/enumerations}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ abstract class {{resolveName}}{{!!
{{/ifPredicate}}
}

{{#typeAliases}}
{{>dart/DartTypeAlias}}
{{/typeAliases}}
{{#enumerations}}
{{>dart/DartEnumeration}}
{{/enumerations}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
!}}
name: {{libraryName}}
environment:
sdk: '>=2.12.0 <3.0.0'
sdk: '>=2.13.0 <3.0.0'
dependencies:
ffi:
intl:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ class {{resolveName}}{{#if external.dart.converter}}Internal{{/if}} {
}
{{/unlessPredicate}}

{{#typeAliases}}
{{>dart/DartTypeAlias}}
{{/typeAliases}}
{{#enumerations}}
{{>dart/DartEnumeration}}
{{/enumerations}}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{{!!
!
! Copyright (C) 2016-2021 HERE Europe B.V.
!
! Licensed under the Apache License, Version 2.0 (the "License");
! you may not use this file except in compliance with the License.
! You may obtain a copy of the License at
!
! http://www.apache.org/licenses/LICENSE-2.0
!
! Unless required by applicable law or agreed to in writing, software
! distributed under the License is distributed on an "AS IS" BASIS,
! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
! See the License for the specific language governing permissions and
! limitations under the License.
!
! SPDX-License-Identifier: Apache-2.0
! License-Filename: LICENSE
!
!}}
{{>dart/DartDocumentation}}{{>dart/DartAttributes}}
typedef {{resolveName visibility}}{{resolveName}} = {{resolveName typeRef}};
Loading

0 comments on commit 9e6882b

Please sign in to comment.