Skip to content

Share implementation of local rename and related identifiers + implement NameMatcher in Swift #70008

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
698397c
[Refactoring] Expose `findLocalRenameLocs` in Refactoring.h
ahoppen Nov 13, 2023
ada3076
[SourceKit] Share implemention of local rename and related idents
ahoppen Nov 13, 2023
bc3c8fc
[SourceKit] In related identifiers, directly construct an array of ra…
ahoppen Sep 15, 2023
d095d0a
[SourceKit] Remove `newName` from `RenameLoc`
ahoppen Nov 14, 2023
d9eef8c
[SourceKit] Remove `IsNonProtocolType` parameter from rename locations
ahoppen Nov 14, 2023
b3ab9bf
[SourceKit] Remove `UnresolvedLoc.ResolveArgLocs`
ahoppen Nov 14, 2023
ba06b5c
[SourceKit] Replace `UnresolvedLoc` by `SourceLoc`
ahoppen Nov 14, 2023
8208c23
[SourceKit] Remove `ResolvedLoc.Node`
ahoppen Nov 14, 2023
5d7200a
[SourceKit] Remove the local rename refactoring action
ahoppen Nov 14, 2023
bfad46d
[SourceKit] Remove the `-syntactic-rename` option from `swift-refactor`
ahoppen Nov 14, 2023
a0313e3
[SourceKit] Merge `Renamer` and `RenameRangeDetailCollector`
ahoppen Nov 14, 2023
ec267e2
[SourceKit] Hide `RenameRangeDetailCollector` as an implementation de…
ahoppen Nov 6, 2023
8993680
[SourceKit] Return results from rename using return values instead of…
ahoppen Nov 14, 2023
33e9c30
[SourceKit] Unify boolean values in `ResolvedLoc` into a `ResolvedLoc…
ahoppen Nov 14, 2023
1047328
[SourceKit] Lowercase members of `ResolvedLoc`
ahoppen Nov 14, 2023
313055d
[build] Add CMake logic to generate a C++ briding header from `add_pu…
ahoppen Nov 15, 2023
8fd0256
[SourceKit] Use `NameMatcher` that is rewritten in Swift for syntacti…
ahoppen Nov 17, 2023
80c399c
build: disable additional pieces for the build tools phase
compnerd Nov 17, 2023
d224549
[SourceKit] Don’t use C++ to Swift interop to run `NameMatcher`
ahoppen Nov 20, 2023
330ed60
[SourceKit] Don't use C++ interop to append elements to a `ResolvedLo…
ahoppen Nov 23, 2023
fc08a24
[build] Set `CRT_USE_BUILTIN_OFFSETOF` when building with C++ interop…
ahoppen Nov 23, 2023
f408619
Address Hamish’s review comments
ahoppen Nov 27, 2023
b313982
Don’t include `SourceLoc.h` when `USED_IN_CPP_SOURCE` is not set
ahoppen Nov 27, 2023
14bc814
Don’t include `vector` in `BasicBridging.h
ahoppen Nov 28, 2023
bc5cc43
Don’t include `<vector>` in IDEBridging.h
ahoppen Nov 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions include/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ module ASTBridging {
export *
}

module IDEBridging {
header "swift/IDE/IDEBridging.h"
requires cplusplus
export *
}

module ParseBridging {
header "swift/Parse/ParseBridging.h"
requires cplusplus
Expand Down
40 changes: 40 additions & 0 deletions include/swift/Basic/BasicBridging.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "swift/Basic/SourceLoc.h"
#include "llvm/ADT/StringRef.h"
#include <string>
#include <vector>
#endif

// FIXME: We ought to be importing '<swift/bridging>' instead.
Expand Down Expand Up @@ -303,6 +304,10 @@ class BridgedSourceRange {
#endif
};

//===----------------------------------------------------------------------===//
// MARK: BridgedCharSourceRange
//===----------------------------------------------------------------------===//

class BridgedCharSourceRange {
public:
SWIFT_UNAVAILABLE("Use '.start' instead")
Expand Down Expand Up @@ -337,6 +342,41 @@ BridgedCharSourceRange_byteLength(BridgedCharSourceRange range) {
return static_cast<SwiftInt>(range.ByteLength);
}

//===----------------------------------------------------------------------===//
// MARK: std::vector<BridgedCharSourceRange>
//===----------------------------------------------------------------------===//

/// An opaque, heap-allocated `std::vector<CharSourceRange>`.
///
/// This type is manually memory managed. The creator of the object needs to
/// ensure that `takeUnbridged` is called to free the memory.
class BridgedCharSourceRangeVector {
/// Opaque pointer to `std::vector<CharSourceRange>`.
void *_Nonnull vector;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 thanks!


public:
BridgedCharSourceRangeVector();

SWIFT_NAME("append(_:)")
void push_back(BridgedCharSourceRange range);

#ifdef USED_IN_CPP_SOURCE
/// Returns the `std::vector<swift::CharSourceRange>` that this
/// `BridgedCharSourceRangeVector` represents and frees the memory owned by
/// this `BridgedCharSourceRangeVector`.
///
/// No operations should be called on `BridgedCharSourceRangeVector` after
/// `takeUnbridged` is called.
std::vector<swift::CharSourceRange> takeUnbridged() {
auto *vectorPtr =
static_cast<std::vector<swift::CharSourceRange> *>(vector);
std::vector<swift::CharSourceRange> unbridged = *vectorPtr;
delete vectorPtr;
return unbridged;
}
#endif
};

//===----------------------------------------------------------------------===//
// MARK: Plugins
//===----------------------------------------------------------------------===//
Expand Down
163 changes: 163 additions & 0 deletions include/swift/IDE/IDEBridging.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2022 - 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_IDE_IDEBRIDGING
#define SWIFT_IDE_IDEBRIDGING

#include "swift/Basic/BasicBridging.h"

#ifdef USED_IN_CPP_SOURCE
#include "swift/Basic/SourceLoc.h"
#include "llvm/ADT/Optional.h"
#include "llvm/CAS/CASReference.h"
#include <vector>
#endif

enum class LabelRangeType {
None,

/// `foo([a: ]2) or .foo([a: ]String)`
CallArg,

/// `func([a b]: Int)`
Param,

/// `subscript([a a]: Int)`
NoncollapsibleParam,

/// `#selector(foo.func([a]:))`
Selector,
};

