diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/ScopeManager.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/ScopeManager.kt index 42b2cd8739a..6f154c7a13b 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/ScopeManager.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/ScopeManager.kt @@ -248,7 +248,7 @@ class ScopeManager : ScopeProvider { is RecordDeclaration -> RecordScope(nodeToScope) is TemplateDeclaration -> TemplateScope(nodeToScope) is TranslationUnitDeclaration -> FileScope(nodeToScope) - is NamespaceDeclaration -> newNameScopeIfNecessary(nodeToScope) + is NamespaceDeclaration -> newNamespaceIfNecessary(nodeToScope) else -> { LOGGER.error( "No known scope for AST node of type {}", @@ -269,7 +269,7 @@ class ScopeManager : ScopeProvider { } /** - * A small internal helper function used by [enterScope] to create a [NameScope]. + * A small internal helper function used by [enterScope] to create a [NamespaceScope]. * * The issue with name scopes, such as a namespace, is that it can exist across several files, * i.e. translation units, represented by different [NamespaceDeclaration] nodes. But, in order @@ -277,15 +277,15 @@ class ScopeManager : ScopeProvider { * all declarations, such as classes, independently of the translation units. Therefore, we need * to check, whether such as node already exists. If it does already exist: * - we update the scope map so that the current [NamespaceDeclaration] points to the existing - * [NameScope] + * [NamespaceScope] * - we return null, indicating to [enterScope], that no new scope needs to be pushed by * [enterScope]. * - * Otherwise, we return a new name scope. + * Otherwise, we return a new namespace scope. */ - private fun newNameScopeIfNecessary(nodeToScope: NamespaceDeclaration): NameScope? { + private fun newNamespaceIfNecessary(nodeToScope: NamespaceDeclaration): NamespaceScope? { val existingScope = - filterScopes { it is NameScope && it.name == nodeToScope.name }.firstOrNull() + filterScopes { it is NamespaceScope && it.name == nodeToScope.name }.firstOrNull() return if (existingScope != null) { // update the AST node to this namespace declaration @@ -299,7 +299,7 @@ class ScopeManager : ScopeProvider { // does not need to push a new scope null } else { - NameScope(nodeToScope) + NamespaceScope(nodeToScope) } } diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/NameScope.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/NameScope.kt index fd48c7230dd..4280e774b99 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/NameScope.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/NameScope.kt @@ -29,10 +29,10 @@ import de.fraunhofer.aisec.cpg.graph.Node /** * A scope which acts as a namespace with a certain name, which is prefixed to all local names - * declared in it. This could be a package or other structural elements, like a class. In the latter - * case, the derived [RecordScope] should be used. + * declared in it. This could be a package or other structural elements, like a class. In the first + * case, the derived [NamespaceScope], in the latter case, the derived [RecordScope] should be used. */ -open class NameScope(node: Node?) : StructureDeclarationScope(node) { +sealed class NameScope(node: Node?) : StructureDeclarationScope(node) { init { astNode = node diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/NamespaceScope.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/NamespaceScope.kt new file mode 100644 index 00000000000..01c6266c009 --- /dev/null +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/NamespaceScope.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024, 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.graph.scopes + +import de.fraunhofer.aisec.cpg.graph.declarations.NamespaceDeclaration + +/** + * This scope is opened up by a [NamespaceDeclaration] and represents the scope of the whole + * namespace. This scope is special in a way that it will only exist once (per [GlobalScope]) and + * contains all symbols declared in this namespace, even if they are spread across multiple files. + */ +class NamespaceScope(astNode: NamespaceDeclaration) : NameScope(astNode) diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/Scope.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/Scope.kt index e0dd0a18fcf..081eee8c9a1 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/Scope.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/Scope.kt @@ -55,7 +55,7 @@ typealias SymbolMap = MutableMap> * restriction and can act as namespaces to avoid name collisions. */ @NodeEntity -abstract class Scope( +sealed class Scope( @Relationship(value = "SCOPE", direction = Relationship.Direction.INCOMING) @JsonBackReference open var astNode: Node? diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/StructureDeclarationScope.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/StructureDeclarationScope.kt index e29ec310f7c..76a2795f680 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/StructureDeclarationScope.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/StructureDeclarationScope.kt @@ -25,11 +25,18 @@ */ package de.fraunhofer.aisec.cpg.graph.scopes +import de.fraunhofer.aisec.cpg.ScopeManager import de.fraunhofer.aisec.cpg.graph.DeclarationHolder import de.fraunhofer.aisec.cpg.graph.Node import de.fraunhofer.aisec.cpg.graph.declarations.* -open class StructureDeclarationScope(astNode: Node?) : ValueDeclarationScope(astNode) { +/** + * This sealed (and abstract) class represents a [Scope] that in addition to declare variables also + * defines structures, such as classes, namespaces, etc. + * + * This is actually only needed because of the legacy [ScopeManager.resolve] function. + */ +sealed class StructureDeclarationScope(astNode: Node?) : ValueDeclarationScope(astNode) { val structureDeclarations: List get() { return symbols diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/ValueDeclarationScope.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/ValueDeclarationScope.kt index 501c779849d..462b4a00e8f 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/ValueDeclarationScope.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/scopes/ValueDeclarationScope.kt @@ -39,7 +39,7 @@ import org.slf4j.LoggerFactory * Is a scope where local variables can be declared and independent of specific language constructs. * Works for if, for, and extends to the block scope */ -abstract class ValueDeclarationScope(astNode: Node?) : Scope(astNode) { +sealed class ValueDeclarationScope(astNode: Node?) : Scope(astNode) { val valueDeclarations: List get() { return symbols.flatMap { it.value }.filterIsInstance() diff --git a/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/GoHandler.kt b/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/GoHandler.kt index 656894b58de..c4ae1d9e117 100644 --- a/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/GoHandler.kt +++ b/cpg-language-go/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/golang/GoHandler.kt @@ -30,6 +30,7 @@ import de.fraunhofer.aisec.cpg.graph.Node import de.fraunhofer.aisec.cpg.graph.ProblemNode import de.fraunhofer.aisec.cpg.graph.declarations.NamespaceDeclaration import de.fraunhofer.aisec.cpg.graph.scopes.NameScope +import de.fraunhofer.aisec.cpg.graph.scopes.NamespaceScope import de.fraunhofer.aisec.cpg.graph.statements.expressions.Literal import de.fraunhofer.aisec.cpg.helpers.Util import java.util.function.Supplier @@ -100,7 +101,7 @@ abstract class GoHandler