Skip to content

Commit eacb9f1

Browse files
authored
Merge pull request github#9144 from github/alexdenisov/introduce-visitors
Swift: Introduce visitors
2 parents 7ef9a19 + 1b75034 commit eacb9f1

File tree

9 files changed

+206
-26
lines changed

9 files changed

+206
-26
lines changed

swift/extractor/BUILD.bazel

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ swift_cc_binary(
99
"SwiftDispatcher.h",
1010
"SwiftTagTraits.h",
1111
"main.cpp",
12+
"SwiftVisitor.h",
13+
"visitors/DeclVisitor.h",
14+
"visitors/ExprVisitor.h",
15+
"visitors/StmtVisitor.h",
16+
"visitors/TypeVisitor.h",
17+
"visitors/PatternVisitor.h",
1218
],
1319
visibility = ["//swift:__pkg__"],
1420
deps = [

swift/extractor/SwiftDispatcher.h

Lines changed: 18 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,18 @@ class SwiftDispatcher {
5757
SwiftDispatcher(const swift::SourceManager& sourceManager, TrapArena& arena, TrapOutput& trap)
5858
: sourceManager{sourceManager}, arena{arena}, trap{trap} {}
5959

60-
template <typename T>
61-
void extract(T* entity) {
62-
fetchLabel(entity);
60+
// This is a helper method to emit TRAP entries for AST nodes that we don't fully support yet.
61+
template <typename Parent, typename Child>
62+
void TBD(Child* entity, const std::string& suffix) {
63+
using namespace std::string_literals;
64+
auto label = assignNewLabel(entity);
65+
auto kind = detail::getKindName<Parent>(static_cast<const Parent*>(entity)->getKind());
66+
auto name = "TBD ("s + kind + suffix + ")";
67+
if constexpr (std::is_same_v<Parent, swift::TypeBase>) {
68+
trap.emit(UnknownTypesTrap{label, name});
69+
} else {
70+
trap.emit(UnknownAstNodesTrap{label, name});
71+
}
6372
}
6473

6574
private:
@@ -105,20 +114,6 @@ class SwiftDispatcher {
105114
return arena.allocateLabel<Tag>();
106115
}
107116

108-
// This is a helper method to emit TRAP entries for AST nodes that we don't fully support yet.
109-
template <typename Parent, typename Child>
110-
void TBD(Child* entity, const std::string& suffix) {
111-
using namespace std::string_literals;
112-
auto label = assignNewLabel(entity);
113-
auto kind = detail::getKindName<Parent>(static_cast<const Parent*>(entity)->getKind());
114-
auto name = "TBD ("s + kind + suffix + ")";
115-
if constexpr (std::is_same_v<Parent, swift::TypeBase>) {
116-
trap.emit(UnknownTypesTrap{label, name});
117-
} else {
118-
trap.emit(UnknownAstNodesTrap{label, name});
119-
}
120-
}
121-
122117
template <typename Locatable>
123118
void attachLocation(Locatable locatable, TrapLabel<LocatableTag> locatableLabel) {
124119
attachLocation(&locatable, locatableLabel);
@@ -162,12 +157,12 @@ class SwiftDispatcher {
162157

163158
// TODO: The following methods are supposed to redirect TRAP emission to correpsonding visitors,
164159
// which are to be introduced in follow-up PRs
165-
void visit(swift::Decl* decl) { TBD<swift::Decl>(decl, "Decl"); }
166-
void visit(swift::Stmt* stmt) { TBD<swift::Stmt>(stmt, "Stmt"); }
167-
void visit(swift::Expr* expr) { TBD<swift::Expr>(expr, "Expr"); }
168-
void visit(swift::Pattern* pattern) { TBD<swift::Pattern>(pattern, "Pattern"); }
169-
void visit(swift::TypeRepr* type) { TBD<swift::TypeRepr>(type, "TypeRepr"); }
170-
void visit(swift::TypeBase* type) { TBD<swift::TypeBase>(type, "Type"); }
160+
virtual void visit(swift::Decl* decl) = 0;
161+
virtual void visit(swift::Stmt* stmt) = 0;
162+
virtual void visit(swift::Expr* expr) = 0;
163+
virtual void visit(swift::Pattern* pattern) = 0;
164+
virtual void visit(swift::TypeRepr* type) = 0;
165+
virtual void visit(swift::TypeBase* type) = 0;
171166

172167
const swift::SourceManager& sourceManager;
173168
TrapArena& arena;

swift/extractor/SwiftExtractor.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
#include "swift/extractor/trap/generated/TrapClasses.h"
1616
#include "swift/extractor/trap/TrapOutput.h"
17-
#include "swift/extractor/SwiftDispatcher.h"
17+
#include "swift/extractor/SwiftVisitor.h"
1818

1919
using namespace codeql;
2020

@@ -88,9 +88,9 @@ static void extractFile(const SwiftExtractorConfiguration& config,
8888
trap.assignKey(fileLabel, srcFilePath.str().str());
8989
trap.emit(FilesTrap{fileLabel, srcFilePath.str().str()});
9090

91-
SwiftDispatcher dispatcher(compiler.getSourceMgr(), arena, trap);
91+
SwiftVisitor visitor(compiler.getSourceMgr(), arena, trap);
9292
for (swift::Decl* decl : file.getTopLevelDecls()) {
93-
dispatcher.extract(decl);
93+
visitor.extract(decl);
9494
}
9595

9696
// TODO: Pick a better name to avoid collisions

swift/extractor/SwiftVisitor.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#pragma once
2+
3+
#include "swift/extractor/SwiftDispatcher.h"
4+
#include "swift/extractor/visitors/DeclVisitor.h"
5+
#include "swift/extractor/visitors/ExprVisitor.h"
6+
#include "swift/extractor/visitors/StmtVisitor.h"
7+
#include "swift/extractor/visitors/TypeVisitor.h"
8+
#include "swift/extractor/visitors/PatternVisitor.h"
9+
10+
namespace codeql {
11+
12+
class SwiftVisitor : private SwiftDispatcher {
13+
public:
14+
using SwiftDispatcher::SwiftDispatcher;
15+
16+
template <typename T>
17+
void extract(T* entity) {
18+
fetchLabel(entity);
19+
}
20+
21+
private:
22+
void visit(swift::Decl* decl) override { declVisitor.visit(decl); }
23+
void visit(swift::Stmt* stmt) override { stmtVisitor.visit(stmt); }
24+
void visit(swift::Expr* expr) override { exprVisitor.visit(expr); }
25+
void visit(swift::Pattern* pattern) override { patternVisitor.visit(pattern); }
26+
void visit(swift::TypeRepr* type) override { TBD<swift::TypeRepr>(type, "TypeRepr"); }
27+
void visit(swift::TypeBase* type) override { typeVisitor.visit(type); }
28+
29+
DeclVisitor declVisitor{*this};
30+
ExprVisitor exprVisitor{*this};
31+
StmtVisitor stmtVisitor{*this};
32+
TypeVisitor typeVisitor{*this};
33+
PatternVisitor patternVisitor{*this};
34+
};
35+
36+
} // namespace codeql
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#pragma once
2+
3+
#include "swift/extractor/SwiftDispatcher.h"
4+
#include <swift/AST/ASTVisitor.h>
5+
6+
namespace codeql {
7+
8+
class DeclVisitor : public swift::DeclVisitor<DeclVisitor> {
9+
public:
10+
// SwiftDispatcher should outlive the DeclVisitor
11+
DeclVisitor(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
12+
13+
template <typename E>
14+
void visitDecl(E* decl) {
15+
dispatcher.TBD<swift::Decl>(decl, "Decl");
16+
}
17+
18+
private:
19+
SwiftDispatcher& dispatcher;
20+
};
21+
22+
} // namespace codeql
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#pragma once
2+
3+
#include "swift/extractor/SwiftDispatcher.h"
4+
#include <swift/AST/ASTVisitor.h>
5+
6+
namespace codeql {
7+
8+
class ExprVisitor : public swift::ExprVisitor<ExprVisitor> {
9+
public:
10+
// SwiftDispatcher should outlive the ExprVisitor
11+
ExprVisitor(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
12+
13+
template <typename E>
14+
void visitExpr(E* expr) {
15+
dispatcher.TBD<swift::Expr>(expr, "Expr");
16+
}
17+
18+
private:
19+
SwiftDispatcher& dispatcher;
20+
};
21+
22+
} // namespace codeql
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#pragma once
2+
3+
#include "swift/extractor/SwiftDispatcher.h"
4+
#include <swift/AST/ASTVisitor.h>
5+
6+
namespace codeql {
7+
8+
namespace detail {
9+
// swift code lacks default implementations of visitor for some entities. We can add those here
10+
// while we do not have yet all implemented. This is a simplified version of the corresponding Expr
11+
// code in swift/AST/ASTVisitor.h
12+
template <typename CrtpSubclass>
13+
class PatchedPatternVisitor : public swift::PatternVisitor<CrtpSubclass> {
14+
public:
15+
#define PATTERN(CLASS, PARENT) \
16+
void visit##CLASS##Pattern(swift::CLASS##Pattern* E) { \
17+
return static_cast<CrtpSubclass*>(this)->visit##PARENT(E); \
18+
}
19+
#include "swift/AST/PatternNodes.def"
20+
};
21+
22+
} // namespace detail
23+
24+
class PatternVisitor : public detail::PatchedPatternVisitor<PatternVisitor> {
25+
public:
26+
// SwiftDispatcher should outlive the PatternVisitor
27+
PatternVisitor(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
28+
29+
template <typename E>
30+
void visitPattern(E* pattern) {
31+
dispatcher.TBD<swift::Pattern>(pattern, "Pattern");
32+
}
33+
34+
private:
35+
SwiftDispatcher& dispatcher;
36+
};
37+
38+
} // namespace codeql
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#pragma once
2+
3+
#include "swift/extractor/SwiftDispatcher.h"
4+
#include <swift/AST/ASTVisitor.h>
5+
6+
namespace codeql {
7+
8+
namespace detail {
9+
// swift code lacks default implementations of visitor for some entities. We can add those here
10+
// while we do not have yet all implemented. This is a simplified version of the corresponding Expr
11+
// code in swift/AST/ASTVisitor.h
12+
template <typename CrtpSubclass>
13+
class PatchedStmtVisitor : public swift::StmtVisitor<CrtpSubclass> {
14+
public:
15+
#define ABSTRACT_STMT(CLASS, PARENT) \
16+
void visit##CLASS##Stmt(swift::CLASS##Stmt* E) { \
17+
return static_cast<CrtpSubclass*>(this)->visit##PARENT(E); \
18+
}
19+
#define STMT(CLASS, PARENT) ABSTRACT_STMT(CLASS, PARENT)
20+
#include "swift/AST/StmtNodes.def"
21+
};
22+
23+
} // namespace detail
24+
25+
class StmtVisitor : public detail::PatchedStmtVisitor<StmtVisitor> {
26+
public:
27+
// SwiftDispatcher should outlive the StmtVisitor
28+
StmtVisitor(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
29+
30+
template <typename E>
31+
void visitStmt(E* stmt) {
32+
dispatcher.TBD<swift::Stmt>(stmt, "Stmt");
33+
}
34+
35+
private:
36+
SwiftDispatcher& dispatcher;
37+
};
38+
39+
} // namespace codeql
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#pragma once
2+
3+
#include "swift/extractor/SwiftDispatcher.h"
4+
#include <swift/AST/TypeVisitor.h>
5+
6+
namespace codeql {
7+
8+
class TypeVisitor : public swift::TypeVisitor<TypeVisitor> {
9+
public:
10+
// SwiftDispatcher should outlive the TypeVisitor
11+
TypeVisitor(SwiftDispatcher& dispatcher) : dispatcher(dispatcher) {}
12+
13+
template <typename E>
14+
void visitType(E* type) {
15+
dispatcher.TBD<swift::TypeBase>(type, "Type");
16+
}
17+
18+
private:
19+
SwiftDispatcher& dispatcher;
20+
};
21+
22+
} // namespace codeql

0 commit comments

Comments
 (0)