enum class ResolvedLocContext { Default, Selector, Comment, StringLiteral };

#ifdef USED_IN_CPP_SOURCE
struct ResolvedLoc {
/// The range of the call's base name.
swift::CharSourceRange range;

// FIXME: (NameMatcher) We should agree on whether `labelRanges` contains the
// colon or not
/// The range of the labels.
///
/// What the label range contains depends on the `labelRangeType`:
/// - Labels of calls span from the label name (excluding trivia) to the end
/// of the colon's trivia.
/// - Declaration labels contain the first name and the second name, excluding
/// the trivia on their sides
/// - For function arguments that don't have a label, this is an empty range
/// that points to the start of the argument (exculding trivia).
std::vector<swift::CharSourceRange> labelRanges;

/// The in index in `labelRanges` that belongs to the first trailing closure
/// or `llvm::None` if there is no trailing closure.
llvm::Optional<unsigned> firstTrailingLabel;

LabelRangeType labelType;

/// Whether the location is in an active `#if` region or not.
bool isActive;

ResolvedLocContext context;

ResolvedLoc(swift::CharSourceRange range,
std::vector<swift::CharSourceRange> labelRanges,
llvm::Optional<unsigned> firstTrailingLabel,
LabelRangeType labelType, bool isActive,
ResolvedLocContext context);

ResolvedLoc();
};

#endif // USED_IN_CPP_SOURCE

/// An opaque, heap-allocated `ResolvedLoc`.
///
/// This type is manually memory managed. The creator of the object needs to
/// ensure that `takeUnbridged` is called to free the memory.
struct BridgedResolvedLoc {
/// Opaque pointer to `ResolvedLoc`.
void *resolvedLoc;

/// This consumes `labelRanges` by calling `takeUnbridged` on it.
SWIFT_NAME(
"init(range:labelRanges:firstTrailingLabel:labelType:isActive:context:)")
BridgedResolvedLoc(BridgedCharSourceRange range,
BridgedCharSourceRangeVector labelRanges,
unsigned firstTrailingLabel, LabelRangeType labelType,
bool isActive, ResolvedLocContext context);

#ifdef USED_IN_CPP_SOURCE
ResolvedLoc takeUnbridged() {
ResolvedLoc *resolvedLocPtr = static_cast<ResolvedLoc *>(resolvedLoc);
ResolvedLoc unbridged = *resolvedLocPtr;
delete resolvedLocPtr;
return unbridged;
}
#endif
};

