Files
sourcekit-lsp/Tests/SourceKitLSPTests/CrossLanguageRenameTests.swift
Alex Hoppen aee36fdf6c Remove SkipUnless checks that always evaluate to true
We don’t support testing SourceKit-LSP using toolchains that don’t contain these features anymore.
2025-01-23 21:11:08 -08:00

867 lines
21 KiB
Swift
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 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
//
//===----------------------------------------------------------------------===//
import LanguageServerProtocol
import SKTestSupport
import XCTest
private let libAlibBPackageManifest = """
let package = Package(
name: "MyLibrary",
targets: [
.target(name: "LibA"),
.target(name: "LibB", dependencies: ["LibA"]),
]
)
"""
private let libAlibBCxxInteropPackageManifest = """
let package = Package(
name: "MyLibrary",
targets: [
.target(name: "LibA"),
.target(name: "LibB", dependencies: ["LibA"], swiftSettings: [.interoperabilityMode(.Cxx)]),
]
)
"""
final class CrossLanguageRenameTests: XCTestCase {
func testZeroArgCFunction() async throws {
try await assertMultiFileRename(
files: [
"LibA/include/LibA.h": """
void 1⃣cFunc();
""",
"LibA/LibA.c": """
#include "LibA.h"
void 2⃣cFunc() {}
""",
"LibB/LibB.swift": """
import LibA
public func test() {
3⃣cFunc()
}
""",
],
headerFileLanguage: .c,
newName: "dFunc",
expectedPrepareRenamePlaceholder: "cFunc",
expected: [
"LibA/include/LibA.h": """
void dFunc();
""",
"LibA/LibA.c": """
#include "LibA.h"
void dFunc() {}
""",
"LibB/LibB.swift": """
import LibA
public func test() {
dFunc()
}
""",
],
manifest: libAlibBPackageManifest
)
}
func testMultiArgCFunction() async throws {
try await assertMultiFileRename(
files: [
"LibA/include/LibA.h": """
void 1⃣cFunc(int x, int y);
""",
"LibA/LibA.c": """
#include "LibA.h"
void 2⃣cFunc(int x, int y) {}
""",
"LibB/LibB.swift": """
import LibA
public func test() {
3⃣cFunc(1, 2)
}
""",
],
headerFileLanguage: .c,
newName: "dFunc",
expectedPrepareRenamePlaceholder: "cFunc",
expected: [
"LibA/include/LibA.h": """
void dFunc(int x, int y);
""",
"LibA/LibA.c": """
#include "LibA.h"
void dFunc(int x, int y) {}
""",
"LibB/LibB.swift": """
import LibA
public func test() {
dFunc(1, 2)
}
""",
],
manifest: libAlibBPackageManifest
)
}
func testCFunctionWithSwiftNameAnnotation() async throws {
try await assertMultiFileRename(
files: [
"LibA/include/LibA.h": """
void 1⃣cFunc(int x, int y) __attribute__((swift_name("cFunc(x:y:)")));
""",
"LibA/LibA.c": """
#include "LibA.h"
void 2⃣cFunc(int x, int y) {}
""",
"LibB/LibB.swift": """
import LibA
public func test() {
3⃣cFunc(x: 1, y: 2)
}
""",
],
headerFileLanguage: .c,
newName: "dFunc",
expectedPrepareRenamePlaceholder: "cFunc",
expected: [
"LibA/include/LibA.h": """
void dFunc(int x, int y) __attribute__((swift_name("cFunc(x:y:)")));
""",
"LibA/LibA.c": """
#include "LibA.h"
void dFunc(int x, int y) {}
""",
"LibB/LibB.swift": """
import LibA
public func test() {
cFunc(x: 1, y: 2)
}
""",
],
manifest: libAlibBPackageManifest
)
}
func testZeroArgObjCSelector() async throws {
try SkipUnless.platformIsDarwin("Non-Darwin platforms don't support Objective-C")
try await assertMultiFileRename(
files: [
"LibA/include/LibA.h": """
@interface Foo
- (int)1⃣performAction;
@end
""",
"LibA/LibA.m": """
#include "LibA.h"
@implementation Foo
- (int)performAction {
return [self 2⃣performAction];
}
@end
""",
"LibB/LibB.swift": """
import LibA
public func test(foo: Foo) {
foo.3⃣performAction()
}
""",
],
headerFileLanguage: .objective_c,
newName: "performNewAction",
expectedPrepareRenamePlaceholder: "performAction",
expected: [
"LibA/include/LibA.h": """
@interface Foo
- (int)performNewAction;
@end
""",
"LibA/LibA.m": """
#include "LibA.h"
@implementation Foo
- (int)performNewAction {
return [self performNewAction];
}
@end
""",
"LibB/LibB.swift": """
import LibA
public func test(foo: Foo) {
foo.performNewAction()
}
""",
],
manifest: libAlibBPackageManifest
)
}
func testZeroArgObjCClassSelector() async throws {
try SkipUnless.platformIsDarwin("Non-Darwin platforms don't support Objective-C")
try await assertMultiFileRename(
files: [
"LibA/include/LibA.h": """
@interface Foo
+ (int)1⃣performAction;
@end
""",
"LibA/LibA.m": """
#include "LibA.h"
@implementation Foo
+ (int)performAction {
return [Foo 2⃣performAction];
}
@end
""",
"LibB/LibB.swift": """
import LibA
public func test() {
Foo.3⃣performAction()
}
""",
],
headerFileLanguage: .objective_c,
newName: "performNewAction",
expectedPrepareRenamePlaceholder: "performAction",
expected: [
"LibA/include/LibA.h": """
@interface Foo
+ (int)performNewAction;
@end
""",
"LibA/LibA.m": """
#include "LibA.h"
@implementation Foo
+ (int)performNewAction {
return [Foo performNewAction];
}
@end
""",
"LibB/LibB.swift": """
import LibA
public func test() {
Foo.performNewAction()
}
""",
],
manifest: libAlibBPackageManifest
)
}
func testOneArgObjCSelector() async throws {
try SkipUnless.platformIsDarwin("Non-Darwin platforms don't support Objective-C")
try await assertMultiFileRename(
files: [
"LibA/include/LibA.h": """
@interface Foo
- (int)1⃣performAction:(int)action;
@end
""",
"LibA/LibA.m": """
#include "LibA.h"
@implementation Foo
- (int)2⃣performAction:(int)action {
return [self performAction:action];
}
@end
""",
"LibB/LibB.swift": """
import LibA
public func test(foo: Foo) {
foo.3⃣performAction(1)
}
""",
],
headerFileLanguage: .objective_c,
newName: "performNewAction:",
expectedPrepareRenamePlaceholder: "performAction:",
expected: [
"LibA/include/LibA.h": """
@interface Foo
- (int)performNewAction:(int)action;
@end
""",
"LibA/LibA.m": """
#include "LibA.h"
@implementation Foo
- (int)performNewAction:(int)action {
return [self performNewAction:action];
}
@end
""",
"LibB/LibB.swift": """
import LibA
public func test(foo: Foo) {
foo.performNewAction(1)
}
""",
],
manifest: libAlibBPackageManifest
)
}
func testMultiArgObjCSelector() async throws {
try SkipUnless.platformIsDarwin("Non-Darwin platforms don't support Objective-C")
try await assertMultiFileRename(
files: [
"LibA/include/LibA.h": """
@interface Foo
- (int)1⃣performAction:(int)action with:(int)value;
@end
""",
"LibA/LibA.m": """
#include "LibA.h"
@implementation Foo
- (int)2⃣performAction:(int)action with:(int)value {
return [self performAction:action with:value];
}
@end
""",
"LibB/LibB.swift": """
import LibA
public func test(foo: Foo) {
foo.3⃣performAction(1, with: 2)
}
""",
],
headerFileLanguage: .objective_c,
newName: "performNewAction:by:",
expectedPrepareRenamePlaceholder: "performAction:with:",
expected: [
"LibA/include/LibA.h": """
@interface Foo
- (int)performNewAction:(int)action by:(int)value;
@end
""",
"LibA/LibA.m": """
#include "LibA.h"
@implementation Foo
- (int)performNewAction:(int)action by:(int)value {
return [self performNewAction:action by:value];
}
@end
""",
"LibB/LibB.swift": """
import LibA
public func test(foo: Foo) {
foo.performNewAction(1, by: 2)
}
""",
],
manifest: libAlibBPackageManifest
)
}
func testObjCSelectorWithSwiftNameAnnotation() async throws {
try SkipUnless.platformIsDarwin("Non-Darwin platforms don't support Objective-C")
try await assertMultiFileRename(
files: [
"LibA/include/LibA.h": """
@interface Foo
- (int)1⃣performAction:(int)action withValue:(int)value __attribute__((swift_name("perform(action:with:)")));
@end
""",
"LibA/LibA.m": """
#include "LibA.h"
@implementation Foo
- (int)2⃣performAction:(int)action withValue:(int)value {
return [self performAction:action withValue:value];
}
@end
""",
"LibB/LibB.swift": """
import LibA
public func test(foo: Foo) {
foo.3⃣perform(action: 1, with: 2)
}
""",
],
headerFileLanguage: .objective_c,
newName: "performNewAction:by:",
expectedPrepareRenamePlaceholder: "performAction:withValue:",
expected: [
"LibA/include/LibA.h": """
@interface Foo
- (int)performNewAction:(int)action by:(int)value __attribute__((swift_name("perform(action:with:)")));
@end
""",
"LibA/LibA.m": """
#include "LibA.h"
@implementation Foo
- (int)performNewAction:(int)action by:(int)value {
return [self performNewAction:action by:value];
}
@end
""",
"LibB/LibB.swift": """
import LibA
public func test(foo: Foo) {
foo.perform(action: 1, with: 2)
}
""",
],
manifest: libAlibBPackageManifest
)
}
func testObjCClass() async throws {
try SkipUnless.platformIsDarwin("Non-Darwin platforms don't support Objective-C")
try await assertMultiFileRename(
files: [
"LibA/include/LibA.h": """
@interface 1⃣Foo
@end
""",
"LibA/LibA.m": """
#include "LibA.h"
@implementation 2⃣Foo
@end
""",
"LibB/LibB.swift": """
import LibA
public func test(foo: 3⃣Foo) {
}
""",
],
headerFileLanguage: .objective_c,
newName: "Bar",
expectedPrepareRenamePlaceholder: "Foo",
expected: [
"LibA/include/LibA.h": """
@interface Bar
@end
""",
"LibA/LibA.m": """
#include "LibA.h"
@implementation Bar
@end
""",
"LibB/LibB.swift": """
import LibA
public func test(foo: Bar) {
}
""",
],
manifest: libAlibBPackageManifest
)
}
func testObjCClassWithSwiftNameAnnotation() async throws {
try SkipUnless.platformIsDarwin("Non-Darwin platforms don't support Objective-C")
try await assertMultiFileRename(
files: [
"LibA/include/LibA.h": """
__attribute__((swift_name("Foo")))
@interface 1⃣AHFoo
@end
""",
"LibA/LibA.m": """
#include "LibA.h"
@implementation 2⃣AHFoo
@end
""",
"LibB/LibB.swift": """
import LibA
public func test(foo: 3⃣Foo) {
}
""",
],
headerFileLanguage: .objective_c,
newName: "AHBar",
expectedPrepareRenamePlaceholder: "AHFoo",
expected: [
"LibA/include/LibA.h": """
__attribute__((swift_name("Foo")))
@interface AHBar
@end
""",
"LibA/LibA.m": """
#include "LibA.h"
@implementation AHBar
@end
""",
"LibB/LibB.swift": """
import LibA
public func test(foo: Foo) {
}
""",
],
manifest: libAlibBPackageManifest
)
}
func testCppMethod() async throws {
try await assertMultiFileRename(
files: [
"LibA/include/LibA.h": """
struct Foo {
void 1⃣doStuff() const;
};
""",
"LibA/LibA.cpp": """
#include "LibA.h"
void Foo::2⃣doStuff() const {};
""",
"LibB/LibB.swift": """
import LibA
public func test(foo: Foo) {
foo.3⃣doStuff()
}
""",
],
headerFileLanguage: .cpp,
newName: "doCoolStuff",
expectedPrepareRenamePlaceholder: "doStuff",
expected: [
"LibA/include/LibA.h": """
struct Foo {
void doCoolStuff() const;
};
""",
"LibA/LibA.cpp": """
#include "LibA.h"
void Foo::doCoolStuff() const {};
""",
"LibB/LibB.swift": """
import LibA
public func test(foo: Foo) {
foo.doCoolStuff()
}
""",
],
manifest: """
let package = Package(
name: "MyLibrary",
targets: [
.target(name: "LibA"),
.target(name: "LibB", dependencies: ["LibA"], swiftSettings: [.unsafeFlags(["-cxx-interoperability-mode=default"])]),
]
)
"""
)
}
func testCppMethodWithSwiftName() async throws {
try await assertMultiFileRename(
files: [
"LibA/include/LibA.h": """
struct Foo {
void 1⃣doStuff(int x) const __attribute__((swift_name("do(stuff:)")));
};
""",
"LibA/LibA.cpp": """
#include "LibA.h"
void Foo::2⃣doStuff(int x) const {};
""",
"LibB/LibB.swift": """
import LibA
public func test(foo: Foo) {
foo.3⃣do(stuff: 1)
}
""",
],
headerFileLanguage: .cpp,
newName: "doCoolStuff",
expectedPrepareRenamePlaceholder: "doStuff",
expected: [
"LibA/include/LibA.h": """
struct Foo {
void doCoolStuff(int x) const __attribute__((swift_name("do(stuff:)")));
};
""",
"LibA/LibA.cpp": """
#include "LibA.h"
void Foo::doCoolStuff(int x) const {};
""",
"LibB/LibB.swift": """
import LibA
public func test(foo: Foo) {
foo.do(stuff: 1)
}
""",
],
manifest: """
let package = Package(
name: "MyLibrary",
targets: [
.target(name: "LibA"),
.target(name: "LibB", dependencies: ["LibA"], swiftSettings: [.unsafeFlags(["-cxx-interoperability-mode=default"])]),
]
)
"""
)
}
func testCppMethodInObjCpp() async throws {
try await assertMultiFileRename(
files: [
"LibA/include/LibA.h": """
struct Foo {
void 1⃣doStuff() const;
};
""",
"LibA/LibA.mm": """
#include "LibA.h"
void Foo::2⃣doStuff() const {};
""",
"LibB/LibB.swift": """
import LibA
public func test(foo: Foo) {
foo.3⃣doStuff()
}
""",
],
headerFileLanguage: .objective_cpp,
newName: "doCoolStuff",
expectedPrepareRenamePlaceholder: "doStuff",
expected: [
"LibA/include/LibA.h": """
struct Foo {
void doCoolStuff() const;
};
""",
"LibA/LibA.mm": """
#include "LibA.h"
void Foo::doCoolStuff() const {};
""",
"LibB/LibB.swift": """
import LibA
public func test(foo: Foo) {
foo.doCoolStuff()
}
""",
],
manifest: """
let package = Package(
name: "MyLibrary",
targets: [
.target(name: "LibA"),
.target(name: "LibB", dependencies: ["LibA"], swiftSettings: [.unsafeFlags(["-cxx-interoperability-mode=default"])]),
]
)
"""
)
}
func testZeroArgObjCClassSelectorInObjCpp() async throws {
try SkipUnless.platformIsDarwin("Non-Darwin platforms don't support Objective-C")
try await assertMultiFileRename(
files: [
"LibA/include/LibA.h": """
@interface Foo
+ (int)1⃣performAction;
@end
""",
"LibA/LibA.mm": """
#include "LibA.h"
@implementation Foo
+ (int)performAction {
return [Foo 2⃣performAction];
}
@end
""",
"LibB/LibB.swift": """
import LibA
public func test() {
Foo.3⃣performAction()
}
""",
],
headerFileLanguage: .objective_cpp,
newName: "performNewAction",
expectedPrepareRenamePlaceholder: "performAction",
expected: [
"LibA/include/LibA.h": """
@interface Foo
+ (int)performNewAction;
@end
""",
"LibA/LibA.mm": """
#include "LibA.h"
@implementation Foo
+ (int)performNewAction {
return [Foo performNewAction];
}
@end
""",
"LibB/LibB.swift": """
import LibA
public func test() {
Foo.performNewAction()
}
""",
],
manifest: libAlibBPackageManifest
)
}
func testRenameCxxClassExposedToSwift() async throws {
try await assertMultiFileRename(
files: [
"LibA/include/LibA.h": """
struct 1⃣Foo {};
""",
"LibA/LibA.cpp": "",
"LibB/LibB.swift": """
import LibA
func test(foo: 2⃣Foo) {}
""",
],
headerFileLanguage: .cpp,
newName: "Bar",
expectedPrepareRenamePlaceholder: "Foo",
expected: [
"LibA/include/LibA.h": """
struct Bar {};
""",
"LibA/LibA.cpp": "",
"LibB/LibB.swift": """
import LibA
func test(foo: Bar) {}
""",
],
manifest: libAlibBCxxInteropPackageManifest
)
}
func testRenameCxxMethodExposedToSwift() async throws {
try await assertMultiFileRename(
files: [
"LibA/include/LibA.h": """
struct Foo {
int 1⃣doStuff() const;
};
""",
"LibA/LibA.cpp": """
#include "LibA.h"
int Foo::2⃣doStuff() const {
return 42;
}
""",
"LibB/LibB.swift": """
import LibA
func test(foo: Foo) {
foo.3⃣doStuff()
}
""",
],
headerFileLanguage: .cpp,
newName: "doNewStuff",
expectedPrepareRenamePlaceholder: "doStuff",
expected: [
"LibA/include/LibA.h": """
struct Foo {
int doNewStuff() const;
};
""",
"LibA/LibA.cpp": """
#include "LibA.h"
int Foo::doNewStuff() const {
return 42;
}
""",
"LibB/LibB.swift": """
import LibA
func test(foo: Foo) {
foo.doNewStuff()
}
""",
],
manifest: libAlibBCxxInteropPackageManifest
)
}
func testRenameSwiftMethodExposedToSwift() async throws {
try await assertMultiFileRename(
files: [
"LibA/include/LibA.h": """
struct Foo {
int 1⃣doStuff() const;
};
""",
"LibA/LibA.cpp": """
#include "LibA.h"
int Foo::2⃣doStuff() const {
return 42;
}
""",
"LibB/LibB.swift": """
import LibA
func test(foo: Foo) {
foo.3⃣doStuff()
}
""",
],
headerFileLanguage: .cpp,
newName: "doNewStuff",
expectedPrepareRenamePlaceholder: "doStuff",
expected: [
"LibA/include/LibA.h": """
struct Foo {
int doNewStuff() const;
};
""",
"LibA/LibA.cpp": """
#include "LibA.h"
int Foo::doNewStuff() const {
return 42;
}
""",
"LibB/LibB.swift": """
import LibA
func test(foo: Foo) {
foo.doNewStuff()
}
""",
],
manifest: libAlibBCxxInteropPackageManifest
)
}
}