Skip to content

Commit f547583

Browse files
committed
[APIDigester] Allow outputting module differ diagnostics as JSON for other tools to consume
1 parent 972dc99 commit f547583

File tree

5 files changed

+376
-1
lines changed

5 files changed

+376
-1
lines changed

include/swift/APIDigester/ModuleDiagsConsumer.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include "swift/AST/DiagnosticConsumer.h"
2424
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
2525

26+
#include "llvm/ADT/StringSet.h"
27+
#include "llvm/Support/JSON.h"
2628
#include "llvm/Support/raw_ostream.h"
2729
#include <set>
2830

@@ -42,6 +44,27 @@ class ModuleDifferDiagsConsumer: public PrintingDiagnosticConsumer {
4244
void handleDiagnostic(SourceManager &SM, const DiagnosticInfo &Info) override;
4345
};
4446

47+
struct ModuleDifferDiagnosticInfo {
48+
DiagID ID;
49+
llvm::SmallString<256> Text;
50+
51+
ModuleDifferDiagnosticInfo(DiagID ID, llvm::SmallString<256> Text)
52+
: ID(ID), Text(Text) {}
53+
54+
void serialize(llvm::json::OStream &JSON);
55+
};
56+
57+
/// Diagnostic consumer that outputs module differ diags as JSON.
58+
class ModuleDifferDiagsJSONConsumer : public DiagnosticConsumer {
59+
llvm::raw_ostream &OS;
60+
std::vector<ModuleDifferDiagnosticInfo> AllDiags;
61+
62+
public:
63+
ModuleDifferDiagsJSONConsumer(llvm::raw_ostream &OS) : OS(OS){};
64+
~ModuleDifferDiagsJSONConsumer();
65+
void handleDiagnostic(SourceManager &SM, const DiagnosticInfo &Info) override;
66+
};
67+
4568
class FilteringDiagnosticConsumer: public DiagnosticConsumer {
4669
bool HasError = false;
4770
std::unique_ptr<DiagnosticConsumer> subConsumer;

lib/APIDigester/ModuleDiagsConsumer.cpp

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515
//
1616
//===----------------------------------------------------------------------===//
1717

18+
#include "swift/APIDigester/ModuleDiagsConsumer.h"
1819
#include "swift/AST/DiagnosticEngine.h"
1920
#include "swift/AST/DiagnosticsModuleDiffer.h"
20-
#include "swift/APIDigester/ModuleDiagsConsumer.h"
21+
#include "swift/Basic/SourceManager.h"
2122

2223
using namespace swift;
2324

@@ -81,6 +82,81 @@ static StringRef getCategoryName(uint32_t ID) {
8182
return "/* Others */";
8283
}
8384
}
85+
86+
static StringRef getSerializedIdentifier(uint32_t ID) {
87+
switch (ID) {
88+
case LocalDiagID::removed_decl:
89+
return "removedDecl";
90+
case LocalDiagID::moved_decl:
91+
return "movedDecl";
92+
case LocalDiagID::decl_kind_changed:
93+
return "declKindChanged";
94+
case LocalDiagID::renamed_decl:
95+
return "renamedDecl";
96+
case LocalDiagID::objc_name_change:
97+
return "objcNameChange";
98+
case LocalDiagID::decl_attr_change:
99+
return "declAttrChange";
100+
case LocalDiagID::decl_new_attr:
101+
return "declNewAttr";
102+
case LocalDiagID::func_self_access_change:
103+
return "funcSelfAccessChange";
104+
case LocalDiagID::new_decl_without_intro:
105+
return "newDeclWithoutIntro";
106+
case LocalDiagID::default_arg_removed:
107+
return "defaultArgRemoved";
108+
case LocalDiagID::decl_type_change:
109+
return "declTypeChange";
110+
case LocalDiagID::func_type_escaping_changed:
111+
return "funcTypeEscapingChanged";
112+
case LocalDiagID::param_ownership_change:
113+
return "paramOwnershipChange";
114+
case LocalDiagID::type_witness_change:
115+
return "typeWitnessChange";
116+
case LocalDiagID::raw_type_change:
117+
return "rawTypeChange";
118+
case LocalDiagID::generic_sig_change:
119+
return "genericSigChange";
120+
case LocalDiagID::enum_case_added:
121+
return "enumCaseAdded";
122+
case LocalDiagID::decl_added:
123+
return "declAdded";
124+
case LocalDiagID::decl_reorder:
125+
return "declReorder";
126+
case LocalDiagID::var_has_fixed_order_change:
127+
return "varHasFixedOrderChange";
128+
case LocalDiagID::func_has_fixed_order_change:
129+
return "funcHasFixedOrderChange";
130+
case LocalDiagID::conformance_added:
131+
return "conformanceAdded";
132+
case LocalDiagID::conformance_removed:
133+
return "conformanceRemoved";
134+
case LocalDiagID::optional_req_changed:
135+
return "optionalReqChanged";
136+
case LocalDiagID::existing_conformance_added:
137+
return "existingConformanceAdded";
138+
case LocalDiagID::default_associated_type_removed:
139+
return "defaultAssociatedTypeRemoved";
140+
case LocalDiagID::protocol_req_added:
141+
return "protocolReqAdded";
142+
case LocalDiagID::decl_new_witness_table_entry:
143+
return "declNewWitnessTableEntry";
144+
case LocalDiagID::super_class_removed:
145+
return "superClassRemoved";
146+
case LocalDiagID::super_class_changed:
147+
return "superClassChanged";
148+
case LocalDiagID::no_longer_open:
149+
return "noLongerOpen";
150+
case LocalDiagID::desig_init_added:
151+
return "desigInitAdded";
152+
case LocalDiagID::added_invisible_designated_init:
153+
return "addedInvisibleDesignatedInit";
154+
case LocalDiagID::not_inheriting_convenience_inits:
155+
return "notInheritingConvenienceInits";
156+
default:
157+
return "other";
158+
}
159+
}
84160
}
85161

