Skip to content

Commit

Permalink
Improvement of built-in types for all supported languages (#1113)
Browse files Browse the repository at this point in the history
* Improvement of built-in types for all supported languages

This PR is a cleanup and improvement for the built-in types for all supported languages

* Addressed review comments

* Make javalanguage open again

---------

Co-authored-by: Alexander Kuechler <[email protected]>
  • Loading branch information
oxisto and KuechA authored Mar 3, 2023
1 parent bc2f253 commit e32d4dc
Show file tree
Hide file tree
Showing 15 changed files with 121 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ fun getFanciesFor(original: Node?, node: Node?): List<Pair<AttributedStyle, Regi
fancyWord("new", node, list, styles.keyword)

// check for primitive types
for (primitive in node.language?.primitiveTypes ?: listOf()) {
for (primitive in node.language?.primitiveTypeNames ?: listOf()) {
fancyWord(primitive, node, list, styles.keyword)
}

Expand Down Expand Up @@ -289,7 +289,7 @@ private fun fancyType(
node: HasType,
list: MutableList<Pair<AttributedStyle, Region>>
) {
val types = outer.language?.primitiveTypes?.toMutableSet() ?: mutableSetOf()
val types = outer.language?.primitiveTypeNames?.toMutableSet() ?: mutableSetOf()
types += node.type.name.toString()

// check for primitive types
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ public synchronized void cacheType(HasType node, Type type) {
}

public static boolean isPrimitive(Type type, Language<? extends LanguageFrontend> language) {
return language.getPrimitiveTypes().contains(type.getTypeName());
return language.getPrimitiveTypeNames().contains(type.getTypeName());
}

public boolean isUnknown(Type type) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class BooleanType(
typeName: CharSequence = "bool",
bitWidth: Int? = 1,
language: Language<out LanguageFrontend>? = null,
modifier: Modifier = Modifier.UNSIGNED
modifier: Modifier = Modifier.NOT_APPLICABLE
) : NumericType(typeName, bitWidth, language, modifier) {

override fun duplicate(): Type {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ private static String removeAccessModifier(
*/
private static boolean isPrimitiveType(
@NotNull List<String> stringList, @NotNull Language<? extends LanguageFrontend> language) {
return stringList.stream().anyMatch(s -> language.getPrimitiveTypes().contains(s));
return stringList.stream().anyMatch(s -> language.getPrimitiveTypeNames().contains(s));
}

/**
Expand All @@ -400,7 +400,7 @@ private static List<String> joinPrimitive(
int index = 0;

for (String s : typeBlocks) {
if (language.getPrimitiveTypes().contains(s)) {
if (language.getPrimitiveTypeNames().contains(s)) {
if (primitiveType.length() > 0) {
primitiveType.append(" ");
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,10 @@ private constructor(

return if (language != null) {
try {
// Make sure, that our simple types are also known to the type manager
language.builtInTypes.values.forEach { TypeManager.getInstance().registerType(it) }

// Return a new language frontend
language.newFrontend(config, scopeManager)
} catch (e: Exception) {
when (e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import de.fraunhofer.aisec.cpg.graph.Node
import de.fraunhofer.aisec.cpg.graph.types.*
import java.io.File
import kotlin.reflect.KClass
import org.neo4j.ogm.annotation.Transient

/**
* Represents a programming language. When creating new languages in the CPG, one must derive custom
Expand All @@ -57,25 +56,13 @@ abstract class Language<T : LanguageFrontend> : Node() {
/** The class of the frontend which is used to parse files of this language. */
abstract val frontend: KClass<out T>

/** The primitive types of this language. */
/** The primitive type names of this language. */
@get:JsonIgnore
val primitiveTypes: Set<String>
get() = simpleTypes.keys
val primitiveTypeNames: Set<String>
get() = builtInTypes.keys

// TODO: Maybe make this abstract?
@get:JsonIgnore
@Transient
open val simpleTypes: Map<String, Type> =
mapOf(
"boolean" to IntegerType("boolean", 1, this, NumericType.Modifier.SIGNED),
"char" to IntegerType("char", 8, this, NumericType.Modifier.NOT_APPLICABLE),
"byte" to IntegerType("byte", 8, this, NumericType.Modifier.SIGNED),
"short" to IntegerType("short", 16, this, NumericType.Modifier.SIGNED),
"int" to IntegerType("int", 32, this, NumericType.Modifier.SIGNED),
"long" to IntegerType("long", 64, this, NumericType.Modifier.SIGNED),
"float" to FloatingPointType("float", 32, this, NumericType.Modifier.SIGNED),
"double" to FloatingPointType("double", 64, this, NumericType.Modifier.SIGNED),
)
/** The built-in types of this language. */
@get:JsonIgnore abstract val builtInTypes: Map<String, Type>

/** The access modifiers of this programming language */
open val accessModifiers: Set<String>
Expand All @@ -87,7 +74,7 @@ abstract class Language<T : LanguageFrontend> : Node() {
scopeManager: ScopeManager = ScopeManager(),
): T

fun getSimpleTypeOf(typeString: String) = simpleTypes[typeString]
fun getSimpleTypeOf(typeString: String) = builtInTypes[typeString]

/** Returns true if the [file] can be handled by the frontend of this language. */
fun handlesFile(file: File): Boolean {
Expand All @@ -103,7 +90,7 @@ abstract class Language<T : LanguageFrontend> : Node() {
result = 31 * result + fileExtensions.hashCode()
result = 31 * result + namespaceDelimiter.hashCode()
result = 31 * result + frontend.hashCode()
result = 31 * result + primitiveTypes.hashCode()
result = 31 * result + primitiveTypeNames.hashCode()
result = 31 * result + accessModifiers.hashCode()
return result
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ open class CLanguage :

@Transient
@JsonIgnore
override val simpleTypes: Map<String, Type> =
override val builtInTypes: Map<String, Type> =
mapOf(
"boolean" to IntegerType("boolean", 1, this, NumericType.Modifier.SIGNED),
"char" to IntegerType("char", 8, this, NumericType.Modifier.NOT_APPLICABLE),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ class CPPLanguage :
override val unknownTypeString = listOf("auto")

@Transient
override val simpleTypes =
override val builtInTypes =
mapOf(
"bool" to BooleanType("bool", 1, this, NumericType.Modifier.SIGNED),
"bool" to BooleanType("bool", language = this),
"char" to IntegerType("char", 8, this, NumericType.Modifier.NOT_APPLICABLE),
"byte" to IntegerType("byte", 8, this, NumericType.Modifier.SIGNED),
"short" to IntegerType("short", 16, this, NumericType.Modifier.SIGNED),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ import de.fraunhofer.aisec.cpg.TranslationConfiguration
import de.fraunhofer.aisec.cpg.graph.Node
import de.fraunhofer.aisec.cpg.graph.declarations.TranslationUnitDeclaration
import de.fraunhofer.aisec.cpg.graph.statements.expressions.ProblemExpression
import de.fraunhofer.aisec.cpg.graph.types.FloatingPointType
import de.fraunhofer.aisec.cpg.graph.types.IntegerType
import de.fraunhofer.aisec.cpg.graph.types.NumericType
import de.fraunhofer.aisec.cpg.graph.types.Type
import de.fraunhofer.aisec.cpg.sarif.PhysicalLocation
import java.io.File
import java.util.function.Supplier
Expand All @@ -43,7 +47,17 @@ class TestLanguage(namespaceDelimiter: String = "::") : Language<TestLanguageFro
override val fileExtensions: List<String> = listOf()
override val namespaceDelimiter: String
override val frontend: KClass<out TestLanguageFrontend> = TestLanguageFrontend::class

override val builtInTypes: Map<String, Type> =
mapOf(
"boolean" to IntegerType("boolean", 1, this, NumericType.Modifier.SIGNED),
"char" to IntegerType("char", 8, this, NumericType.Modifier.NOT_APPLICABLE),
"byte" to IntegerType("byte", 8, this, NumericType.Modifier.SIGNED),
"short" to IntegerType("short", 16, this, NumericType.Modifier.SIGNED),
"int" to IntegerType("int", 32, this, NumericType.Modifier.SIGNED),
"long" to IntegerType("long", 64, this, NumericType.Modifier.SIGNED),
"float" to FloatingPointType("float", 32, this, NumericType.Modifier.SIGNED),
"double" to FloatingPointType("double", 64, this, NumericType.Modifier.SIGNED),
)
init {
this.namespaceDelimiter = namespaceDelimiter
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,11 @@ import de.fraunhofer.aisec.cpg.TranslationConfiguration
import de.fraunhofer.aisec.cpg.frontends.HasGenerics
import de.fraunhofer.aisec.cpg.frontends.HasShortCircuitOperators
import de.fraunhofer.aisec.cpg.frontends.Language
import de.fraunhofer.aisec.cpg.graph.types.FloatingPointType
import de.fraunhofer.aisec.cpg.graph.types.IntegerType
import de.fraunhofer.aisec.cpg.graph.types.NumericType
import de.fraunhofer.aisec.cpg.graph.types.StringType
import de.fraunhofer.aisec.cpg.graph.types.*
import org.neo4j.ogm.annotation.Transient

/** The Go language. */
open class GoLanguage : Language<GoLanguageFrontend>(), HasShortCircuitOperators, HasGenerics {
class GoLanguage : Language<GoLanguageFrontend>(), HasShortCircuitOperators, HasGenerics {
override val fileExtensions = listOf("go")
override val namespaceDelimiter = "."
@Transient override val frontend = GoLanguageFrontend::class
Expand All @@ -46,21 +43,62 @@ open class GoLanguage : Language<GoLanguageFrontend>(), HasShortCircuitOperators
override val startCharacter = '['
override val endCharacter = ']'

/** See [Documentation](https://pkg.go.dev/builtin). */
@Transient
override val simpleTypes =
override val builtInTypes =
mapOf(
// https://pkg.go.dev/builtin#any
// TODO: Actually, this should be a type alias to interface{}
"any" to ObjectType("any", listOf(), false, this),
// https://pkg.go.dev/builtin#error
// TODO: Actually, this is an interface{ Error() string } type.
"error" to ObjectType("error", listOf(), false, this),
// https://pkg.go.dev/builtin#bool
"bool" to BooleanType("bool", language = this),
// https://pkg.go.dev/builtin#int
"int" to IntegerType("int", 32, this, NumericType.Modifier.SIGNED),
// // https://pkg.go.dev/builtin#int8
"int8" to IntegerType("int8", 8, this, NumericType.Modifier.SIGNED),
// https://pkg.go.dev/builtin#int16
"int16" to IntegerType("int16", 16, this, NumericType.Modifier.SIGNED),
// https://pkg.go.dev/builtin#int32
"int32" to IntegerType("int32", 32, this, NumericType.Modifier.SIGNED),
// https://pkg.go.dev/builtin#int64
"int64" to IntegerType("int64", 64, this, NumericType.Modifier.SIGNED),
// https://pkg.go.dev/builtin#uint
"uint" to IntegerType("uint", 32, this, NumericType.Modifier.UNSIGNED),
// https://pkg.go.dev/builtin#uint8
"uint8" to IntegerType("uint8", 8, this, NumericType.Modifier.UNSIGNED),
// https://pkg.go.dev/builtin#uint16
"uint16" to IntegerType("uint16", 16, this, NumericType.Modifier.UNSIGNED),
// https://pkg.go.dev/builtin#uint32
"uint32" to IntegerType("uint32", 32, this, NumericType.Modifier.UNSIGNED),
// https://pkg.go.dev/builtin#uint64
"uint64" to IntegerType("uint64", 64, this, NumericType.Modifier.UNSIGNED),
// https://pkg.go.dev/builtin#uintptr
"uintptr" to
IntegerType(
"uintptr",
null /* depends on the architecture, so we don't know */,
this,
NumericType.Modifier.UNSIGNED
),
// https://pkg.go.dev/builtin#float32
"float32" to FloatingPointType("float32", 32, this, NumericType.Modifier.SIGNED),
// https://pkg.go.dev/builtin#float64
"float64" to FloatingPointType("float64", 64, this, NumericType.Modifier.SIGNED),
"complex32" to NumericType("complex32", 32, this, NumericType.Modifier.NOT_APPLICABLE),
"complex64" to NumericType("complex54", 64, this, NumericType.Modifier.NOT_APPLICABLE),
// https://pkg.go.dev/builtin#complex64
"complex64" to NumericType("complex64", 64, this, NumericType.Modifier.NOT_APPLICABLE),
// https://pkg.go.dev/builtin#complex128
"complex128" to
NumericType("complex128", 128, this, NumericType.Modifier.NOT_APPLICABLE),
// https://pkg.go.dev/builtin#rune
// TODO: Actually, this should be a type alias to int32
"rune" to IntegerType("int32", 32, this, NumericType.Modifier.SIGNED),
// https://pkg.go.dev/builtin#byte
// TODO: Actually, this should be a type alias to uint8
"byte" to IntegerType("uint8", 8, this, NumericType.Modifier.UNSIGNED),
// https://pkg.go.dev/builtin#string
"string" to StringType("string", this)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,34 @@ open class JavaLanguage :
override val conjunctiveOperators = listOf("&&")
override val disjunctiveOperators = listOf("||")

/**
* See
* [Java Language Specification](https://docs.oracle.com/javase/specs/jls/se19/html/jls-4.html).
*/
@Transient
@JsonIgnore
override val simpleTypes =
override val builtInTypes =
mapOf(
"boolean" to IntegerType("boolean", 1, this, NumericType.Modifier.SIGNED),
// Boolean Types:
// https://docs.oracle.com/javase/specs/jls/se19/html/jls-4.html#jls-4.2.5
"boolean" to BooleanType("boolean", language = this),
"Boolean" to BooleanType("java.lang.Boolean", language = this),
"java.lang.Boolean" to BooleanType("java.lang.Boolean", language = this),

// Integral Types:
// https://docs.oracle.com/javase/specs/jls/se19/html/jls-4.html#jls-4.2.1
"byte" to IntegerType("byte", 8, this, NumericType.Modifier.SIGNED),
"char" to IntegerType("char", 16, this, NumericType.Modifier.SIGNED),
"char" to IntegerType("char", 16, this, NumericType.Modifier.UNSIGNED),
"short" to IntegerType("short", 16, this, NumericType.Modifier.SIGNED),
"int" to IntegerType("int", 32, this, NumericType.Modifier.SIGNED),
"long" to IntegerType("long", 64, this, NumericType.Modifier.SIGNED),

// Floating-Point Types:
// https://docs.oracle.com/javase/specs/jls/se19/html/jls-4.html#jls-4.2.3
"float" to FloatingPointType("float", 32, this, NumericType.Modifier.SIGNED),
"double" to FloatingPointType("double", 64, this, NumericType.Modifier.SIGNED),

// String: https://docs.oracle.com/javase/specs/jls/se19/html/jls-4.html#jls-4.3.3
"String" to StringType("java.lang.String", this),
"java.lang.String" to StringType("java.lang.String", this)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ class LLVMIRLanguage : Language<LLVMIRLanguageFrontend>() {
override val frontend: KClass<out LLVMIRLanguageFrontend> = LLVMIRLanguageFrontend::class

// TODO: In theory, the integers can have any bitwidth from 1 to 1^32 bits. It's not known if
// they are interpreted as signed or unsigned.
// they are interpreted as signed or unsigned.
@Transient
override val simpleTypes =
override val builtInTypes =
mapOf(
"i1" to IntegerType("i1", 1, this, NumericType.Modifier.NOT_APPLICABLE),
"i8" to IntegerType("i8", 8, this, NumericType.Modifier.NOT_APPLICABLE),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ class PythonLanguage : Language<PythonLanguageFrontend>(), HasShortCircuitOperat
override val conjunctiveOperators = listOf("and")
override val disjunctiveOperators = listOf("or")

/** See [Documentation](https://docs.python.org/3/library/stdtypes.html#). */
@Transient
override val simpleTypes =
override val builtInTypes =
mapOf(
"bool" to IntegerType("bool", 1, this, NumericType.Modifier.NOT_APPLICABLE),
"bool" to BooleanType("bool", language = this),
"int" to
IntegerType(
"int",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import de.fraunhofer.aisec.cpg.ScopeManager
import de.fraunhofer.aisec.cpg.TranslationConfiguration
import de.fraunhofer.aisec.cpg.frontends.HasShortCircuitOperators
import de.fraunhofer.aisec.cpg.frontends.Language
import de.fraunhofer.aisec.cpg.graph.types.*
import kotlin.reflect.KClass
import org.neo4j.ogm.annotation.Transient

Expand All @@ -42,6 +43,19 @@ open class JavaScriptLanguage : Language<TypeScriptLanguageFrontend>(), HasShort
override val conjunctiveOperators = listOf("&&", "&&=", "??", "??=")
override val disjunctiveOperators = listOf("||", "||=")

/**
* See
* [Documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#primitive_values).
*/
@Transient
override val builtInTypes =
mapOf(
"boolean" to BooleanType("boolean", language = this),
"number" to FloatingPointType("number", 64, this, NumericType.Modifier.SIGNED),
"bigint" to IntegerType("bigint", null, this, NumericType.Modifier.SIGNED),
"string" to StringType("string", this),
)

override fun newFrontend(
config: TranslationConfiguration,
scopeManager: ScopeManager,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
*/
package de.fraunhofer.aisec.cpg.frontends.typescript

import de.fraunhofer.aisec.cpg.graph.types.*

/** The TypeScript language. */
class TypeScriptLanguage : JavaScriptLanguage() {
override val fileExtensions = listOf("ts", "tsx")
Expand Down

0 comments on commit e32d4dc

Please sign in to comment.