Skip to content

Commit 4912f54

Browse files
author
Nathan Hawes
committed
[IDE][InterfaceGen] Always print the top-level decl in header file generated interface.
While the decls being printed for header file generated interfaces were mapped from the top-level clang decls in that file, the Swift decls they correspond to may not be top-level. E.g. top-level functions in the header file can be mapped to property accessors on the Swift side, which were being printed simply as "get" at the top level. This updates header interface generation to map each decl to its top-level decl before printing. Resolves rdar://problem/63409659
1 parent b981b7e commit 4912f54

File tree

4 files changed

+357
-3
lines changed

4 files changed

+357
-3
lines changed

lib/IDE/ModuleInterfacePrinting.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,16 @@ void swift::ide::printSwiftSourceInterface(SourceFile &File,
840840
File.print(Printer, Options);
841841
}
842842

843+
static Decl* getTopLevelDecl(Decl *D) {
844+
while (!D->getDeclContext()->isModuleScopeContext()) {
845+
auto *ParentD = D->getDeclContext()->getAsDecl();
846+
if (!ParentD)
847+
break;
848+
D = ParentD;
849+
}
850+
return D;
851+
}
852+
843853
void swift::ide::printHeaderInterface(
844854
StringRef Filename,
845855
ASTContext &Ctx,
@@ -858,10 +868,8 @@ void swift::ide::printHeaderInterface(
858868
SmallVector<Decl *, 32> ClangDecls;
859869
llvm::SmallPtrSet<Decl *, 32> SeenDecls;
860870
auto headerReceiver = [&](Decl *D) {
861-
if (SeenDecls.count(D) == 0) {
862-
SeenDecls.insert(D);
871+
if (SeenDecls.insert(getTopLevelDecl(D)).second)
863872
ClangDecls.push_back(D);
864-
}
865873
};
866874

867875
Importer.lookupDeclsFromHeader(Filename, headerFilter, headerReceiver);
@@ -881,6 +889,10 @@ void swift::ide::printHeaderInterface(
881889
PrinterToUse = &RegularCommentPrinter;
882890

883891
for (auto *D : ClangDecls) {
892+
// Even though the corresponding clang decl should be top-level, its
893+
// equivalent Swift decl may not be. E.g. a top-level function may be mapped
894+
// to a property accessor in Swift.
895+
D = getTopLevelDecl(D);
884896
ASTPrinter &Printer = *PrinterToUse;
885897
if (!AdjustedOptions.shouldPrint(D)) {
886898
Printer.callAvoidPrintDeclPost(D);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#define CF_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
2+
#define CF_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type
3+
#define NS_ENUM(_type, _name) CF_ENUM(_type, _name)
4+
#define NS_OPTIONS(_type, _name) CF_OPTIONS(_type, _name)
5+
#define CF_SWIFT_NAME(_name) __attribute__((swift_name(#_name)))
6+
#define NS_SWIFT_NAME(_name) CF_SWIFT_NAME(_name)
7+
8+
typedef NS_ENUM(unsigned, SKFuelKind) { SKFuelKindH2, SKFuelKindCH4, SKFuelKindC12H26 };
9+
unsigned SKFuelKindIsCryogenic(SKFuelKind kind) NS_SWIFT_NAME(getter:SKFuelKind.isCryogenic(self:));
10+
unsigned SKFuelKindIsNotCryogenic(SKFuelKind kind) NS_SWIFT_NAME(getter:SKFuelKind.isNotCryogenic(self:));

test/SourceKit/InterfaceGen/gen_header.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,7 @@
2121
// RUN: %sourcekitd-test -req=interface-gen -header %S/Inputs/header2.h -swift-version=5 -pass-version-as-string -- -fsyntax-only %t.m -I %S/Inputs > %t.header2.swift4.response
2222
// RUN: %FileCheck -input-file %t.header2.swift4.response %s -check-prefix=SWIFT4-STR
2323
// SWIFT4-STR: public func show_only_for_swift_4()
24+
25+
// RUN: echo '#include "header3.h"' > %t.m
26+
// RUN: %sourcekitd-test -req=interface-gen -header %S/Inputs/header3.h -swift-version=5 -- -fsyntax-only %t.m -I %S/Inputs > %t.header3.response
27+
// RUN: %diff -u %s.header3.response %t.header3.response
Lines changed: 328 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,328 @@
1+
2+
public enum SKFuelKind : UInt32 {
3+
4+
5+
case H2 = 0
6+
7+
case CH4 = 1
8+
9+
case C12H26 = 2
10+
}
11+
extension SKFuelKind {
12+
13+
public var isCryogenic: UInt32 { get }
14+
15+
public var isNotCryogenic: UInt32 { get }
16+
}
17+
18+
[
19+
{
20+
key.kind: source.lang.swift.syntaxtype.attribute.builtin,
21+
key.offset: 1,
22+
key.length: 6
23+
},
24+
{
25+
key.kind: source.lang.swift.syntaxtype.keyword,
26+
key.offset: 8,
27+
key.length: 4
28+
},
29+
{
30+
key.kind: source.lang.swift.syntaxtype.identifier,
31+
key.offset: 13,
32+
key.length: 10
33+
},
34+
{
35+
key.kind: source.lang.swift.syntaxtype.typeidentifier,
36+
key.offset: 26,
37+
key.length: 6
38+
},
39+
{
40+
key.kind: source.lang.swift.syntaxtype.keyword,
41+
key.offset: 45,
42+
key.length: 4
43+
},
44+
{
45+
key.kind: source.lang.swift.syntaxtype.identifier,
46+
key.offset: 50,
47+
key.length: 2
48+
},
49+
{
50+
key.kind: source.lang.swift.syntaxtype.number,
51+
key.offset: 55,
52+
key.length: 1
53+
},
54+
{
55+
key.kind: source.lang.swift.syntaxtype.keyword,
56+
key.offset: 62,
57+
key.length: 4
58+
},
59+
{
60+
key.kind: source.lang.swift.syntaxtype.identifier,
61+
key.offset: 67,
62+
key.length: 3
63+
},
64+
{
65+
key.kind: source.lang.swift.syntaxtype.number,
66+
key.offset: 73,
67+
key.length: 1
68+
},
69+
{
70+
key.kind: source.lang.swift.syntaxtype.keyword,
71+
key.offset: 80,
72+
key.length: 4
73+
},
74+
{
75+
key.kind: source.lang.swift.syntaxtype.identifier,
76+
key.offset: 85,
77+
key.length: 6
78+
},
79+
{
80+
key.kind: source.lang.swift.syntaxtype.number,
81+
key.offset: 94,
82+
key.length: 1
83+
},
84+
{
85+
key.kind: source.lang.swift.syntaxtype.keyword,
86+
key.offset: 98,
87+
key.length: 9
88+
},
89+
{
90+
key.kind: source.lang.swift.syntaxtype.typeidentifier,
91+
key.offset: 108,
92+
key.length: 10
93+
},
94+
{
95+
key.kind: source.lang.swift.syntaxtype.attribute.builtin,
96+
key.offset: 126,
97+
key.length: 6
98+
},
99+
{
100+
key.kind: source.lang.swift.syntaxtype.keyword,
101+
key.offset: 133,
102+
key.length: 3
103+
},
104+
{
105+
key.kind: source.lang.swift.syntaxtype.identifier,
106+
key.offset: 137,
107+
key.length: 11
108+
},
109+
{
110+
key.kind: source.lang.swift.syntaxtype.typeidentifier,
111+
key.offset: 150,
112+
key.length: 6
113+
},
114+
{
115+
key.kind: source.lang.swift.syntaxtype.keyword,
116+
key.offset: 159,
117+
key.length: 3
118+
},
119+
{
120+
key.kind: source.lang.swift.syntaxtype.attribute.builtin,
121+
key.offset: 170,
122+
key.length: 6
123+
},
124+
{
125+
key.kind: source.lang.swift.syntaxtype.keyword,
126+
key.offset: 177,
127+
key.length: 3
128+
},
129+
{
130+
key.kind: source.lang.swift.syntaxtype.identifier,
131+
key.offset: 181,
132+
key.length: 14
133+
},
134+
{
135+
key.kind: source.lang.swift.syntaxtype.typeidentifier,
136+
key.offset: 197,
137+
key.length: 6
138+
},
139+
{
140+
key.kind: source.lang.swift.syntaxtype.keyword,
141+
key.offset: 206,
142+
key.length: 3
143+
}
144+
]
145+
[
146+
{
147+
key.kind: source.lang.swift.ref.struct,
148+
key.offset: 26,
149+
key.length: 6,
150+
key.is_system: 1
151+
},
152+
{
153+
key.kind: source.lang.swift.ref.enum,
154+
key.offset: 108,
155+
key.length: 10
156+
},
157+
{
158+
key.kind: source.lang.swift.ref.struct,
159+
key.offset: 150,
160+
key.length: 6,
161+
key.is_system: 1
162+
},
163+
{
164+
key.kind: source.lang.swift.ref.struct,
165+
key.offset: 197,
166+
key.length: 6,
167+
key.is_system: 1
168+
}
169+
]
170+
[
171+
{
172+
key.kind: source.lang.swift.decl.enum,
173+
key.accessibility: source.lang.swift.accessibility.public,
174+
key.name: "SKFuelKind",
175+
key.offset: 8,
176+
key.length: 89,
177+
key.nameoffset: 13,
178+
key.namelength: 10,
179+
key.bodyoffset: 34,
180+
key.bodylength: 62,
181+
key.inheritedtypes: [
182+
{
183+
key.name: "UInt32"
184+
}
185+
],
186+
key.attributes: [
187+
{
188+
key.offset: 1,
189+
key.length: 6,
190+
key.attribute: source.decl.attribute.public
191+
}
192+
],
193+
key.elements: [
194+
{
195+
key.kind: source.lang.swift.structure.elem.typeref,
196+
key.offset: 26,
197+
key.length: 6
198+
}
199+
],
200+
key.substructure: [
201+
{
202+
key.kind: source.lang.swift.decl.enumcase,
203+
key.offset: 45,
204+
key.length: 11,
205+
key.nameoffset: 0,
206+
key.namelength: 0,
207+
key.substructure: [
208+
{
209+
key.kind: source.lang.swift.decl.enumelement,
210+
key.accessibility: source.lang.swift.accessibility.public,
211+
key.name: "H2",
212+
key.offset: 50,
213+
key.length: 6,
214+
key.nameoffset: 50,
215+
key.namelength: 2,
216+
key.elements: [
217+
{
218+
key.kind: source.lang.swift.structure.elem.init_expr,
219+
key.offset: 55,
220+
key.length: 1
221+
}
222+
]
223+
}
224+
]
225+
},
226+
{
227+
key.kind: source.lang.swift.decl.enumcase,
228+
key.offset: 62,
229+
key.length: 12,
230+
key.nameoffset: 0,
231+
key.namelength: 0,
232+
key.substructure: [
233+
{
234+
key.kind: source.lang.swift.decl.enumelement,
235+
key.accessibility: source.lang.swift.accessibility.public,
236+
key.name: "CH4",
237+
key.offset: 67,
238+
key.length: 7,
239+
key.nameoffset: 67,
240+
key.namelength: 3,
241+
key.elements: [
242+
{
243+
key.kind: source.lang.swift.structure.elem.init_expr,
244+
key.offset: 73,
245+
key.length: 1
246+
}
247+
]
248+
}
249+
]
250+
},
251+
{
252+
key.kind: source.lang.swift.decl.enumcase,
253+
key.offset: 80,
254+
key.length: 15,
255+
key.nameoffset: 0,
256+
key.namelength: 0,
257+
key.substructure: [
258+
{
259+
key.kind: source.lang.swift.decl.enumelement,
260+
key.accessibility: source.lang.swift.accessibility.public,
261+
key.name: "C12H26",
262+
key.offset: 85,
263+
key.length: 10,
264+
key.nameoffset: 85,
265+
key.namelength: 6,
266+
key.elements: [
267+
{
268+
key.kind: source.lang.swift.structure.elem.init_expr,
269+
key.offset: 94,
270+
key.length: 1
271+
}
272+
]
273+
}
274+
]
275+
}
276+
]
277+
},
278+
{
279+
key.kind: source.lang.swift.decl.extension,
280+
key.name: "SKFuelKind",
281+
key.offset: 98,
282+
key.length: 115,
283+
key.nameoffset: 108,
284+
key.namelength: 10,
285+
key.bodyoffset: 120,
286+
key.bodylength: 92,
287+
key.substructure: [
288+
{
289+
key.kind: source.lang.swift.decl.var.instance,
290+
key.accessibility: source.lang.swift.accessibility.public,
291+
key.name: "isCryogenic",
292+
key.offset: 133,
293+
key.length: 31,
294+
key.typename: "UInt32",
295+
key.nameoffset: 137,
296+
key.namelength: 11,
297+
key.bodyoffset: 158,
298+
key.bodylength: 5,
299+
key.attributes: [
300+
{
301+
key.offset: 126,
302+
key.length: 6,
303+
key.attribute: source.decl.attribute.public
304+
}
305+
]
306+
},
307+
{
308+
key.kind: source.lang.swift.decl.var.instance,
309+
key.accessibility: source.lang.swift.accessibility.public,
310+
key.name: "isNotCryogenic",
311+
key.offset: 177,
312+
key.length: 34,
313+
key.typename: "UInt32",
314+
key.nameoffset: 181,
315+
key.namelength: 14,
316+
key.bodyoffset: 205,
317+
key.bodylength: 5,
318+
key.attributes: [
319+
{
320+
key.offset: 170,
321+
key.length: 6,
322+
key.attribute: source.decl.attribute.public
323+
}
324+
]
325+
}
326+
]
327+
}
328+
]

0 commit comments

Comments
 (0)