Skip to content

Commit

Permalink
Generate forward declaration for inner classes when they are actually…
Browse files Browse the repository at this point in the history
… used.
  • Loading branch information
NazarKacharaba committed Jul 8, 2023
1 parent c856547 commit 61c6047
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 22 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Unreleased
### Bug fixes:
* Fixed documentation references to constructors in Java.
* Added forward declaration for inner interfaces and classes.

## 13.6.1
### Bug fixes:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import com.here.gluecodium.generator.common.NameHelper
import com.here.gluecodium.generator.common.NameResolver
import com.here.gluecodium.generator.common.nameRuleSetFromConfig
import com.here.gluecodium.generator.common.templates.TemplateEngine
import com.here.gluecodium.generator.cpp.CppGeneratorPredicates.predicates
import com.here.gluecodium.model.lime.LimeAttributeType.CPP
import com.here.gluecodium.model.lime.LimeAttributeType.EQUATABLE
import com.here.gluecodium.model.lime.LimeConstant
Expand Down Expand Up @@ -123,10 +122,11 @@ internal class CppGenerator : Generator {
.filter { it.external?.cpp == null }
.map { it.fullName }
.toSet()
val predicates = CppGeneratorPredicates(filteredModel.referenceMap).predicates

val generatedFiles = filteredModel.topElements.flatMap {
val fileName = nameRules.getOutputFilePath(it)
generateCode(it, fileName, includeResolver, nameResolver, fullNameResolver, signatureResolver, allErrorEnums)
generateCode(it, fileName, includeResolver, nameResolver, fullNameResolver, signatureResolver, allErrorEnums, predicates)
} + COMMON_HEADERS.map { generateHelperFile(it, "include", ".h") } +
COMMON_IMPLS.map { generateHelperFile(it, "src", ".cpp") } +
generateExportHelperFile(exportCommonName, "Common", GeneratedFile.SourceSet.COMMON) +
Expand All @@ -146,7 +146,8 @@ internal class CppGenerator : Generator {
nameResolver: CppNameResolver,
fullNameResolver: CppFullNameResolver,
signatureResolver: CppSignatureResolver,
allErrorEnums: Set<String>
allErrorEnums: Set<String>,
predicates: Map<String, (Any)-> Boolean>
): List<GeneratedFile> {

val allTypes = LimeTypeHelper.getAllTypes(rootElement)
Expand Down Expand Up @@ -180,13 +181,13 @@ internal class CppGenerator : Generator {
val headerIncludesCollector = CppHeaderIncludesCollector(includeResolver, allErrorEnums)
val headerIncludes = headerIncludesCollector.collectImports(rootElement) + exportInclude
templateData["functionUsings"] = collectFunctionUsings(rootElement, signatureResolver)
result += generateHeader(rootElement, nameResolvers, fileName, templateData, headerIncludes)
result += generateHeader(rootElement, nameResolvers, fileName, templateData, headerIncludes, predicates)
}
if (needsImplementation) {
val implIncludesCollector = CppImplIncludesCollector(includeResolver, allErrorEnums)
val implementationIncludes = implIncludesCollector.collectImports(rootElement) +
createSelfInclude(rootElement, needsHeader, fileName)
result += generateImplementation(rootElement, nameResolvers, implementationIncludes, templateData, fileName)
result += generateImplementation(rootElement, nameResolvers, implementationIncludes, templateData, fileName, predicates)
}

return result
Expand All @@ -206,7 +207,8 @@ internal class CppGenerator : Generator {
nameResolvers: Map<String, NameResolver>,
implementationIncludes: List<Include>,
generalData: Map<String, Any>,
fileName: String
fileName: String,
predicates: Map<String, (Any)-> Boolean>
): GeneratedFile {
val templateData = generalData + mapOf(
"includes" to implementationIncludes.distinct().sorted(),
Expand All @@ -223,7 +225,8 @@ internal class CppGenerator : Generator {
nameResolvers: Map<String, NameResolver>,
fileName: String,
generalData: Map<String, Any>,
headerIncludes: List<Include>
headerIncludes: List<Include>,
predicates: Map<String, (Any)-> Boolean>
): GeneratedFile {
val absolutePath = Paths.get(GENERATOR_NAME, "include", fileName)
val headerFileName = "$absolutePath.h"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,19 @@ import com.here.gluecodium.generator.common.CommonGeneratorPredicates
import com.here.gluecodium.model.lime.LimeAttributeType
import com.here.gluecodium.model.lime.LimeContainer
import com.here.gluecodium.model.lime.LimeContainerWithInheritance
import com.here.gluecodium.model.lime.LimeElement
import com.here.gluecodium.model.lime.LimeField
import com.here.gluecodium.model.lime.LimeFunction
import com.here.gluecodium.model.lime.LimeNamedElement
import com.here.gluecodium.model.lime.LimeStruct
import com.here.gluecodium.model.lime.LimeType
import com.here.gluecodium.model.lime.LimeTypeHelper
import com.here.gluecodium.model.lime.LimeTypeRef

/**
* List of predicates used by `ifPredicate`/`unlessPredicate` template helpers in C++ generator.
*/
internal object CppGeneratorPredicates {
internal class CppGeneratorPredicates(private val referenceMap: Map<String, LimeElement>) {
val predicates = mapOf(
"needsRefSuffix" to { limeTypeRef: Any ->
limeTypeRef is LimeTypeRef && CppNameResolver.needsRefSuffix(limeTypeRef)
Expand Down Expand Up @@ -101,10 +104,27 @@ internal object CppGeneratorPredicates {
else -> true
}
},
"isUsedInAnotherInnerClasses" to fun(limeField: Any): Boolean {
if (limeField !is LimeContainer || !limeField.path.hasParent) return false
val parent = referenceMap[limeField.path.parent.toAmbiguousString()]
if (parent !is LimeContainerWithInheritance) return false

return (parent.interfaces + parent.classes)
.filter { it != limeField }
.map { InnerClassForwardDeclarationCollection.collectImports(it) }
.any { it.contains(limeField.fullName) }
},
"needsInnerForwardDeclarations" to fun(limeField: Any): Boolean {
if (limeField !is LimeContainer) return false
return limeField.classes.size + limeField.interfaces.size > 0
},

val containers = limeField.interfaces + limeField.classes
val typesUsedInTheClass = containers
.associateWith { InnerClassForwardDeclarationCollection.collectImports(it) }

return containers.any { container ->
typesUsedInTheClass.filterKeys { it != container }.values.flatten().contains(container.fullName)
}
}
)

private fun needsNotNullComment(limeTypeRef: LimeTypeRef) =
Expand All @@ -119,4 +139,11 @@ internal object CppGeneratorPredicates {
val typesToVisit = leafType.fields.map { it.typeRef.type.actualType }.distinct() - visitedTypes
return typesToVisit.flatMap { getAllFieldTypesRec(it, visitedTypes) } + leafType
}

private object InnerClassForwardDeclarationCollection : CppImportsCollector<String>() {
override fun collectImports(limeElement: LimeNamedElement): List<String> {
val allTypes = LimeTypeHelper.getAllTypes(limeElement)
return collectTypeRefs(allTypes).map { it.elementFullName }
}
}
}
4 changes: 4 additions & 0 deletions gluecodium/src/main/resources/templates/cpp/CppClass.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,14 @@ public:
{{#ifPredicate "needsInnerForwardDeclarations"}}
public:
{{#this.classes}}
{{#ifPredicate "isUsedInAnotherInnerClasses"}}
class {{this.name}};
{{/ifPredicate}}
{{/this.classes}}
{{#this.interfaces}}
{{#ifPredicate "isUsedInAnotherInnerClasses"}}
class {{this.name}};
{{/ifPredicate}}
{{/this.interfaces}}
{{/ifPredicate}}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,27 @@ package smoke.forward

class InnerClassForwardDeclarations {
@Internal
interface InnerInterface {
interface InnerInterface1 {
}

open class InnerClass {
interface InnerInterface2 {
}

interface InnerInterface3 {
}

open class InnerClass1 {
@Internal
fun getInnerInterface() : InnerInterface
fun getInnerInterface() : InnerInterface1
}

class InnerClass2 {
class InnerInnerClass1 {
fun foo() : InnerInnerClass2
}

class InnerInnerClass2 {
fun bar(arg: InnerInterface2)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,76 @@ class _GLUECODIUM_CPP_EXPORT InnerClassForwardDeclarations {
virtual ~InnerClassForwardDeclarations() = 0;

public:
class InnerClass;
class InnerInterface;
class InnerInterface1;
class InnerInterface2;

public:
class _GLUECODIUM_CPP_EXPORT InnerClass {
class _GLUECODIUM_CPP_EXPORT InnerClass1 {
public:
InnerClass();
virtual ~InnerClass() = 0;
InnerClass1();
virtual ~InnerClass1() = 0;

public:
/**
*
* \return @NotNull
*/
virtual ::std::shared_ptr< ::smoke::forward::InnerClassForwardDeclarations::InnerInterface > get_inner_interface( ) = 0;
virtual ::std::shared_ptr< ::smoke::forward::InnerClassForwardDeclarations::InnerInterface1 > get_inner_interface( ) = 0;
};

class _GLUECODIUM_CPP_EXPORT InnerInterface {
class _GLUECODIUM_CPP_EXPORT InnerClass2 {
public:
InnerInterface();
virtual ~InnerInterface() = 0;
InnerClass2();
virtual ~InnerClass2() = 0;

public:
class InnerInnerClass2;

public:
class _GLUECODIUM_CPP_EXPORT InnerInnerClass1 {
public:
InnerInnerClass1();
virtual ~InnerInnerClass1() = 0;

public:
/**
*
* \return @NotNull
*/
virtual ::std::shared_ptr< ::smoke::forward::InnerClassForwardDeclarations::InnerClass2::InnerInnerClass2 > foo( ) = 0;
};

class _GLUECODIUM_CPP_EXPORT InnerInnerClass2 {
public:
InnerInnerClass2();
virtual ~InnerInnerClass2() = 0;

public:
/**
*
* \param[in] arg @NotNull
*/
virtual void bar( const ::std::shared_ptr< ::smoke::forward::InnerClassForwardDeclarations::InnerInterface2 >& arg ) = 0;
};

};

class _GLUECODIUM_CPP_EXPORT InnerInterface1 {
public:
InnerInterface1();
virtual ~InnerInterface1() = 0;
};

class _GLUECODIUM_CPP_EXPORT InnerInterface2 {
public:
InnerInterface2();
virtual ~InnerInterface2() = 0;
};

class _GLUECODIUM_CPP_EXPORT InnerInterface3 {
public:
InnerInterface3();
virtual ~InnerInterface3() = 0;
};

};
Expand Down

0 comments on commit 61c6047

Please sign in to comment.