mirror of
https://github.com/github/codeql.git
synced 2026-04-27 01:35:13 +02:00
Merge pull request #9144 from github/alexdenisov/introduce-visitors
Swift: Introduce visitors
This commit is contained in:
@@ -9,6 +9,12 @@ swift_cc_binary(
|
||||
"SwiftDispatcher.h",
|
||||
"SwiftTagTraits.h",
|
||||
"main.cpp",
|
||||
"SwiftVisitor.h",
|
||||
"visitors/DeclVisitor.h",
|
||||
"visitors/ExprVisitor.h",
|
||||
"visitors/StmtVisitor.h",
|
||||
"visitors/TypeVisitor.h",
|
||||
"visitors/PatternVisitor.h",
|
||||
],
|
||||
visibility = ["//swift:__pkg__"],
|
||||
deps = [
|
||||
|
||||
@@ -57,9 +57,18 @@ class SwiftDispatcher {
|
||||
SwiftDispatcher(const swift::SourceManager& sourceManager, TrapArena& arena, TrapOutput& trap)
|
||||
: sourceManager{sourceManager}, arena{arena}, trap{trap} {}
|
||||
|
||||
template <typename T>
|
||||
void extract(T* entity) {
|
||||
fetchLabel(entity);
|
||||
// This is a helper method to emit TRAP entries for AST nodes that we don't fully support yet.
|
||||
template <typename Parent, typename Child>
|
||||
void TBD(Child* entity, const std::string& suffix) {
|
||||
using namespace std::string_literals;
|
||||
auto label = assignNewLabel(entity);
|
||||
auto kind = detail::getKindName<Parent>(static_cast<const Parent*>(entity)->getKind());
|
||||
auto name = "TBD ("s + kind + suffix + ")";
|
||||
if constexpr (std::is_same_v<Parent, swift::TypeBase>) {
|
||||
trap.emit(UnknownTypesTrap{label, name});
|
||||
} else {
|
||||
trap.emit(UnknownAstNodesTrap{label, name});
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -105,20 +114,6 @@ class SwiftDispatcher {
|
||||
return arena.allocateLabel<Tag>();
|
||||
}
|
||||
|
||||
// This is a helper method to emit TRAP entries for AST nodes that we don't fully support yet.
|
||||
template <typename Parent, typename Child>
|
||||
void TBD(Child* entity, const std::string& suffix) {
|
||||
using namespace std::string_literals;
|
||||
auto label = assignNewLabel(entity);
|
||||
auto kind = detail::getKindName<Parent>(static_cast<const Parent*>(entity)->getKind());
|
||||
auto name = "TBD ("s + kind + suffix + ")";
|
||||
if constexpr (std::is_same_v<Parent, swift::TypeBase>) {
|
||||
trap.emit(UnknownTypesTrap{label, name});
|
||||
} else {
|
||||
trap.emit(UnknownAstNodesTrap{label, name});
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Locatable>
|
||||
void attachLocation(Locatable locatable, TrapLabel<LocatableTag> locatableLabel) {
|
||||
attachLocation(&locatable, locatableLabel);
|
||||
@@ -162,12 +157,12 @@ class SwiftDispatcher {
|
||||
|
||||
// TODO: The following methods are supposed to redirect TRAP emission to correpsonding visitors,
|
||||
// which are to be introduced in follow-up PRs
|
||||
void visit(swift::Decl* decl) { TBD<swift::Decl>(decl, "Decl"); }
|
||||
void visit(swift::Stmt* stmt) { TBD<swift::Stmt>(stmt, "Stmt"); }
|
||||
void visit(swift::Expr* expr) { TBD<swift::Expr>(expr, "Expr"); }
|
||||
void visit(swift::Pattern* pattern) { TBD<swift::Pattern>(pattern, "Pattern"); }
|
||||
void visit(swift::TypeRepr* type) { TBD<swift::TypeRepr>(type, "TypeRepr"); }
|
||||
void visit(swift::TypeBase* type) { TBD<swift::TypeBase>(type, "Type"); }
|
||||
virtual void visit(swift::Decl* decl) = 0;
|
||||
virtual void visit(swift::Stmt* stmt) = 0;
|
||||
virtual void visit(swift::Expr* expr) = 0;
|
||||
virtual void visit(swift::Pattern* pattern) = 0;
|
||||
virtual void visit(swift::TypeRepr* type) = 0;
|
||||
virtual void visit(swift::TypeBase* type) = 0;
|
||||
|
||||
const swift::SourceManager& sourceManager;
|
||||
TrapArena& arena;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#include "swift/extractor/trap/generated/TrapClasses.h"
|
||||
#include "swift/extractor/trap/TrapOutput.h"
|
||||
#include "swift/extractor/SwiftDispatcher.h"
|
||||
#include "swift/extractor/SwiftVisitor.h"
|
||||
|
||||
using namespace codeql;
|
||||
|
||||
@@ -88,9 +88,9 @@ static void extractFile(const SwiftExtractorConfiguration& config,
|
||||
trap.assignKey(fileLabel, srcFilePath.str().str());
|
||||
trap.emit(FilesTrap{fileLabel, srcFilePath.str().str()});
|
||||
|
||||
SwiftDispatcher dispatcher(compiler.getSourceMgr(), arena, trap);
|
||||
SwiftVisitor visitor(compiler.getSourceMgr(), arena, trap);
|
||||
for (swift::Decl* decl : file.getTopLevelDecls()) {
|
||||
dispatcher.extract(decl);
|
||||
visitor.extract(decl);
|
||||
}
|
||||
|
||||
// TODO: Pick a better name to avoid collisions
|
||||
|
||||
36
swift/extractor/SwiftVisitor.h
Normal file
36
swift/extractor/SwiftVisitor.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "swift/extractor/SwiftDispatcher.h"
|
||||
#include "swift/extractor/visitors/DeclVisitor.h"
|
||||
#include "swift/extractor/visitors/ExprVisitor.h"
|
||||
#include "swift/extractor/visitors/StmtVisitor.h"
|
||||
#include "swift/extractor/visitors/TypeVisitor.h"
|
||||
#include "swift/extractor/visitors/PatternVisitor.h"
|
||||
|
||||
namespace codeql {
|
||||
|
||||
class SwiftVisitor : private SwiftDispatcher {
|
||||
public:
|
||||
using SwiftDispatcher::SwiftDispatcher;
|
||||
|
||||
template <typename T>
|
||||
void extract(T* entity) {
|
||||
fetchLabel(entity);
|
||||
}
|
||||
|
||||
private:
|
||||
void visit(swift::Decl* decl) override { declVisitor.visit(decl); }
|
||||
void visit(swift::Stmt* stmt) override { stmtVisitor.visit(stmt); }
|
||||
void visit(swift::Expr* expr) override { exprVisitor.visit(expr); }
|
||||
void visit(swift::Pattern* pattern) override { patternVisitor.visit(pattern); }
|
||||
void visit(swift::TypeRepr* type) override { TBD<swift::TypeRepr>(type, "TypeRepr"); }
|
||||
void visit(swift::TypeBase* type) override { typeVisitor.visit(type); }
|
||||
|
||||
DeclVisitor declVisitor{*this};
|
||||
ExprVisitor exprVisitor{*this};
|
||||
StmtVisitor stmtVisitor{*this};
|
||||
TypeVisitor typeVisitor{*this};
|
||||
PatternVisitor patternVisitor{*this};
|
||||
};
|
||||
|
||||
} // namespace codeql
|
||||
22
swift/extractor/visitors/DeclVisitor.h
Normal file
22
swift/extractor/visitors/DeclVisitor.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "swift/extractor/SwiftDispatcher.h"
|
||||
#include <swift/AST/ASTVisitor.h>
|
||||
|
||||
namespace codeql {
|
||||
|
||||
class DeclVisitor : public swift::DeclVisitor<DeclVisitor> {
|
||||
public:
|
||||
// SwiftDispatcher should outlive the DeclVisitor
|
||||
DeclVisitor(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
|
||||
|
||||
template <typename E>
|
||||
void visitDecl(E* decl) {
|
||||
dispatcher.TBD<swift::Decl>(decl, "Decl");
|
||||
}
|
||||
|
||||
private:
|
||||
SwiftDispatcher& dispatcher;
|
||||
};
|
||||
|
||||
} // namespace codeql
|
||||
22
swift/extractor/visitors/ExprVisitor.h
Normal file
22
swift/extractor/visitors/ExprVisitor.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "swift/extractor/SwiftDispatcher.h"
|
||||
#include <swift/AST/ASTVisitor.h>
|
||||
|
||||
namespace codeql {
|
||||
|
||||
class ExprVisitor : public swift::ExprVisitor<ExprVisitor> {
|
||||
public:
|
||||
// SwiftDispatcher should outlive the ExprVisitor
|
||||
ExprVisitor(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
|
||||
|
||||
template <typename E>
|
||||
void visitExpr(E* expr) {
|
||||
dispatcher.TBD<swift::Expr>(expr, "Expr");
|
||||
}
|
||||
|
||||
private:
|
||||
SwiftDispatcher& dispatcher;
|
||||
};
|
||||
|
||||
} // namespace codeql
|
||||
38
swift/extractor/visitors/PatternVisitor.h
Normal file
38
swift/extractor/visitors/PatternVisitor.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "swift/extractor/SwiftDispatcher.h"
|
||||
#include <swift/AST/ASTVisitor.h>
|
||||
|
||||
namespace codeql {
|
||||
|
||||
namespace detail {
|
||||
// swift code lacks default implementations of visitor for some entities. We can add those here
|
||||
// while we do not have yet all implemented. This is a simplified version of the corresponding Expr
|
||||
// code in swift/AST/ASTVisitor.h
|
||||
template <typename CrtpSubclass>
|
||||
class PatchedPatternVisitor : public swift::PatternVisitor<CrtpSubclass> {
|
||||
public:
|
||||
#define PATTERN(CLASS, PARENT) \
|
||||
void visit##CLASS##Pattern(swift::CLASS##Pattern* E) { \
|
||||
return static_cast<CrtpSubclass*>(this)->visit##PARENT(E); \
|
||||
}
|
||||
#include "swift/AST/PatternNodes.def"
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class PatternVisitor : public detail::PatchedPatternVisitor<PatternVisitor> {
|
||||
public:
|
||||
// SwiftDispatcher should outlive the PatternVisitor
|
||||
PatternVisitor(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
|
||||
|
||||
template <typename E>
|
||||
void visitPattern(E* pattern) {
|
||||
dispatcher.TBD<swift::Pattern>(pattern, "Pattern");
|
||||
}
|
||||
|
||||
private:
|
||||
SwiftDispatcher& dispatcher;
|
||||
};
|
||||
|
||||
} // namespace codeql
|
||||
39
swift/extractor/visitors/StmtVisitor.h
Normal file
39
swift/extractor/visitors/StmtVisitor.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include "swift/extractor/SwiftDispatcher.h"
|
||||
#include <swift/AST/ASTVisitor.h>
|
||||
|
||||
namespace codeql {
|
||||
|
||||
namespace detail {
|
||||
// swift code lacks default implementations of visitor for some entities. We can add those here
|
||||
// while we do not have yet all implemented. This is a simplified version of the corresponding Expr
|
||||
// code in swift/AST/ASTVisitor.h
|
||||
template <typename CrtpSubclass>
|
||||
class PatchedStmtVisitor : public swift::StmtVisitor<CrtpSubclass> {
|
||||
public:
|
||||
#define ABSTRACT_STMT(CLASS, PARENT) \
|
||||
void visit##CLASS##Stmt(swift::CLASS##Stmt* E) { \
|
||||
return static_cast<CrtpSubclass*>(this)->visit##PARENT(E); \
|
||||
}
|
||||
#define STMT(CLASS, PARENT) ABSTRACT_STMT(CLASS, PARENT)
|
||||
#include "swift/AST/StmtNodes.def"
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class StmtVisitor : public detail::PatchedStmtVisitor<StmtVisitor> {
|
||||
public:
|
||||
// SwiftDispatcher should outlive the StmtVisitor
|
||||
StmtVisitor(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
|
||||
|
||||
template <typename E>
|
||||
void visitStmt(E* stmt) {
|
||||
dispatcher.TBD<swift::Stmt>(stmt, "Stmt");
|
||||
}
|
||||
|
||||
private:
|
||||
SwiftDispatcher& dispatcher;
|
||||
};
|
||||
|
||||
} // namespace codeql
|
||||
22
swift/extractor/visitors/TypeVisitor.h
Normal file
22
swift/extractor/visitors/TypeVisitor.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "swift/extractor/SwiftDispatcher.h"
|
||||
#include <swift/AST/TypeVisitor.h>
|
||||
|
||||
namespace codeql {
|
||||
|
||||
class TypeVisitor : public swift::TypeVisitor<TypeVisitor> {
|
||||
public:
|
||||
// SwiftDispatcher should outlive the TypeVisitor
|
||||
TypeVisitor(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
|
||||
|
||||
template <typename E>
|
||||
void visitType(E* type) {
|
||||
dispatcher.TBD<swift::TypeBase>(type, "Type");
|
||||
}
|
||||
|
||||
private:
|
||||
SwiftDispatcher& dispatcher;
|
||||
};
|
||||
|
||||
} // namespace codeql
|
||||
Reference in New Issue
Block a user