All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.fraunhofer.aisec.cpg.frontends.LanguageTraits.kt Maven / Gradle / Ivy

Go to download

A simple library to extract a code property graph out of source code. It has support for multiple passes that can extend the analysis after the graph is constructed.

There is a newer version: 8.3.0
Show newest version
/*
 * Copyright (c) 2021, Fraunhofer AISEC. All rights reserved.
 *
 * 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.
 *
 *                    $$$$$$\  $$$$$$$\   $$$$$$\
 *                   $$  __$$\ $$  __$$\ $$  __$$\
 *                   $$ /  \__|$$ |  $$ |$$ /  \__|
 *                   $$ |      $$$$$$$  |$$ |$$$$\
 *                   $$ |      $$  ____/ $$ |\_$$ |
 *                   $$ |  $$\ $$ |      $$ |  $$ |
 *                   \$$$$$   |$$ |      \$$$$$   |
 *                    \______/ \__|       \______/
 *
 */
package de.fraunhofer.aisec.cpg.frontends

import de.fraunhofer.aisec.cpg.ScopeManager
import de.fraunhofer.aisec.cpg.TranslationContext
import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.TranslationUnitDeclaration
import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.MemberExpression
import de.fraunhofer.aisec.cpg.graph.types.Type
import de.fraunhofer.aisec.cpg.passes.SymbolResolver

/**
 * A language trait is a feature or trait that is common to a group of programming languages. Any
 * [Language] that supports them should implement the desired trait interface. Examples could be the
 * support of pointers, support for templates or generics.
 *
 * Currently, this interface has no methods. However, in the future, this could be used to execute
 * language/frontend-specific code for the particular trait. This could help to fine-tune the
 * [CallResolver] for specific languages.
 */
interface LanguageTrait

/** A language trait, that specifies that this language has support for templates or generics. */
interface HasGenerics : LanguageTrait {
    /** The char starting the template specific code (e.g. `<`) */
    val startCharacter: Char

    /** The char ending the template specific code (e.g. `>`) */
    val endCharacter: Char
}

/** A language trait, that specifies that this language has support for templates or generics. */
interface HasTemplates : HasGenerics {
    /**
     * This function can be used to fine-tune the resolution of template function calls.
     *
     * Note: The function itself should NOT set the [CallExpression.invokes] but rather return a
     * list of possible candidates.
     *
     * @return a pair in which the first member denotes whether resolution was successful and the
     *   second parameter is a list of [FunctionDeclaration] candidates.
     */
    fun handleTemplateFunctionCalls(
        curClass: RecordDeclaration?,
        templateCall: CallExpression,
        applyInference: Boolean,
        ctx: TranslationContext,
        currentTU: TranslationUnitDeclaration
    ): Pair>
}

/**
 * A language trait that specifies, that this language has support for default arguments, e.g. in
 * functions.
 */
interface HasDefaultArguments : LanguageTrait

/**
 * A language trait that specifies that this language has a complex call resolution that we need to
 * fine-tune in the language implementation.
 */
interface HasComplexCallResolution : LanguageTrait {
    /**
     * A function that can be used to fine-tune resolution of a normal (non-method) [call].
     *
     * Note: The function itself should NOT set the [CallExpression.invokes] but rather return a
     * list of possible candidates.
     *
     * @return a list of [FunctionDeclaration] candidates.
     */
    fun refineNormalCallResolution(
        call: CallExpression,
        ctx: TranslationContext,
        currentTU: TranslationUnitDeclaration
    ): List

    /**
     * A function that can be used to fine-tune resolution of a method [call].
     *
     * Note: The function itself should NOT set the [CallExpression.invokes] but rather return a
     * list of possible candidates.
     *
     * @return a list of [FunctionDeclaration] candidates.
     */
    fun refineMethodCallResolution(
        curClass: RecordDeclaration?,
        possibleContainingTypes: Set,
        call: CallExpression,
        ctx: TranslationContext,
        currentTU: TranslationUnitDeclaration,
        callResolver: SymbolResolver
    ): List