/// A heap-allocated `std::vector<ResoledLoc>` that can be represented by an
/// opaque pointer value.
///
/// This type is manually memory managed. The creator of the object needs to
/// ensure that `takeUnbridged` is called to free the memory.
class BridgedResolvedLocVector {
/// Opaque pointer to `std::vector<ResolvedLoc>`
void *vector;

public:
BridgedResolvedLocVector();

/// Create a `BridgedResolvedLocVector` from an opaque value obtained from
/// `getOpaqueValue`.
BridgedResolvedLocVector(void *opaqueValue);

/// This consumes `Loc`, calling `takeUnbridged` on it.
SWIFT_NAME("append(_:)")
void push_back(BridgedResolvedLoc Loc);

#ifdef USED_IN_CPP_SOURCE
std::vector<ResolvedLoc> takeUnbridged() {
std::vector<ResolvedLoc> *vectorPtr =
static_cast<std::vector<ResolvedLoc> *>(vector);
std::vector<ResolvedLoc> unbridged = *vectorPtr;
delete vectorPtr;
return unbridged;
}
#endif

SWIFT_IMPORT_UNSAFE
void *getOpaqueValue() const;
};

#ifdef __cplusplus
extern "C" {
#endif

/// Entry point to run the NameMatcher written in swift-syntax.
///
/// - Parameters:
/// - sourceFilePtr: A pointer to an `ExportedSourceFile`, used to access the
/// syntax tree
/// - locations: Pointer to a buffer of `BridgedSourceLoc` that should be
/// resolved by the name matcher.
/// - locationsCount: Number of elements in `locations`.
/// - Returns: The opaque value of a `BridgedResolvedLocVector`.
void *swift_SwiftIDEUtilsBridging_runNameMatcher(const void *sourceFilePtr,
BridgedSourceLoc *locations,
size_t locationsCount);
#ifdef __cplusplus
}
#endif

#endif
33 changes: 6 additions & 27 deletions include/swift/IDE/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/DeclNameLoc.h"
#include "swift/AST/Effects.h"
#include "swift/AST/Module.h"
#include "swift/AST/Expr.h"
#include "swift/AST/Module.h"
#include "swift/Basic/LLVM.h"
#include "swift/IDE/IDEBridging.h"
#include "swift/IDE/SourceEntityWalker.h"
#include "swift/Parse/Token.h"
#include "llvm/ADT/PointerIntPair.h"
Expand Down Expand Up @@ -300,29 +301,6 @@ struct ResolvedStmtStartCursorInfo : public ResolvedCursorInfo {

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

struct UnresolvedLoc {
SourceLoc Loc;
bool ResolveArgLocs;
};

enum class LabelRangeType {
None,
CallArg, // foo([a: ]2) or .foo([a: ]String)
Param, // func([a b]: Int)
NoncollapsibleParam, // subscript([a a]: Int)
Selector, // #selector(foo.func([a]:))
};

struct ResolvedLoc {
ASTWalker::ParentTy Node;
CharSourceRange Range;
std::vector<CharSourceRange> LabelRanges;
llvm::Optional<unsigned> FirstTrailingLabel;
LabelRangeType LabelType;
bool IsActive;
bool IsInSelector;
};

/// Used by NameMatcher to track parent CallExprs when walking a checked AST.
struct CallingParent {
Expr *ApplicableTo;
Expand All @@ -337,7 +315,7 @@ struct CallingParent {
/// whether it is within active/inactive code, or a selector or string literal).
class NameMatcher: public ASTWalker {
SourceFile &SrcFile;
std::vector<UnresolvedLoc> LocsToResolve;
std::vector<SourceLoc> LocsToResolve;
std::vector<ResolvedLoc> ResolvedLocs;
ArrayRef<Token> TokensToCheck;

Expand Down Expand Up @@ -391,8 +369,9 @@ class NameMatcher: public ASTWalker {

public:
explicit NameMatcher(SourceFile &SrcFile) : SrcFile(SrcFile) { }
std::vector<ResolvedLoc> resolve(ArrayRef<UnresolvedLoc> Locs, ArrayRef<Token> Tokens);
ResolvedLoc resolve(UnresolvedLoc Loc);
std::vector<ResolvedLoc> resolve(ArrayRef<SourceLoc> Locs,
ArrayRef<Token> Tokens);
ResolvedLoc resolve(SourceLoc Loc);
};

enum class RangeKind : int8_t {
Expand Down
Loading