Skip to content

Commit 84d0a6f

Browse files
author
Nathan Hawes
authored
Merge pull request #23106 from nathawes/cherry-pick-sourcekit-parseable-interface-fixes
[5.1][ParseableInterface][sourcekitd] Cherry-pick SourceKit parseable interface fixes
2 parents 9e90b5e + 58a8c9a commit 84d0a6f

File tree

9 files changed

+212
-1
lines changed

9 files changed

+212
-1
lines changed

lib/Frontend/ParseableInterfaceSupport.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "clang/Basic/Module.h"
2929
#include "clang/Frontend/CompilerInstance.h"
3030
#include "clang/Lex/Preprocessor.h"
31+
#include "clang/Lex/PreprocessorOptions.h"
3132
#include "clang/Lex/HeaderSearch.h"
3233
#include "llvm/ADT/Hashing.h"
3334
#include "llvm/ADT/StringSet.h"
@@ -169,6 +170,16 @@ createInvocationForBuildingFromInterface(ASTContext &Ctx, StringRef ModuleName,
169170
SubInvocation.setClangModuleCachePath(CacheDir);
170171
SubInvocation.getFrontendOptions().PrebuiltModuleCachePath = PrebuiltCacheDir;
171172

173+
// Respect the detailed-record preprocessor setting of the parent context.
174+
// This, and the "raw" clang module format it implicitly enables, are required
175+
// by sourcekitd.
176+
if (auto *ClangLoader = Ctx.getClangModuleLoader()) {
177+
auto &Opts = ClangLoader->getClangInstance().getPreprocessorOpts();
178+
if (Opts.DetailedRecord) {
179+
SubInvocation.getClangImporterOptions().DetailedPreprocessingRecord = true;
180+
}
181+
}
182+
172183
// Inhibit warnings from the SubInvocation since we are assuming the user
173184
// is not in a position to fix them.
174185
SubInvocation.getDiagnosticOptions().SuppressWarnings = true;
@@ -452,7 +463,7 @@ bool ParseableInterfaceModuleLoader::buildSwiftModuleFromSwiftInterface(
452463
return;
453464
}
454465

455-
SubError = Diags.hadAnyError();
466+
SubError = SubInstance.getDiags().hadAnyError();
456467
});
457468
return !RunSuccess || SubError;
458469
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/modulecache)
3+
//
4+
// Setup builds a parseable interface for a module SomeModule (built from some-module.swift).
5+
// This test checks we still build and load its corresponding .swiftmodule when the file that imports it contains an error prior to the import statement.
6+
7+
// Setup phase 1: Write the input file.
8+
//
9+
// RUN: echo 'public func SomeFunc() -> Int { return 42; }' >>%t/some-module.swift
10+
11+
// Setup phase 2: build the module.
12+
//
13+
// RUN: %target-swift-frontend -I %t -emit-parseable-module-interface-path %t/SomeModule.swiftinterface -module-name SomeModule %t/some-module.swift -emit-module -o /dev/null
14+
15+
// Actual test: compile and verify the import succeeds (i.e. we only report the error in this file)
16+
//
17+
// RUN: %target-swift-frontend -typecheck -verify -I %t -module-cache-path %t/modulecache -enable-parseable-module-interface %s
18+
19+
unresolved // expected-error {{use of unresolved identifier 'unresolved'}}
20+
21+
import SomeModule
22+
23+
print(SomeFunc())
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
public struct MyPoint {
2+
public let x: Double
3+
public let y: Double
4+
5+
public init(x: Double, y: Double) {
6+
self.x = x
7+
self.y = y
8+
}
9+
10+
public var magnitudeSquared: Double {
11+
return x*x + y*y
12+
}
13+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import MyPoint
2+
3+
public extension MyPoint {
4+
var magnitude: Double {
5+
return magnitudeSquared.squareRoot()
6+
}
7+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/modulecache)
3+
4+
// 1) Build .swiftinterface files for MyPoint and MyExtensions, using a non-default module cache path
5+
// RUN: %target-swift-frontend -emit-parseable-module-interface-path %t/MyPoint.swiftinterface -module-name MyPoint -emit-module -o /dev/null %S/Inputs/parseable-interface/MyPoint.swift
6+
// RUN: %target-swift-frontend -emit-parseable-module-interface-path %t/MyPointExtensions.swiftinterface -module-name MyPointExtensions -emit-module -o /dev/null -enable-parseable-module-interface -module-cache-path %t/modulecache -I %t %S/Inputs/parseable-interface/MyPointExtensions.swift
7+
// RUN: %empty-directory(%t/modulecache)
8+
9+
// 2) Check completion using the default (cold) module cache
10+
// RUN: %target-swift-ide-test -code-completion -code-completion-token=MEMBER -source-filename %s -I %t | %FileCheck %s
11+
12+
// 3) Check completion again with a warm module cache
13+
// RUN: %target-swift-ide-test -code-completion -code-completion-token=MEMBER -source-filename %s -I %t | %FileCheck %s
14+
15+
import MyPoint
16+
import MyPointExtensions
17+
18+
let x = MyPoint(x: 1, y: 10.5)
19+
20+
print(x.#^MEMBER^#)
21+
22+
// CHECK: Begin completions, 5 items
23+
// CHECK: Keyword[self]/CurrNominal: self[#MyPoint#]; name=self
24+
// CHECK: Decl[InstanceVar]/CurrNominal: x[#Double#]; name=x
25+
// CHECK: Decl[InstanceVar]/CurrNominal: y[#Double#]; name=y
26+
// CHECK: Decl[InstanceVar]/CurrNominal: magnitudeSquared[#Double#]; name=magnitudeSquared
27+
// CHECK: Decl[InstanceVar]/CurrNominal: magnitude[#Double#]; name=magnitude
28+
// CHECK: End completions

test/SourceKit/InterfaceGen/gen_swift_module.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,11 @@ func f(s : inout [Int]) {
2424
// RUN: %sourcekitd-test -req=interface-gen-open -module Swift \
2525
// RUN: == -req=find-usr -usr "s:SMsSkRzSL7ElementSTRpzrlE4sortyyF::SYNTHESIZED::s:Sa::SYNTHESIZED::USRDOESNOTEXIST" | %FileCheck -check-prefix=SYNTHESIZED-USR3 %s
2626
// SYNTHESIZED-USR3-NOT: USR NOT FOUND
27+
28+
29+
// Test we can generate the interface of a module loaded via a .swiftinterface file correctly
30+
31+
// RUN: %empty-directory(%t.mod)
32+
// RUN: %swift -emit-module -o /dev/null -emit-parseable-module-interface-path %t.mod/swift_mod.swiftinterface %S/Inputs/swift_mod.swift -parse-as-library
33+
// RUN: %sourcekitd-test -req=interface-gen -module swift_mod -- -I %t.mod -enable-parseable-module-interface -module-cache-path %t/mcp > %t.response
34+
// RUN: diff -u %s.from_swiftinterface.response %t.response
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
2+
public class MyClass {
3+
4+
public func pub_method()
5+
}
6+
7+
public func pub_function()
8+
9+
10+
[
11+
{
12+
key.kind: source.lang.swift.syntaxtype.attribute.builtin,
13+
key.offset: 1,
14+
key.length: 6
15+
},
16+
{
17+
key.kind: source.lang.swift.syntaxtype.keyword,
18+
key.offset: 8,
19+
key.length: 5
20+
},
21+
{
22+
key.kind: source.lang.swift.syntaxtype.identifier,
23+
key.offset: 14,
24+
key.length: 7
25+
},
26+
{
27+
key.kind: source.lang.swift.syntaxtype.attribute.builtin,
28+
key.offset: 29,
29+
key.length: 6
30+
},
31+
{
32+
key.kind: source.lang.swift.syntaxtype.keyword,
33+
key.offset: 36,
34+
key.length: 4
35+
},
36+
{
37+
key.kind: source.lang.swift.syntaxtype.identifier,
38+
key.offset: 41,
39+
key.length: 10
40+
},
41+
{
42+
key.kind: source.lang.swift.syntaxtype.attribute.builtin,
43+
key.offset: 57,
44+
key.length: 6
45+
},
46+
{
47+
key.kind: source.lang.swift.syntaxtype.keyword,
48+
key.offset: 64,
49+
key.length: 4
50+
},
51+
{
52+
key.kind: source.lang.swift.syntaxtype.identifier,
53+
key.offset: 69,
54+
key.length: 12
55+
}
56+
]
57+
<<NULL>>
58+
[
59+
{
60+
key.kind: source.lang.swift.decl.class,
61+
key.accessibility: source.lang.swift.accessibility.public,
62+
key.name: "MyClass",
63+
key.offset: 8,
64+
key.length: 47,
65+
key.runtime_name: "_TtC4main7MyClass",
66+
key.nameoffset: 14,
67+
key.namelength: 7,
68+
key.bodyoffset: 23,
69+
key.bodylength: 31,
70+
key.attributes: [
71+
{
72+
key.offset: 1,
73+
key.length: 6,
74+
key.attribute: source.decl.attribute.public
75+
}
76+
],
77+
key.substructure: [
78+
{
79+
key.kind: source.lang.swift.decl.function.method.instance,
80+
key.accessibility: source.lang.swift.accessibility.public,
81+
key.name: "pub_method()",
82+
key.offset: 36,
83+
key.length: 17,
84+
key.nameoffset: 41,
85+
key.namelength: 12,
86+
key.attributes: [
87+
{
88+
key.offset: 29,
89+
key.length: 6,
90+
key.attribute: source.decl.attribute.public
91+
}
92+
]
93+
}
94+
]
95+
},
96+
{
97+
key.kind: source.lang.swift.decl.function.free,
98+
key.accessibility: source.lang.swift.accessibility.public,
99+
key.name: "pub_function()",
100+
key.offset: 64,
101+
key.length: 19,
102+
key.nameoffset: 69,
103+
key.namelength: 14,
104+
key.attributes: [
105+
{
106+
key.offset: 57,
107+
key.length: 6,
108+
key.attribute: source.decl.attribute.public
109+
}
110+
]
111+
}
112+
]

tools/SourceKit/lib/SwiftLang/SwiftEditorInterfaceGen.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,7 @@ void SwiftLangSupport::editorOpenInterface(EditorConsumer &Consumer,
708708
}
709709

710710
Invocation.getClangImporterOptions().ImportForwardDeclarations = true;
711+
Invocation.getFrontendOptions().EnableParseableModuleInterface = true;
711712

712713
std::string ErrMsg;
713714
auto IFaceGenRef = SwiftInterfaceGenContext::create(Name,

tools/swift-ide-test/swift-ide-test.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,12 @@ static llvm::cl::opt<std::string>
268268
ModuleCachePath("module-cache-path", llvm::cl::desc("Clang module cache path"),
269269
llvm::cl::cat(Category));
270270

271+
static llvm::cl::opt<bool>
272+
EnableParseableModuleInterface("enable-parseable-module-interface",
273+
llvm::cl::desc("Enable loading .swiftinterface files when available"),
274+
llvm::cl::cat(Category),
275+
llvm::cl::init(true));
276+
271277
static llvm::cl::opt<std::string>
272278
PCHOutputDir("pch-output-dir",
273279
llvm::cl::desc("place autogenerated PCH files in this directory"),
@@ -3256,6 +3262,8 @@ int main(int argc, char *argv[]) {
32563262
InitInvok.getLangOptions().EffectiveLanguageVersion = actual.getValue();
32573263
}
32583264
}
3265+
InitInvok.getFrontendOptions().EnableParseableModuleInterface =
3266+
options::EnableParseableModuleInterface;
32593267
InitInvok.getClangImporterOptions().ModuleCachePath =
32603268
options::ModuleCachePath;
32613269
InitInvok.getClangImporterOptions().PrecompiledHeaderOutputDir =

0 commit comments

Comments
 (0)