86162
swift::ide::api::
@@ -123,6 +199,45 @@ swift::ide::api::ModuleDifferDiagsConsumer::~ModuleDifferDiagsConsumer() {
123199
}
124200
}
125201

202+
void swift::ide::api::ModuleDifferDiagnosticInfo::serialize(
203+
llvm::json::OStream &JSON) {
204+
JSON.object([&]() {
205+
JSON.attribute("identifier", getSerializedIdentifier((uint32_t)ID));
206+
JSON.attribute("text", Text);
207+
});
208+
}
209+
210+
void swift::ide::api::ModuleDifferDiagsJSONConsumer::handleDiagnostic(
211+
SourceManager &SM, const DiagnosticInfo &Info) {
212+
llvm::SmallString<256> Text;
213+
{
214+
llvm::raw_svector_ostream Out(Text);
215+
DiagnosticEngine::formatDiagnosticText(Out, Info.FormatString,
216+
Info.FormatArgs);
217+
}
218+
219+
AllDiags.push_back(ModuleDifferDiagnosticInfo(Info.ID, Text));
220+
}
221+
222+
swift::ide::api::ModuleDifferDiagsJSONConsumer::
223+
~ModuleDifferDiagsJSONConsumer() {
224+
llvm::json::OStream JSON(OS, 2);
225+
226+
JSON.object([&]() {
227+
JSON.attributeObject("version", [&]() {
228+
JSON.attribute("major", 0);
229+
JSON.attribute("minor", 1);
230+
});
231+
JSON.attributeArray("diagnostics", [&]() {
232+
for (auto &Info : AllDiags) {
233+
Info.serialize(JSON);
234+
}
235+
});
236+
});
237+
238+
JSON.flush();
239+
}
240+
126241
bool swift::ide::api::
127242
FilteringDiagnosticConsumer::shouldProceed(const DiagnosticInfo &Info) {
128243
if (allowedBreakages->empty()) {
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
{
2+
"version": {
3+
"major": 0,
4+
"minor": 1
5+
},
6+
"diagnostics": [
7+
{
8+
"identifier": "declTypeChange",
9+
"text": "cake: Constructor S1.init(_:) has parameter 0 type change from Swift.Int to Swift.Double"
10+
},
11+
{
12+
"identifier": "funcSelfAccessChange",
13+
"text": "cake: Func S1.foo1() has self access kind changing from NonMutating to Mutating"
14+
},
15+
{
16+
"identifier": "declNewAttr",
17+
"text": "cake: Func S1.foo3() is now static"
18+
},
19+
{
20+
"identifier": "declNewAttr",
21+
"text": "cake: Func C1.foo1() is now not static"
22+
},
23+
{
24+
"identifier": "declTypeChange",
25+
"text": "cake: Func C1.foo2(_:) has parameter 0 type change from Swift.Int to () -> ()"
26+
},
27+
{
28+
"identifier": "declAttrChange",
29+
"text": "cake: Var C1.CIIns1 changes from weak to strong"
30+
},
31+
{
32+
"identifier": "declAttrChange",
33+
"text": "cake: Var C1.CIIns2 changes from strong to weak"
34+
},
35+
{
36+
"identifier": "superClassChanged",
37+
"text": "cake: Class C4 has changed its super class from APINotesTest.OldType to APINotesTest.NewType"
38+
},
39+
{
40+
"identifier": "declNewAttr",
41+
"text": "cake: Enum IceKind is now without @frozen"
42+
},
43+
{
44+
"identifier": "conformanceRemoved",
45+
"text": "cake: Enum IceKind has removed conformance to Sendable"
46+
},
47+
{
48+
"identifier": "genericSigChange",
49+
"text": "cake: Func P1.P1Constraint() has generic signature change from <Self where Self : cake.P1, Self : cake.P2> to <Self where Self : cake.P1>"
50+
},
51+
{
52+
"identifier": "conformanceRemoved",
53+
"text": "cake: Struct fixedLayoutStruct has removed conformance to P1"
54+
},
55+
{
56+
"identifier": "enumCaseAdded",
57+
"text": "cake: EnumElement FrozenKind.AddedCase has been added as a new enum case"
58+
},
59+
{
60+
"identifier": "defaultArgRemoved",
61+
"text": "cake: Func C7.foo(_:_:) has removed default argument from parameter 0"
62+
},
63+
{
64+
"identifier": "defaultArgRemoved",
65+
"text": "cake: Func C7.foo(_:_:) has removed default argument from parameter 1"
66+
},
67+
{
68+
"identifier": "genericSigChange",
69+
"text": "cake: Protocol P3 has generic signature change from <Self : cake.P1, Self : cake.P2> to <Self : cake.P1, Self : cake.P4>"
70+
},
71+
{
72+
"identifier": "conformanceRemoved",
73+
"text": "cake: Protocol P3 has removed inherited protocol P2"
74+
},
75+
{
76+
"identifier": "conformanceAdded",
77+
"text": "cake: Protocol P3 has added inherited protocol P4"
78+
},
79+
{
80+
"identifier": "defaultAssociatedTypeRemoved",
81+
"text": "cake: AssociatedType AssociatedTypePro.T1 has removed default type Swift.Int"
82+
},
83+
{
84+
"identifier": "declTypeChange",
85+
"text": "cake: AssociatedType AssociatedTypePro.T3 has default type change from cake.C1 to cake.C6"
86+
},
87+
{
88+
"identifier": "removedDecl",
89+
"text": "cake: Accessor RemoveSetters.Value.Set() has been removed"
90+
},
91+
{
92+
"identifier": "removedDecl",
93+
"text": "cake: Accessor RemoveSetters.subscript(_:).Set() has been removed"
94+
},
95+
{
96+
"identifier": "protocolReqAdded",
97+
"text": "cake: AssociatedType RequiementChanges.addedTypeWithoutDefault has been added as a protocol requirement"
98+
},
99+
{
100+
"identifier": "protocolReqAdded",
101+
"text": "cake: Func RequiementChanges.addedFunc() has been added as a protocol requirement"
102+
},
103+
{
104+
"identifier": "protocolReqAdded",
105+
"text": "cake: Var RequiementChanges.addedVar has been added as a protocol requirement"
106+
},
107+
{
108+
"identifier": "superClassRemoved",
109+
"text": "cake: Class SuperClassRemoval has removed its super class cake.C3"
110+
},
111+
{
112+
"identifier": "notInheritingConvenienceInits",
113+
"text": "cake: Class SuperClassRemoval no longer inherits convenience inits from its superclass"
114+
},
115+
{
116+
"identifier": "declKindChanged",
117+
"text": "cake: Class ClassToStruct has been changed to a Struct"
118+
},
119+
{
120+
"identifier": "desigInitAdded",
121+
"text": "cake: Constructor ClassWithMissingDesignatedInits.init() has been added as a designated initializer to an open class"
122+
},
123+
{
124+
"identifier": "declKindChanged",
125+
"text": "cake: Protocol ProtocolToEnum has been changed to a Enum"
126+
},
127+
{
128+
"identifier": "superClassChanged",
129+
"text": "cake: Class SubGenericClass has changed its super class from cake.GenericClass<cake.P1> to cake.GenericClass<cake.P2>"
130+
},
131+
{
132+
"identifier": "optionalReqChanged",
133+
"text": "cake: Func ObjCProtocol.removeOptional() is no longer an optional requirement"
134+
},
135+
{
136+
"identifier": "removedDecl",
137+
"text": "cake: Accessor GlobalVarChangedToLet.Set() has been removed"
138+
},
139+
{
140+
"identifier": "noLongerOpen",
141+
"text": "cake: Func ClassWithOpenMember.foo() is no longer open for subclassing"
142+
},
143+
{
144+
"identifier": "noLongerOpen",
145+
"text": "cake: Var ClassWithOpenMember.property is no longer open for subclassing"
146+
},
147+
{
148+
"identifier": "noLongerOpen",
149+
"text": "cake: Accessor ClassWithOpenMember.property.Get() is no longer open for subclassing"
150+
},
151+
{
152+
"identifier": "noLongerOpen",
153+
"text": "cake: Func ClassWithOpenMember.bar() is no longer open for subclassing"
154+
},
155+
{
156+
"identifier": "declKindChanged",
157+
"text": "cake: InfixOperator ..*.. has been changed to a PrefixOperator"
158+
},
159+
{
160+
"identifier": "paramOwnershipChange",
161+
"text": "cake: Func ownershipChange(_:_:) has parameter 0 changing from InOut to Default"
162+
},
163+
{
164+
"identifier": "paramOwnershipChange",
165+
"text": "cake: Func ownershipChange(_:_:) has parameter 1 changing from Shared to Owned"
166+
},
167+
{
168+
"identifier": "declTypeChange",
169+
"text": "cake: TypeAlias TChangesFromIntToString.T has underlying type change from Swift.Int to Swift.String"
170+
},
171+
{
172+
"identifier": "funcSelfAccessChange",
173+
"text": "cake: Func HasMutatingMethodClone.foo() has self access kind changing from Mutating to NonMutating"
174+
},
175+
{
176+
"identifier": "objcNameChange",
177+
"text": "cake: Class SwiftObjcClass has ObjC name change from OldObjCClass to NewObjCClass"
178+
},
179+
{
180+
"identifier": "objcNameChange",
181+
"text": "cake: Func SwiftObjcClass.foo(a:b:c:) has ObjC name change from OldObjCFool:OldObjCA:OldObjCB: to NewObjCFool:NewObjCA:NewObjCB:"
182+
},
183+
{
184+
"identifier": "desigInitAdded",
185+
"text": "cake: Constructor AddingNewDesignatedInit.init(_:) has been added as a designated initializer to an open class"
186+
},
187+
{
188+
"identifier": "renamedDecl",
189+
"text": "cake: Func S1.foo5(x:y:) has been renamed to Func foo5(x:y:z:)"
190+
},
191+
{
192+
"identifier": "removedDecl",
193+
"text": "cake: Constructor Somestruct2.init(_:) has been removed"
194+
},
195+
{
196+
"identifier": "renamedDecl",
197+
"text": "cake: Struct Somestruct2 has been renamed to Struct NSSomestruct2"
198+
},
199+
{
200+
"identifier": "removedDecl",
201+
"text": "cake: Func C4.foo() has been removed"
202+
},
203+
{
204+
"identifier": "removedDecl",
205+
"text": "cake: Func RequiementChanges.removedFunc() has been removed"
206+
},
207+
{
208+
"identifier": "removedDecl",
209+
"text": "cake: AssociatedType RequiementChanges.removedType has been removed"
210+
},
211+
{
212+
"identifier": "removedDecl",
213+
"text": "cake: Var RequiementChanges.removedVar has been removed"
214+
},
215+
{
216+
"identifier": "removedDecl",
217+
"text": "cake: Func Int.IntEnhancer() has been removed"
218+
}
219+
]
220+
}

0 commit comments

Comments
 (0)