Merge pull request #9144 from github/alexdenisov/introduce-visitors

Swift: Introduce visitors
This commit is contained in:
AlexDenisov
2022-05-13 17:57:47 +02:00
committed by GitHub
9 changed files with 206 additions and 26 deletions

View File

@@ -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 = [

View File

@@ -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;

View File

@@ -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

View 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

View 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

View 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

View 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

View 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

View 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