@@ -1943,6 +1943,144 @@ TEST(CrossFileRenameTests, WithUpToDateIndex) {
1943
1943
}
1944
1944
}
1945
1945
1946
+ TEST (CrossFileRenameTests, ObjC) {
1947
+ MockCompilationDatabase CDB;
1948
+ CDB.ExtraClangFlags = {" -xobjective-c" };
1949
+ // rename is runnning on all "^" points in FooH.
1950
+ struct Case {
1951
+ llvm::StringRef FooH;
1952
+ llvm::StringRef FooM;
1953
+ llvm::StringRef NewName;
1954
+ llvm::StringRef ExpectedFooH;
1955
+ llvm::StringRef ExpectedFooM;
1956
+ };
1957
+ Case Cases[] = {// --- Zero arg selector
1958
+ {
1959
+ // Input
1960
+ R"cpp(
1961
+ @interface Foo
1962
+ - (int)performA^ction;
1963
+ @end
1964
+ )cpp" ,
1965
+ R"cpp(
1966
+ @implementation Foo
1967
+ - (int)performAction {
1968
+ [self performAction];
1969
+ }
1970
+ @end
1971
+ )cpp" ,
1972
+ // New name
1973
+ " performNewAction" ,
1974
+ // Expected
1975
+ R"cpp(
1976
+ @interface Foo
1977
+ - (int)performNewAction;
1978
+ @end
1979
+ )cpp" ,
1980
+ R"cpp(
1981
+ @implementation Foo
1982
+ - (int)performNewAction {
1983
+ [self performNewAction];
1984
+ }
1985
+ @end
1986
+ )cpp" ,
1987
+ },
1988
+ // --- Single arg selector
1989
+ {
1990
+ // Input
1991
+ R"cpp(
1992
+ @interface Foo
1993
+ - (int)performA^ction:(int)action;
1994
+ @end
1995
+ )cpp" ,
1996
+ R"cpp(
1997
+ @implementation Foo
1998
+ - (int)performAction:(int)action {
1999
+ [self performAction:action];
2000
+ }
2001
+ @end
2002
+ )cpp" ,
2003
+ // New name
2004
+ " performNewAction:" ,
2005
+ // Expected
2006
+ R"cpp(
2007
+ @interface Foo
2008
+ - (int)performNewAction:(int)action;
2009
+ @end
2010
+ )cpp" ,
2011
+ R"cpp(
2012
+ @implementation Foo
2013
+ - (int)performNewAction:(int)action {
2014
+ [self performNewAction:action];
2015
+ }
2016
+ @end
2017
+ )cpp" ,
2018
+ },
2019
+ // --- Multi arg selector
2020
+ {
2021
+ // Input
2022
+ R"cpp(
2023
+ @interface Foo
2024
+ - (int)performA^ction:(int)action with:(int)value;
2025
+ @end
2026
+ )cpp" ,
2027
+ R"cpp(
2028
+ @implementation Foo
2029
+ - (int)performAction:(int)action with:(int)value {
2030
+ [self performAction:action with:value];
2031
+ }
2032
+ @end
2033
+ )cpp" ,
2034
+ // New name
2035
+ " performNewAction:by:" ,
2036
+ // Expected
2037
+ R"cpp(
2038
+ @interface Foo
2039
+ - (int)performNewAction:(int)action by:(int)value;
2040
+ @end
2041
+ )cpp" ,
2042
+ R"cpp(
2043
+ @implementation Foo
2044
+ - (int)performNewAction:(int)action by:(int)value {
2045
+ [self performNewAction:action by:value];
2046
+ }
2047
+ @end
2048
+ )cpp" ,
2049
+ }};
2050
+
2051
+ trace::TestTracer Tracer;
2052
+ for (const auto &T : Cases) {
2053
+ SCOPED_TRACE (T.FooH );
2054
+ Annotations FooH (T.FooH );
2055
+ Annotations FooM (T.FooM );
2056
+ std::string FooHPath = testPath (" foo.h" );
2057
+ std::string FooMPath = testPath (" foo.m" );
2058
+
2059
+ MockFS FS;
2060
+ FS.Files [FooHPath] = std::string (FooH.code ());
2061
+ FS.Files [FooMPath] = std::string (FooM.code ());
2062
+
2063
+ auto ServerOpts = ClangdServer::optsForTest ();
2064
+ ServerOpts.BuildDynamicSymbolIndex = true ;
2065
+ ClangdServer Server (CDB, FS, ServerOpts);
2066
+
2067
+ // Add all files to clangd server to make sure the dynamic index has been
2068
+ // built.
2069
+ runAddDocument (Server, FooHPath, FooH.code ());
2070
+ runAddDocument (Server, FooMPath, FooM.code ());
2071
+
2072
+ for (const auto &RenamePos : FooH.points ()) {
2073
+ EXPECT_THAT (Tracer.takeMetric (" rename_files" ), SizeIs (0 ));
2074
+ auto FileEditsList =
2075
+ llvm::cantFail (runRename (Server, FooHPath, RenamePos, T.NewName , {}));
2076
+ EXPECT_THAT (Tracer.takeMetric (" rename_files" ), ElementsAre (2 ));
2077
+ EXPECT_THAT (applyEdits (std::move (FileEditsList.GlobalChanges )),
2078
+ UnorderedElementsAre (Pair (Eq (FooHPath), Eq (T.ExpectedFooH )),
2079
+ Pair (Eq (FooMPath), Eq (T.ExpectedFooM ))));
2080
+ }
2081
+ }
2082
+ }
2083
+
1946
2084
TEST (CrossFileRenameTests, CrossFileOnLocalSymbol) {
1947
2085
// cross-file rename should work for function-local symbols, even there is no
1948
2086
// index provided.
0 commit comments