Skip to content

Commit 680b7a1

Browse files
committed
Swift: extract location extraction into a separate entity
1 parent e9da5ee commit 680b7a1

File tree

4 files changed

+84
-65
lines changed

4 files changed

+84
-65
lines changed

swift/extractor/infra/SwiftDispatcher.h

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "swift/extractor/infra/SwiftTagTraits.h"
1212
#include "swift/extractor/trap/generated/TrapClasses.h"
1313
#include "swift/extractor/infra/file/PathHash.h"
14+
#include "swift/extractor/infra/SwiftLocationExtractor.h"
1415

1516
namespace codeql {
1617

@@ -29,8 +30,7 @@ class SwiftDispatcher {
2930
const swift::Expr*,
3031
const swift::Pattern*,
3132
const swift::TypeRepr*,
32-
const swift::TypeBase*,
33-
std::filesystem::path>;
33+
const swift::TypeBase*>;
3434

3535
template <typename E>
3636
static constexpr bool IsStorable = std::is_constructible_v<Store::Handle, const E&>;
@@ -48,10 +48,11 @@ class SwiftDispatcher {
4848
: sourceManager{sourceManager},
4949
trap{trap},
5050
currentModule{currentModule},
51-
currentPrimarySourceFile{currentPrimarySourceFile} {
51+
currentPrimarySourceFile{currentPrimarySourceFile},
52+
locationExtractor(trap) {
5253
if (currentPrimarySourceFile) {
5354
// we make sure the file is in the trap output even if the source is empty
54-
fetchLabel(getFilePath(currentPrimarySourceFile->getFilename()));
55+
locationExtractor.emitFile(currentPrimarySourceFile->getFilename());
5556
}
5657
}
5758

@@ -325,20 +326,7 @@ class SwiftDispatcher {
325326
void attachLocation(swift::SourceLoc start,
326327
swift::SourceLoc end,
327328
TrapLabel<LocatableTag> locatableLabel) {
328-
if (!start.isValid() || !end.isValid()) {
329-
// invalid locations seem to come from entities synthesized by the compiler
330-
return;
331-
}
332-
auto file = getFilePath(sourceManager.getDisplayNameForLoc(start));
333-
DbLocation entry{{}};
334-
entry.file = fetchLabel(file);
335-
std::tie(entry.start_line, entry.start_column) = sourceManager.getLineAndColumnInBuffer(start);
336-
std::tie(entry.end_line, entry.end_column) = sourceManager.getLineAndColumnInBuffer(end);
337-
entry.id = trap.createLabel<DbLocationTag>('{', entry.file, "}:", entry.start_line, ':',
338-
entry.start_column, ':', entry.end_line, ':',
339-
entry.end_column);
340-
emit(entry);
341-
emit(LocatableLocationsTrap{locatableLabel, entry.id});
329+
locationExtractor.attachLocation(sourceManager, start, end, locatableLabel);
342330
}
343331

344332
template <typename Tag, typename... Ts>
@@ -391,19 +379,14 @@ class SwiftDispatcher {
391379
virtual void visit(const swift::TypeRepr* typeRepr, swift::Type type) = 0;
392380
virtual void visit(const swift::TypeBase* type) = 0;
393381

394-
void visit(const std::filesystem::path& file) {
395-
auto entry = createEntry(file, file.string());
396-
entry.name = file.string();
397-
emit(entry);
398-
}
399-
400382
const swift::SourceManager& sourceManager;
401383
TrapDomain& trap;
402384
Store store;
403385
Store::Handle waitingForNewLabel{std::monostate{}};
404386
swift::ModuleDecl& currentModule;
405387
swift::SourceFile* currentPrimarySourceFile;
406388
std::unordered_set<swift::ModuleDecl*> encounteredModules;
389+
SwiftLocationExtractor locationExtractor;
407390
};
408391

409392
} // namespace codeql
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#pragma once
2+
3+
#include <swift/AST/SourceFile.h>
4+
#include <swift/Basic/SourceManager.h>
5+
6+
#include "swift/extractor/trap/TrapDomain.h"
7+
#include "swift/extractor/trap/generated/TrapEntries.h"
8+
#include "swift/extractor/trap/generated/TrapClasses.h"
9+
#include "swift/extractor/infra/file/PathHash.h"
10+
11+
namespace codeql {
12+
13+
class TrapDomain;
14+
15+
class SwiftLocationExtractor {
16+
public:
17+
explicit SwiftLocationExtractor(TrapDomain& trap) : trap(trap) {}
18+
19+
void attachLocation(const swift::SourceManager& sourceManager,
20+
swift::SourceLoc start,
21+
swift::SourceLoc end,
22+
TrapLabel<LocatableTag> locatableLabel) {
23+
if (!start.isValid() || !end.isValid()) {
24+
// invalid locations seem to come from entities synthesized by the compiler
25+
return;
26+
}
27+
auto file = getFilePath(sourceManager.getDisplayNameForLoc(start));
28+
DbLocation entry{{}};
29+
entry.file = fetchFileLabel(file);
30+
std::tie(entry.start_line, entry.start_column) = sourceManager.getLineAndColumnInBuffer(start);
31+
std::tie(entry.end_line, entry.end_column) = sourceManager.getLineAndColumnInBuffer(end);
32+
entry.id = trap.createLabel<DbLocationTag>('{', entry.file, "}:", entry.start_line, ':',
33+
entry.start_column, ':', entry.end_line, ':',
34+
entry.end_column);
35+
trap.emit(entry);
36+
trap.emit(LocatableLocationsTrap{locatableLabel, entry.id});
37+
}
38+
39+
void emitFile(llvm::StringRef path) { fetchFileLabel(getFilePath(path)); }
40+
41+
private:
42+
TrapLabel<FileTag> fetchFileLabel(const std::filesystem::path& file) {
43+
if (store.count(file)) {
44+
return store[file];
45+
}
46+
47+
DbFile entry({});
48+
entry.id = trap.createLabel<DbFileTag>(file.string());
49+
entry.name = file.string();
50+
trap.emit(entry);
51+
store[file] = entry.id;
52+
return entry.id;
53+
}
54+
55+
static std::filesystem::path getFilePath(std::string_view path) {
56+
// TODO: this needs more testing
57+
// TODO: check canonicalization of names on a case insensitive filesystems
58+
// TODO: make symlink resolution conditional on CODEQL_PRESERVE_SYMLINKS=true
59+
std::error_code ec;
60+
auto ret = std::filesystem::canonical(path, ec);
61+
if (ec) {
62+
std::cerr << "Cannot get real path: " << std::quoted(path) << ": " << ec.message() << "\n";
63+
return {};
64+
}
65+
return ret;
66+
}
67+
68+
TrapDomain& trap;
69+
std::unordered_map<std::filesystem::path, TrapLabel<FileTag>> store;
70+
};
71+
72+
} // namespace codeql

swift/extractor/invocation/CodeQLDiagnosticsConsumer.cpp

Lines changed: 1 addition & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#include "swift/extractor/invocation/CodeQLDiagnosticsConsumer.h"
2-
#include "swift/extractor/trap/TrapDomain.h"
32
#include "swift/extractor/trap/generated/TrapEntries.h"
4-
#include "swift/extractor/trap/generated/TrapClasses.h"
53

64
#include <swift/AST/DiagnosticEngine.h>
75
#include <swift/Basic/SourceManager.h>
@@ -27,43 +25,6 @@ static int diagnosticsKind(const swift::DiagnosticInfo& diagInfo) {
2725
return 0;
2826
}
2927

30-
static std::filesystem::path getFilePath(std::string_view path) {
31-
// TODO: this needs more testing
32-
// TODO: check canonicalization of names on a case insensitive filesystems
33-
// TODO: make symlink resolution conditional on CODEQL_PRESERVE_SYMLINKS=true
34-
std::error_code ec;
35-
auto ret = std::filesystem::canonical(path, ec);
36-
if (ec) {
37-
std::cerr << "Cannot get real path: " << std::quoted(path) << ": " << ec.message() << "\n";
38-
return {};
39-
}
40-
return ret;
41-
}
42-
43-
static void attachLocation(TrapDomain& trap,
44-
swift::SourceManager& sourceManager,
45-
const swift::DiagnosticInfo& diagInfo,
46-
DiagnosticsTrap& locatable) {
47-
auto loc = diagInfo.Loc;
48-
if (!loc.isValid()) {
49-
return;
50-
}
51-
auto filepath = getFilePath(sourceManager.getDisplayNameForLoc(loc));
52-
DbFile file({});
53-
file.id = trap.createLabel<DbFileTag>();
54-
file.name = filepath;
55-
trap.emit(file);
56-
57-
DbLocation location({});
58-
location.id = trap.createLabel<DbLocationTag>();
59-
location.file = file.id;
60-
std::tie(location.start_line, location.start_column) =
61-
sourceManager.getLineAndColumnInBuffer(loc);
62-
std::tie(location.end_line, location.end_column) = sourceManager.getLineAndColumnInBuffer(loc);
63-
trap.emit(location);
64-
trap.emit(LocatableLocationsTrap{locatable.id, location.id});
65-
}
66-
6728
void CodeQLDiagnosticsConsumer::handleDiagnostic(swift::SourceManager& sourceManager,
6829
const swift::DiagnosticInfo& diagInfo) {
6930
auto message = getDiagMessage(sourceManager, diagInfo);
@@ -72,7 +33,7 @@ void CodeQLDiagnosticsConsumer::handleDiagnostic(swift::SourceManager& sourceMan
7233
diag.kind = diagnosticsKind(diagInfo);
7334
diag.text = message;
7435
trap.emit(diag);
75-
attachLocation(trap, sourceManager, diagInfo, diag);
36+
locationExtractor.attachLocation(sourceManager, diagInfo.Loc, diagInfo.Loc, diag.id);
7637
}
7738

7839
std::string CodeQLDiagnosticsConsumer::getDiagMessage(swift::SourceManager& sourceManager,
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
#pragma once
22

33
#include <swift/AST/DiagnosticConsumer.h>
4+
#include "swift/extractor/infra/SwiftLocationExtractor.h"
45

56
namespace codeql {
67

78
class TrapDomain;
89

910
class CodeQLDiagnosticsConsumer : public swift::DiagnosticConsumer {
1011
public:
11-
explicit CodeQLDiagnosticsConsumer(TrapDomain& targetFile) : trap(targetFile) {}
12+
explicit CodeQLDiagnosticsConsumer(TrapDomain& targetFile)
13+
: trap(targetFile), locationExtractor(targetFile) {}
1214
void handleDiagnostic(swift::SourceManager& sourceManager,
1315
const swift::DiagnosticInfo& diagInfo) override;
1416

1517
private:
1618
static std::string getDiagMessage(swift::SourceManager& sourceManager,
1719
const swift::DiagnosticInfo& diagInfo);
1820
TrapDomain& trap;
21+
SwiftLocationExtractor locationExtractor;
1922
};
2023

2124
} // namespace codeql

0 commit comments

Comments
 (0)