Skip to content

Commit 3a49ee9

Browse files
authored
Merge pull request #68550 from hamishknight/pillar-of-garbage
2 parents 68a7a94 + febb019 commit 3a49ee9

File tree

8 files changed

+62
-41
lines changed

8 files changed

+62
-41
lines changed

include/swift/AST/DiagnosticConsumer.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,9 @@ class DiagnosticConsumer {
122122
/// Invoked whenever the frontend emits a diagnostic.
123123
///
124124
/// \param SM The source manager associated with the source locations in
125-
/// this diagnostic.
125+
/// this diagnostic. NOTE: Do not persist either the SourceManager, or the
126+
/// buffer names from the SourceManager, since it may not outlive the
127+
/// DiagnosticConsumer (this is the case when building module interfaces).
126128
///
127129
/// \param Info Information describing the diagnostic.
128130
virtual void handleDiagnostic(SourceManager &SM,

include/swift/Basic/Edit.h

+19-5
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,34 @@
1313
#ifndef SWIFT_BASIC_EDIT_H
1414
#define SWIFT_BASIC_EDIT_H
1515

16+
#include "llvm/ADT/ArrayRef.h"
1617
#include "swift/Basic/LLVM.h"
1718
#include "swift/Basic/SourceLoc.h"
1819

1920
namespace swift {
2021
class SourceManager;
2122
class CharSourceRange;
2223

23-
struct SingleEdit {
24-
SourceManager &SM;
25-
CharSourceRange Range;
26-
std::string Text;
24+
/// A set of edits made to a source file.
25+
class SourceEdits final {
26+
public:
27+
struct Edit {
28+
std::string Path;
29+
std::string Text;
30+
unsigned Offset;
31+
unsigned Length;
32+
};
33+
34+
private:
35+
std::vector<Edit> Edits;
36+
37+
public:
38+
ArrayRef<Edit> getEdits() const { return Edits; }
39+
40+
void addEdit(SourceManager &SM, CharSourceRange Range, StringRef Text);
2741
};
2842

29-
void writeEditsInJson(ArrayRef<SingleEdit> Edits, llvm::raw_ostream &OS);
43+
void writeEditsInJson(const SourceEdits &Edits, llvm::raw_ostream &OS);
3044
}
3145

3246
#endif // SWIFT_BASIC_EDIT_H

lib/Basic/Edit.cpp

+26-17
Original file line numberDiff line numberDiff line change
@@ -14,28 +14,37 @@
1414
#include "swift/Basic/Edit.h"
1515
#include "swift/Basic/SourceManager.h"
1616

17+
using namespace swift;
18+
19+
void SourceEdits::addEdit(SourceManager &SM, CharSourceRange Range,
20+
StringRef Text) {
21+
SourceLoc Loc = Range.getStart();
22+
unsigned BufID = SM.findBufferContainingLoc(Loc);
23+
unsigned Offset = SM.getLocOffsetInBuffer(Loc, BufID);
24+
unsigned Length = Range.getByteLength();
25+
StringRef Path = SM.getIdentifierForBuffer(BufID);
26+
27+
// NOTE: We cannot store SourceManager here since this logic is used by a
28+
// DiagnosticConsumer where the SourceManager may not remain valid. This is
29+
// the case when e.g build swift interfaces, we create a fresh
30+
// CompilerInstance for a limited scope, but diagnostics are passed outside of
31+
// it.
32+
Edits.push_back({Path.str(), Text.str(), Offset, Length});
33+
}
34+
1735
void swift::
18-
writeEditsInJson(ArrayRef<SingleEdit> AllEdits, llvm::raw_ostream &OS) {
36+
writeEditsInJson(const SourceEdits &AllEdits, llvm::raw_ostream &OS) {
1937
OS << "[\n";
20-
for (auto &Edit : AllEdits) {
21-
SourceManager &SM = Edit.SM;
22-
CharSourceRange Range = Edit.Range;
23-
StringRef Text = Edit.Text;
24-
SourceLoc Loc = Range.getStart();
25-
unsigned BufID = SM.findBufferContainingLoc(Loc);
26-
unsigned Offset = SM.getLocOffsetInBuffer(Loc, BufID);
27-
unsigned Length = Range.getByteLength();
28-
StringRef Path(SM.getIdentifierForBuffer(BufID));
29-
38+
for (auto &Edit : AllEdits.getEdits()) {
3039
OS << " {\n";
3140
OS << " \"file\": \"";
32-
OS.write_escaped(Path) << "\",\n";
33-
OS << " \"offset\": " << Offset << ",\n";
34-
if (Length != 0)
35-
OS << " \"remove\": " << Length << ",\n";
36-
if (!Text.empty()) {
41+
OS.write_escaped(Edit.Path) << "\",\n";
42+
OS << " \"offset\": " << Edit.Offset << ",\n";
43+
if (Edit.Length != 0)
44+
OS << " \"remove\": " << Edit.Length << ",\n";
45+
if (!Edit.Text.empty()) {
3746
OS << " \"text\": \"";
38-
OS.write_escaped(Text) << "\",\n";
47+
OS.write_escaped(Edit.Text) << "\",\n";
3948
}
4049
OS << " },\n";
4150
}

lib/Frontend/SerializedDiagnosticConsumer.cpp

+6-5
Original file line numberDiff line numberDiff line change
@@ -228,11 +228,12 @@ namespace serialized_diagnostics {
228228
unsigned SerializedDiagnosticConsumer::getEmitFile(
229229
SourceManager &SM, StringRef Filename, unsigned bufferID
230230
) {
231-
// NOTE: Using Filename.data() here relies on SourceMgr using
232-
// const char* as buffer identifiers. This is fast, but may
233-
// be brittle. We can always switch over to using a StringMap.
234-
// Note that the logic in EditorDiagConsumer::getBufferInfo
235-
// will also need changing.
231+
// FIXME: Using Filename.data() here is wrong, since the provided
232+
// SourceManager may not live as long as this consumer (which is
233+
// the case if it's a diagnostic produced from building a module
234+
// interface). We ought to switch over to using a StringMap once
235+
// buffer names are unique (currently not the case for
236+
// pretty-printed decl buffers).
236237
unsigned &existingEntry = State->Files[Filename.data()];
237238
if (existingEntry)
238239
return existingEntry;

lib/FrontendTool/FrontendTool.cpp

+4-5
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ class JSONFixitWriter
216216
std::string FixitsOutputPath;
217217
std::unique_ptr<llvm::raw_ostream> OSPtr;
218218
bool FixitAll;
219-
std::vector<SingleEdit> AllEdits;
219+
SourceEdits AllEdits;
220220

221221
public:
222222
JSONFixitWriter(std::string fixitsOutputPath,
@@ -229,9 +229,8 @@ class JSONFixitWriter
229229
const DiagnosticInfo &Info) override {
230230
if (!(FixitAll || shouldTakeFixit(Info)))
231231
return;
232-
for (const auto &Fix : Info.FixIts) {
233-
AllEdits.push_back({SM, Fix.getRange(), Fix.getText().str()});
234-
}
232+
for (const auto &Fix : Info.FixIts)
233+
AllEdits.addEdit(SM, Fix.getRange(), Fix.getText());
235234
}
236235

237236
bool finishProcessing() override {
@@ -251,7 +250,7 @@ class JSONFixitWriter
251250
return true;
252251
}
253252

254-
swift::writeEditsInJson(llvm::makeArrayRef(AllEdits), *OS);
253+
swift::writeEditsInJson(AllEdits, *OS);
255254
return false;
256255
}
257256
};

lib/IDE/Utils.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -722,14 +722,14 @@ void swift::ide::SourceEditConsumer::acceptMacroExpansionBuffer(
722722

723723
struct swift::ide::SourceEditJsonConsumer::Implementation {
724724
llvm::raw_ostream &OS;
725-
std::vector<SingleEdit> AllEdits;
725+
SourceEdits AllEdits;
726726
Implementation(llvm::raw_ostream &OS) : OS(OS) {}
727727
~Implementation() {
728728
writeEditsInJson(AllEdits, OS);
729729
}
730730
void accept(SourceManager &SM, CharSourceRange Range,
731731
llvm::StringRef Text) {
732-
AllEdits.push_back({SM, Range, Text.str()});
732+
AllEdits.addEdit(SM, Range, Text);
733733
}
734734
};
735735

tools/SourceKit/lib/SwiftLang/SwiftEditor.cpp

-4
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,6 @@ BufferInfoSharedPtr
9191
EditorDiagConsumer::getBufferInfo(StringRef FileName,
9292
llvm::Optional<unsigned> BufferID,
9393
swift::SourceManager &SM) {
94-
// NOTE: Using StringRef as a key here relies on SourceMgr using const char*
95-
// as buffer identifiers. This is fast, but may be brittle. We can always
96-
// switch over to using a StringMap. Note that the logic in
97-
// SerializedDiagnosticConsumer::getEmitFile will also need changing.
9894
auto Result = BufferInfos.find(FileName);
9995
if (Result != BufferInfos.end())
10096
return Result->second;

tools/SourceKit/lib/SwiftLang/SwiftEditorDiagConsumer.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
#include "SourceKit/Core/LangSupport.h"
1717
#include "swift/AST/DiagnosticConsumer.h"
1818
#include "llvm/ADT/DenseMap.h"
19-
#include "llvm/ADT/MapVector.h"
19+
#include "llvm/ADT/StringMap.h"
2020

2121
namespace SourceKit {
2222

@@ -27,7 +27,7 @@ class EditorDiagConsumer : public swift::DiagnosticConsumer {
2727
llvm::DenseMap<unsigned, DiagnosticsTy> BufferDiagnostics;
2828
DiagnosticsTy InvalidLocDiagnostics;
2929

30-
llvm::MapVector<StringRef, BufferInfoSharedPtr> BufferInfos;
30+
llvm::StringMap<BufferInfoSharedPtr> BufferInfos;
3131

3232
int LastDiagBufferID = -1;
3333
unsigned LastDiagIndex = 0;

0 commit comments

Comments
 (0)