Skip to content

Commit cc858ab

Browse files
authored
Merge pull request #70008 from ahoppen/ahoppen/name-matcher-in-swift
Share implementation of local rename and related identifiers + implement `NameMatcher` in Swift
2 parents 4fe3798 + bc5cc43 commit cc858ab

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1179
-1027
lines changed

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

+40
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "swift/Basic/SourceLoc.h"
3838
#include "llvm/ADT/StringRef.h"
3939
#include <string>
40+
#include <vector>
4041
#endif
4142

4243
// FIXME: We ought to be importing '<swift/bridging>' instead.
@@ -306,6 +307,10 @@ class BridgedSourceRange {
306307
#endif
307308
};
308309

310+
//===----------------------------------------------------------------------===//
311+
// MARK: BridgedCharSourceRange
312+
//===----------------------------------------------------------------------===//
313+
309314
class BridgedCharSourceRange {
310315
public:
311316
SWIFT_UNAVAILABLE("Use '.start' instead")
@@ -340,6 +345,41 @@ BridgedCharSourceRange_byteLength(BridgedCharSourceRange range) {
340345
return static_cast<SwiftInt>(range.ByteLength);
341346
}
342347

348+
//===----------------------------------------------------------------------===//
349+
// MARK: std::vector<BridgedCharSourceRange>
350+
//===----------------------------------------------------------------------===//
351+
352+
/// An opaque, heap-allocated `std::vector<CharSourceRange>`.
353+
///
354+
/// This type is manually memory managed. The creator of the object needs to
355+
/// ensure that `takeUnbridged` is called to free the memory.
356+
class BridgedCharSourceRangeVector {
357+
/// Opaque pointer to `std::vector<CharSourceRange>`.
358+
void *_Nonnull vector;
359+
360+
public:
361+
BridgedCharSourceRangeVector();
362+
363+
SWIFT_NAME("append(_:)")
364+
void push_back(BridgedCharSourceRange range);
365+
366+
#ifdef USED_IN_CPP_SOURCE
367+
/// Returns the `std::vector<swift::CharSourceRange>` that this
368+
/// `BridgedCharSourceRangeVector` represents and frees the memory owned by
369+
/// this `BridgedCharSourceRangeVector`.
370+
///
371+
/// No operations should be called on `BridgedCharSourceRangeVector` after
372+
/// `takeUnbridged` is called.
373+
std::vector<swift::CharSourceRange> takeUnbridged() {
374+
auto *vectorPtr =
375+
static_cast<std::vector<swift::CharSourceRange> *>(vector);
376+
std::vector<swift::CharSourceRange> unbridged = *vectorPtr;
377+
delete vectorPtr;
378+
return unbridged;
379+
}
380+
#endif
381+
};
382+
343383
//===----------------------------------------------------------------------===//
344384
// MARK: Plugins
345385
//===----------------------------------------------------------------------===//

include/swift/IDE/IDEBridging.h

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
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+
18+
#ifdef USED_IN_CPP_SOURCE
19+
#include "swift/Basic/SourceLoc.h"
20+
#include "llvm/ADT/Optional.h"
21+
#include "llvm/CAS/CASReference.h"
22+
#include <vector>
23+
#endif
24+
25+
enum class LabelRangeType {
26+
None,
27+
28+
/// `foo([a: ]2) or .foo([a: ]String)`
29+
CallArg,
30+
31+
/// `func([a b]: Int)`
32+
Param,
33+
34+
/// `subscript([a a]: Int)`
35+
NoncollapsibleParam,
36+
37+
/// `#selector(foo.func([a]:))`
38+
Selector,
39+
};
40+
41+
enum class ResolvedLocContext { Default, Selector, Comment, StringLiteral };
42+
43+
#ifdef USED_IN_CPP_SOURCE
44+
struct ResolvedLoc {
45+
/// The range of the call's base name.
46+
swift::CharSourceRange range;
47+
48+
// FIXME: (NameMatcher) We should agree on whether `labelRanges` contains the
49+
// colon or not
50+
/// The range of the labels.
51+
///
52+
/// What the label range contains depends on the `labelRangeType`:
53+
/// - Labels of calls span from the label name (excluding trivia) to the end
54+
/// of the colon's trivia.
55+
/// - Declaration labels contain the first name and the second name, excluding
56+
/// the trivia on their sides
57+
/// - For function arguments that don't have a label, this is an empty range
58+
/// that points to the start of the argument (exculding trivia).
59+
std::vector<swift::CharSourceRange> labelRanges;
60+
61+
/// The in index in `labelRanges` that belongs to the first trailing closure
62+
/// or `llvm::None` if there is no trailing closure.
63+
llvm::Optional<unsigned> firstTrailingLabel;
64+
65+
LabelRangeType labelType;
66+
67+
/// Whether the location is in an active `#if` region or not.
68+
bool isActive;
69+
70+
ResolvedLocContext context;
71+
72+
ResolvedLoc(swift::CharSourceRange range,
73+
std::vector<swift::CharSourceRange> labelRanges,
74+
llvm::Optional<unsigned> firstTrailingLabel,
75+
LabelRangeType labelType, bool isActive,
76+
ResolvedLocContext context);
77+
78+
ResolvedLoc();
79+
};
80+
81+
#endif // USED_IN_CPP_SOURCE
82+
83+
/// An opaque, heap-allocated `ResolvedLoc`.
84+
///
85+
/// This type is manually memory managed. The creator of the object needs to
86+
/// ensure that `takeUnbridged` is called to free the memory.
87+
struct BridgedResolvedLoc {
88+
/// Opaque pointer to `ResolvedLoc`.
89+
void *resolvedLoc;
90+
91+
/// This consumes `labelRanges` by calling `takeUnbridged` on it.
92+
SWIFT_NAME(
93+
"init(range:labelRanges:firstTrailingLabel:labelType:isActive:context:)")
94+
BridgedResolvedLoc(BridgedCharSourceRange range,
95+
BridgedCharSourceRangeVector labelRanges,
96+
unsigned firstTrailingLabel, LabelRangeType labelType,
97+
bool isActive, ResolvedLocContext context);
98+
99+
#ifdef USED_IN_CPP_SOURCE
100+
ResolvedLoc takeUnbridged() {
101+
ResolvedLoc *resolvedLocPtr = static_cast<ResolvedLoc *>(resolvedLoc);
102+
ResolvedLoc unbridged = *resolvedLocPtr;
103+
delete resolvedLocPtr;
104+
return unbridged;
105+
}
106+
#endif
107+
};
108+
109+
/// A heap-allocated `std::vector<ResoledLoc>` that can be represented by an
110+
/// opaque pointer value.
111+
///
112+
/// This type is manually memory managed. The creator of the object needs to
113+
/// ensure that `takeUnbridged` is called to free the memory.
114+
class BridgedResolvedLocVector {
115+
/// Opaque pointer to `std::vector<ResolvedLoc>`
116+
void *vector;
117+
118+
public:
119+
BridgedResolvedLocVector();
120+
121+
/// Create a `BridgedResolvedLocVector` from an opaque value obtained from
122+
/// `getOpaqueValue`.
123+
BridgedResolvedLocVector(void *opaqueValue);
124+
125+
/// This consumes `Loc`, calling `takeUnbridged` on it.
126+
SWIFT_NAME("append(_:)")
127+
void push_back(BridgedResolvedLoc Loc);
128+
129+
#ifdef USED_IN_CPP_SOURCE
130+
std::vector<ResolvedLoc> takeUnbridged() {
131+
std::vector<ResolvedLoc> *vectorPtr =
132+
static_cast<std::vector<ResolvedLoc> *>(vector);
133+
std::vector<ResolvedLoc> unbridged = *vectorPtr;
134+
delete vectorPtr;
135+
return unbridged;
136+
}
137+
#endif
138+
139+
SWIFT_IMPORT_UNSAFE
140+
void *getOpaqueValue() const;
141+
};
142+
143+
#ifdef __cplusplus
144+
extern "C" {
145+
#endif
146+
147+
/// Entry point to run the NameMatcher written in swift-syntax.
148+
///
149+
/// - Parameters:
150+
/// - sourceFilePtr: A pointer to an `ExportedSourceFile`, used to access the
151+
/// syntax tree
152+
/// - locations: Pointer to a buffer of `BridgedSourceLoc` that should be
153+
/// resolved by the name matcher.
154+
/// - locationsCount: Number of elements in `locations`.
155+
/// - Returns: The opaque value of a `BridgedResolvedLocVector`.
156+
void *swift_SwiftIDEUtilsBridging_runNameMatcher(const void *sourceFilePtr,
157+
BridgedSourceLoc *locations,
158+
size_t locationsCount);
159+
#ifdef __cplusplus
160+
}
161+
#endif
162+
163+
#endif

include/swift/IDE/Utils.h

+6-27
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,29 +301,6 @@ struct ResolvedStmtStartCursorInfo : public ResolvedCursorInfo {
300301

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

303-
struct UnresolvedLoc {
304-
SourceLoc Loc;
305-
bool ResolveArgLocs;
306-
};
307-
308-
enum class LabelRangeType {
309-
None,
310-
CallArg, // foo([a: ]2) or .foo([a: ]String)
311-
Param, // func([a b]: Int)
312-
NoncollapsibleParam, // subscript([a a]: Int)
313-
Selector, // #selector(foo.func([a]:))
314-
};
315-
316-
struct ResolvedLoc {
317-
ASTWalker::ParentTy Node;
318-
CharSourceRange Range;
319-
std::vector<CharSourceRange> LabelRanges;
320-
llvm::Optional<unsigned> FirstTrailingLabel;
321-
LabelRangeType LabelType;
322-
bool IsActive;
323-
bool IsInSelector;
324-
};
325-
326304
/// Used by NameMatcher to track parent CallExprs when walking a checked AST.
327305
struct CallingParent {
328306
Expr *ApplicableTo;
@@ -337,7 +315,7 @@ struct CallingParent {
337315
/// whether it is within active/inactive code, or a selector or string literal).
338316
class NameMatcher: public ASTWalker {
339317
SourceFile &SrcFile;
340-
std::vector<UnresolvedLoc> LocsToResolve;
318+
std::vector<SourceLoc> LocsToResolve;
341319
std::vector<ResolvedLoc> ResolvedLocs;
342320
ArrayRef<Token> TokensToCheck;
343321

@@ -391,8 +369,9 @@ class NameMatcher: public ASTWalker {
391369

392370
public:
393371
explicit NameMatcher(SourceFile &SrcFile) : SrcFile(SrcFile) { }
394-
std::vector<ResolvedLoc> resolve(ArrayRef<UnresolvedLoc> Locs, ArrayRef<Token> Tokens);
395-
ResolvedLoc resolve(UnresolvedLoc Loc);
372+
std::vector<ResolvedLoc> resolve(ArrayRef<SourceLoc> Locs,
373+
ArrayRef<Token> Tokens);
374+
ResolvedLoc resolve(SourceLoc Loc);
396375
};
397376

398377
enum class RangeKind : int8_t {

0 commit comments

Comments
 (0)