    /**
     * A function to fine-tune the results of [CallResolver.getInvocationCandidatesFromRecord],
     * which retrieves a list of [FunctionDeclaration] candidates from a [RecordDeclaration].
     *
     * Note: The function itself should NOT set the [CallExpression.invokes] but rather return a
     * list of possible candidates.
     *
     * @return a list of [FunctionDeclaration] candidates.
     */
    fun refineInvocationCandidatesFromRecord(
        recordDeclaration: RecordDeclaration,
        call: CallExpression,
        name: String,
        ctx: TranslationContext
    ): List
}

/** A language trait that specifies if the language supports function pointers. */
interface HasFunctionPointers : LanguageTrait

/**
 * A language trait that specifies if the language has the concept of "structs". The alternative is
 * to use classes. Note that some languages can have both and that in some languages structs and
 * classes are essentially the same. This is mostly used to determine if an inferred record
 * declaration *can be* a struct or *must be* a class.
 */
interface HasStructs : LanguageTrait

/**
 * A language trait that specifies if the language has the concept of "classes". The alternative is
 * to use structs. Note that some languages can have both and that in some languages structs and
 * classes are essentially the same. This is mostly used to determine if an inferred record
 * declaration *can be* a class or *must be* a struct.
 */
interface HasClasses : LanguageTrait

/**
 * A language trait, that specifies that this language has support for superclasses. If so, we
 * should consider the specified superclass keyword to resolve calls etc.
 */
interface HasSuperClasses : LanguageTrait {
    /**
     * Determines which keyword is used to access functions, etc. of the superclass of an object
     * (often "super).
     */
    val superClassKeyword: String

    fun handleSuperCall(
        callee: MemberExpression,
        curClass: RecordDeclaration,
        scopeManager: ScopeManager,
    ): Boolean
}

/**
 * A language trait, that specifies that this language has certain qualifiers. If so, we should
 * consider them when parsing the types.
 */
interface HasQualifier : LanguageTrait {
    /** The qualifiers which exist in the language. */
    val qualifiers: List
}

/**
 * A language trait, that specifies that this language has "elaborated type specifiers". If so, we
 * should consider them when parsing the types.
 */
interface HasElaboratedTypeSpecifier : LanguageTrait {
    val elaboratedTypeSpecifier: List
}

/**
 * A language trait, that specifies that this language has specifiers which let us conclude that we
 * do not know the type. If so, we should consider them when parsing the types.
 */
interface HasUnknownType : LanguageTrait {
    val unknownTypeString: List
}

/**
 * A language trait, that specifies that this language has binary operators that will short-circuit
 * evaluation if the logical result is already known: '&&', '||' in Java or 'and','or' in Python
 */
interface HasShortCircuitOperators : LanguageTrait {
    /**
     * Operations which only execute the rhs of a binary operation if the lhs is `true`. Typically,
     * these are `&&`, `and` or `^`
     */
    val conjunctiveOperators: List

    /**
     * Operations which only execute the rhs of a binary operation if the lhs is `false`. Typically,
     * these are `||`, `or` or `v`
     */
    val disjunctiveOperators: List

    /**
     * The union of [conjunctiveOperators] and [disjunctiveOperators], i.e., all binary operators of
     * this language which result in some kind of branching behavior.
     */
    val operatorCodes: Set
        get() = conjunctiveOperators.union(disjunctiveOperators)
}

/**
 * A language trait, that specifies that this language treats functions "first-class citizens",
 * meaning they can be assigned to variables and passed as arguments to other functions.
 */
interface HasFirstClassFunctions

/**
 * A language trait, that specifies that this language has an "anonymous" identifier, used for
 * unused parameters or suppressed assignments.
 */
interface HasAnonymousIdentifier {
    val anonymousIdentifier: String
        get() = "_"
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy