Skip to content

Commit 8fd0256

Browse files
committed
[SourceKit] Use NameMatcher that is rewritten in Swift for syntactic rename
1 parent 313055d commit 8fd0256

24 files changed

+449
-53
lines changed

cmake/modules/AddPureSwift.cmake

+11-6
Original file line numberDiff line numberDiff line change
@@ -237,16 +237,21 @@ function(add_pure_swift_host_library name)
237237
endif()
238238

239239
if(APSHL_GENERATE_CXX_BRIDGING_HEADER)
240-
set(bridging_header_dir "${CMAKE_CURRENT_BINARY_DIR}/include/swift/ASTGen")
240+
set(bridging_header_dir "${CMAKE_BINARY_DIR}/include/swift/ASTGen")
241241
set(bridging_header_path "${bridging_header_dir}/${name}-Swift.h")
242242
file(MAKE_DIRECTORY ${bridging_header_dir})
243243
target_compile_options(${name} PRIVATE
244-
"SHELL: -Xfrontend -emit-clang-header-path -Xfrontend ${bridging_header_path} -Xfrontend -clang-header-expose-decls=all-public"
244+
"SHELL: -Xfrontend -emit-clang-header-path -Xfrontend ${bridging_header_path}"
245245
)
246+
if (CMAKE_Swift_COMPILER_VERSION VERSION_LESS 5.9)
247+
# The 5.8 compiler does not expose all public declarations in the bridging header by default.
248+
target_compile_options(${name} PRIVATE
249+
"SHELL: -Xfrontend -clang-header-expose-decls=all-public"
250+
)
251+
# Explicitly link swiftCxx because it's not automatically liked by a Swift 5.8 compiler
252+
target_link_libraries(${name} PRIVATE -lswiftCxx)
253+
endif()
246254

247-
# Explicitly link swiftCxx because it's not automatically liked by a Swift 5.8 compiler
248-
target_link_libraries(${name} PRIVATE -lswiftCxx)
249-
250255
add_custom_command(
251256
TARGET ${name}
252257
POST_BUILD
@@ -256,7 +261,7 @@ function(add_pure_swift_host_library name)
256261
COMMENT "Empty command that targets can depend on so that the C++ bridging header gets generate before they are built"
257262
)
258263

259-
add_custom_target("${name}-cxx-briding-header" DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${header}")
264+
add_custom_target("${name}-cxx-briding-header" DEPENDS ${bridging_header_path})
260265
endif()
261266

262267
if(LLVM_USE_LINKER)

include/module.modulemap

+6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ module ASTBridging {
1010
export *
1111
}
1212

13+
module IDEBridging {
14+
header "swift/IDE/IDEBridging.h"
15+
requires cplusplus
16+
export *
17+
}
18+
1319
module ParseBridging {
1420
header "swift/Parse/ParseBridging.h"
1521
requires cplusplus

include/swift/Basic/BasicBridging.h

+29-3
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,16 @@
2222
//
2323
#include "swift/Basic/BridgedSwiftObject.h"
2424
#include "swift/Basic/Compiler.h"
25+
#include "swift/Basic/SourceLoc.h"
26+
// Workaround to avoid a compiler error because `cas::ObjectRef` is not defined
27+
// when including VirtualFileSystem.h
28+
#include "llvm/CAS/CASReference.h"
2529

2630
#include <stddef.h>
2731
#include <stdint.h>
32+
#include <vector>
2833
#ifdef USED_IN_CPP_SOURCE
29-
// Workaround to avoid a compiler error because `cas::ObjectRef` is not defined
30-
// when including VirtualFileSystem.h
3134
#include <cassert>
32-
#include "llvm/CAS/CASReference.h"
3335

3436
#include "swift/Basic/SourceLoc.h"
3537
#include "llvm/ADT/StringRef.h"
@@ -303,6 +305,10 @@ class BridgedSourceRange {
303305
#endif
304306
};
305307

308+
//===----------------------------------------------------------------------===//
309+
// MARK: CharSourceRange
310+
//===----------------------------------------------------------------------===//
311+
306312
class BridgedCharSourceRange {
307313
public:
308314
SWIFT_UNAVAILABLE("Use '.start' instead")
@@ -337,6 +343,26 @@ BridgedCharSourceRange_byteLength(BridgedCharSourceRange range) {
337343
return static_cast<SwiftInt>(range.ByteLength);
338344
}
339345

346+
//===----------------------------------------------------------------------===//
347+
// MARK: std::vector<CharSourceRange>
348+
//===----------------------------------------------------------------------===//
349+
350+
typedef std::vector<swift::CharSourceRange> CharSourceRangeVector;
351+
352+
/// Create an empty `std::vector<ResolvedLoc>`.
353+
///
354+
/// - Note: This can't be imported as an initializer on
355+
/// `BridgedResolvedLocVector`
356+
/// because initializers without any arguments aren't imported to Swift
357+
SWIFT_NAME("CharSourceRangeVector.empty()")
358+
CharSourceRangeVector CharSourceRangeVector_createEmpty();
359+
360+
/// Convert the `BridgedCharSourceRange` to a `CharSourceRange` and append it
361+
/// to `vector`.
362+
SWIFT_NAME("CharSourceRangeVector.push_back(self:_:)")
363+
void CharSourceRangeVector_push_back_BridgedCharSourceRange(
364+
CharSourceRangeVector &vector, BridgedCharSourceRange range);
365+
340366
//===----------------------------------------------------------------------===//
341367
// MARK: Plugins
342368
//===----------------------------------------------------------------------===//
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
// IMPORTANT: Every target that includes this header file needs to declare an
14+
// explict dependency on `swiftIDEUtilsBridging-cxx-briding-header` to make sure
15+
// that the C++ bridging header gets created before the C++ sources are
16+
// compiled.
17+
18+
#include "swift/IDE/IDEBridging.h"
19+
// Hack: The generated C++ header defines an OptionSet type (for the OptionSet
20+
// in the Swift stdlib) in the `swift` namespace. This collides with the C++
21+
// OptionSet type defined for the compiler.
22+
// Since the Swift stdlib OptionSet can't be instantiated from C++ anyway,
23+
// rename it to `SwiftOptionSet` using a `#define` to make it not collide.
24+
#define OptionSet SwiftOptionSet
25+
#include "swift/ASTGen/swiftIDEUtilsBridging-Swift.h"
26+
#undef OptionSet

include/swift/IDE/IDEBridging.h

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2022 - 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_IDE_IDEBRIDGING
14+
#define SWIFT_IDE_IDEBRIDGING
15+
16+
#include "swift/Basic/BasicBridging.h"
17+
#include "swift/Basic/SourceLoc.h"
18+
#include "llvm/ADT/Optional.h"
19+
#include "llvm/CAS/CASReference.h"
20+
#include <vector>
21+
22+
enum class LabelRangeType {
23+
None,
24+
25+
/// `foo([a: ]2) or .foo([a: ]String)`
26+
CallArg,
27+
28+
/// `func([a b]: Int)`
29+
Param,
30+
31+
/// `subscript([a a]: Int)`
32+
NoncollapsibleParam,
33+
34+
/// `#selector(foo.func([a]:))`
35+
Selector,
36+
};
37+
38+
enum class ResolvedLocContext { Default, Selector, Comment, StringLiteral };
39+
40+
struct ResolvedLoc {
41+
/// The range of the call's base name.
42+
swift::CharSourceRange range;
43+
44+
// FIXME: (NameMatcher) We should agree on whether `labelRanges` contains the
45+
// colon or not
46+
/// The range of the labels.
47+
///
48+
/// What the label range contains depends on the `labelRangeType`:
49+
/// - Labels of calls span from the label name (excluding trivia) to the end
50+
/// of the colon's trivia.
51+
/// - Declaration labels contain the first name and the second name, excluding
52+
/// the trivia on their sides
53+
/// - For function arguments that don't have a label, this is an empty range
54+
/// that points to the start of the argument (exculding trivia).
55+
std::vector<swift::CharSourceRange> labelRanges;
56+
57+
/// The in index in `labelRanges` that belongs to the first trailing closure
58+
/// or `llvm::None` if there is no trailing closure.
59+
llvm::Optional<unsigned> firstTrailingLabel;
60+
61+
LabelRangeType labelType;
62+
63+
/// Whether the location is in an active `#if` region or not.
64+
bool isActive;
65+
66+
ResolvedLocContext context;
67+
68+
SWIFT_NAME(
69+
"init(range:labelRanges:firstTrailingLabel:labelType:isActive:context:)")
70+
ResolvedLoc(BridgedCharSourceRange range, CharSourceRangeVector labelRanges,
71+
unsigned firstTrailingLabel, LabelRangeType labelType,
72+
bool isActive, ResolvedLocContext context);
73+
74+
ResolvedLoc(swift::CharSourceRange range,
75+
std::vector<swift::CharSourceRange> labelRanges,
76+
llvm::Optional<unsigned> firstTrailingLabel,
77+
LabelRangeType labelType, bool isActive,
78+
ResolvedLocContext context);
79+
80+
ResolvedLoc();
81+
};
82+
83+
typedef std::vector<ResolvedLoc> ResolvedLocVector;
84+
85+
/// Create an empty `std::vector<ResolvedLoc>`.
86+
///
87+
/// - Note: This can't be imported as an initializer on
88+
/// `BridgedResolvedLocVector`
89+
/// because initializers without any arguments aren't imported to Swift
90+
SWIFT_NAME("ResolvedLocVector.empty()")
91+
ResolvedLocVector ResolvedLocVector_createEmpty();
92+
93+
typedef std::vector<BridgedSourceLoc> SourceLocVector;
94+
95+
/// Needed so that we can manually conform `SourceLocVectorIterator` to
96+
/// `UnsafeCxxInputIterator` on the Swift side because the conformance is not
97+
/// automatically generated by C++ interop by a Swift 5.8 compiler.
98+
typedef std::vector<BridgedSourceLoc>::const_iterator SourceLocVectorIterator;
99+
100+
SWIFT_NAME("SourceLocVectorIterator.equals(_:_:)")
101+
inline bool SourceLocVectorIterator_equal(const SourceLocVectorIterator &lhs,
102+
const SourceLocVectorIterator &rhs) {
103+
return lhs == rhs;
104+
}
105+
106+
#endif

include/swift/IDE/Utils.h

+2-20
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@
1717
#include "swift/AST/ASTPrinter.h"
1818
#include "swift/AST/DeclNameLoc.h"
1919
#include "swift/AST/Effects.h"
20-
#include "swift/AST/Module.h"
2120
#include "swift/AST/Expr.h"
21+
#include "swift/AST/Module.h"
2222
#include "swift/Basic/LLVM.h"
23+
#include "swift/IDE/IDEBridging.h"
2324
#include "swift/IDE/SourceEntityWalker.h"
2425
#include "swift/Parse/Token.h"
2526
#include "llvm/ADT/PointerIntPair.h"
@@ -300,25 +301,6 @@ struct ResolvedStmtStartCursorInfo : public ResolvedCursorInfo {
300301

301302
void simple_display(llvm::raw_ostream &out, ResolvedCursorInfoPtr info);
302303

303-
enum class LabelRangeType {
304-
None,
305-
CallArg, // foo([a: ]2) or .foo([a: ]String)
306-
Param, // func([a b]: Int)
307-
NoncollapsibleParam, // subscript([a a]: Int)
308-
Selector, // #selector(foo.func([a]:))
309-
};
310-
311-
enum class ResolvedLocContext { Default, Selector, Comment, StringLiteral };
312-
313-
struct ResolvedLoc {
314-
CharSourceRange range;
315-
std::vector<CharSourceRange> labelRanges;
316-
llvm::Optional<unsigned> firstTrailingLabel;
317-
LabelRangeType labelType;
318-
bool isActive;
319-
ResolvedLocContext context;
320-
};
321-
322304
/// Used by NameMatcher to track parent CallExprs when walking a checked AST.
323305
struct CallingParent {
324306
Expr *ApplicableTo;

include/swift/SILOptimizer/OptimizerBridging.h

-9
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,6 @@
2424

2525
#include "swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h"
2626

27-
#else // USED_IN_CPP_SOURCE
28-
29-
#ifdef SWIFT_SIL_SILVALUE_H
30-
#error "should not include swift headers into bridging header"
31-
#endif
32-
#ifdef LLVM_SUPPORT_COMPILER_H
33-
#error "should not include llvm headers into bridging header"
34-
#endif
35-
3627
#endif // USED_IN_CPP_SOURCE
3728

3829
SWIFT_BEGIN_NULLABILITY_ANNOTATIONS

lib/ASTGen/CMakeLists.txt

+14-1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,19 @@ add_pure_swift_host_library(swiftASTGen STATIC
6363
${ASTGen_Swift_dependencies}
6464
)
6565

66+
add_pure_swift_host_library(swiftIDEUtilsBridging GENERATE_CXX_BRIDGING_HEADER
67+
Sources/SwiftIDEUtilsBridging/NameMatcherBridging.swift
68+
69+
DEPENDENCIES
70+
swiftAST
71+
swiftASTGen
72+
73+
SWIFT_DEPENDENCIES
74+
SwiftIDEUtils
75+
SwiftSyntax
76+
)
77+
78+
6679
set(c_include_paths
6780
# LLVM modules and headers.
6881
"${LLVM_MAIN_INCLUDE_DIR}"
@@ -99,7 +112,7 @@ set(compile_options
99112
)
100113

101114
if(SWIFT_BUILD_SWIFT_SYNTAX)
102-
foreach(target swiftASTGen swiftLLVMJSON)
115+
foreach(target swiftASTGen swiftLLVMJSON swiftIDEUtilsBridging)
103116
target_compile_options(${target} PRIVATE ${compile_options})
104117
endforeach()
105118
endif()

lib/ASTGen/Package.swift

+10
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,16 @@ let package = Package(
6969
path: "Sources/ASTGen",
7070
swiftSettings: swiftSetttings
7171
),
72+
.target(
73+
name: "swiftIDEUtilsBridging",
74+
dependencies: [
75+
"swiftASTGen",
76+
.product(name: "SwiftIDEUtils", package: "swift-syntax"),
77+
.product(name: "SwiftSyntax", package: "swift-syntax"),
78+
],
79+
path: "Sources/SwiftIDEUtilsBridging",
80+
swiftSettings: swiftSetttings
81+
),
7282
.target(
7383
name: "swiftLLVMJSON",
7484
dependencies: [],

lib/ASTGen/Sources/ASTGen/Bridge.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ extension BridgedParameterList? {
6262
}
6363
}
6464

65-
extension BridgedSourceLoc {
65+
public extension BridgedSourceLoc {
6666
/// Form a source location at the given absolute position in `buffer`.
6767
init(
6868
at position: AbsolutePosition,

lib/ASTGen/Sources/ASTGen/SourceFile.swift

+11-3
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ import SwiftSyntax
1818

1919
/// Describes a source file that has been "exported" to the C++ part of the
2020
/// compiler, with enough information to interface with the C++ layer.
21-
struct ExportedSourceFile {
21+
public struct ExportedSourceFile {
2222
/// The underlying buffer within the C++ SourceManager, which is used
2323
/// for computations of source locations.
24-
let buffer: UnsafeBufferPointer<UInt8>
24+
public let buffer: UnsafeBufferPointer<UInt8>
2525

2626
/// The name of the enclosing module.
2727
let moduleName: String
@@ -30,7 +30,15 @@ struct ExportedSourceFile {
3030
let fileName: String
3131

3232
/// The syntax tree for the complete source file.
33-
let syntax: SourceFileSyntax
33+
public let syntax: SourceFileSyntax
34+
35+
public func position(of location: BridgedSourceLoc) -> AbsolutePosition? {
36+
let sourceFileBaseAddress = UnsafeRawPointer(buffer.baseAddress!)
37+
guard let opaqueValue = location.getOpaquePointerValue() else {
38+
return nil
39+
}
40+
return AbsolutePosition(utf8Offset: opaqueValue - sourceFileBaseAddress)
41+
}
3442
}
3543

3644
extension Parser.ExperimentalFeatures {

0 commit comments

Comments
 (0)