Skip to content

Commit 97eb40c

Browse files
authored
Add "legacy" parameter required by Xcode 16 (#97)
* Add "legacy" parameter required by Xcode 16 * Add XcodeResultLegacyRunner to check xcoderesulttool version and add legacy flag if needed
1 parent e6b330c commit 97eb40c

File tree

10 files changed

+234
-22
lines changed

10 files changed

+234
-22
lines changed

sonar-apple-plugin/src/main/java/fr/insideapp/sonarqube/apple/XcodeResultExtensionProvider.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package fr.insideapp.sonarqube.apple;
1919

2020
import fr.insideapp.sonarqube.apple.commons.ExtensionProvider;
21+
import fr.insideapp.sonarqube.apple.xcode.legacy.XcodeResultLegacyRunner;
2122
import fr.insideapp.sonarqube.apple.xcode.runner.XcodeResultReadObjectRunner;
2223
import fr.insideapp.sonarqube.apple.xcode.parser.XcodeActionRecordParser;
2324
import fr.insideapp.sonarqube.apple.xcode.runner.XcodeResultReadRunner;
@@ -50,7 +51,8 @@ public List<Object> extensions() {
5051
RESULT_BUNDLE_PROPERTY,
5152
XcodeResultReadRunner.class,
5253
XcodeActionRecordParser.class,
53-
XcodeResultReadObjectRunner.class
54+
XcodeResultReadObjectRunner.class,
55+
XcodeResultLegacyRunner.class
5456
);
5557
}
5658

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* SonarQube Apple Plugin - Enables analysis of Swift and Objective-C projects into SonarQube.
3+
* Copyright © 2022 inside|app ([email protected])
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Lesser General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package fr.insideapp.sonarqube.apple.xcode.legacy;
19+
20+
import fr.insideapp.sonarqube.apple.commons.cli.SingleCommandLineToolRunner;
21+
import org.sonar.api.scanner.ScannerSide;
22+
23+
@ScannerSide
24+
public abstract class XcodeResultLegacyRunnable extends SingleCommandLineToolRunner {
25+
protected XcodeResultLegacyRunnable(String command) {
26+
super(command);
27+
}
28+
29+
public abstract boolean check();
30+
31+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* SonarQube Apple Plugin - Enables analysis of Swift and Objective-C projects into SonarQube.
3+
* Copyright © 2022 inside|app ([email protected])
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Lesser General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package fr.insideapp.sonarqube.apple.xcode.legacy;
19+
20+
import org.sonar.api.scanner.ScannerSide;
21+
22+
import java.util.regex.Matcher;
23+
import java.util.regex.Pattern;
24+
25+
@ScannerSide
26+
public final class XcodeResultLegacyRunner extends XcodeResultLegacyRunnable {
27+
28+
private static final Integer MIN_VERSION = 23_021;
29+
30+
private static final Pattern PATTERN = Pattern.compile("xcresulttool version (?<version>\\d+),.*");
31+
32+
public XcodeResultLegacyRunner() {
33+
super("xcrun");
34+
}
35+
36+
protected String[] arguments() {
37+
return new String[]{
38+
"xcresulttool", "version"
39+
};
40+
}
41+
42+
public boolean check() {
43+
String result = run(arguments()).trim();
44+
Matcher versionMatcher = PATTERN.matcher(result);
45+
if (versionMatcher.find()) {
46+
try {
47+
int version = Integer.parseInt(versionMatcher.group("version"));
48+
return version >= MIN_VERSION;
49+
} catch (NumberFormatException e) {
50+
return false;
51+
}
52+
} else {
53+
return false;
54+
}
55+
}
56+
57+
}

sonar-apple-plugin/src/main/java/fr/insideapp/sonarqube/apple/xcode/runner/XcodeResultReadObjectRunner.java

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,24 +18,39 @@
1818
package fr.insideapp.sonarqube.apple.xcode.runner;
1919

2020
import fr.insideapp.sonarqube.apple.commons.result.models.Reference;
21+
import fr.insideapp.sonarqube.apple.xcode.legacy.XcodeResultLegacyRunnable;
2122
import org.sonar.api.scanner.ScannerSide;
2223

2324
import java.io.File;
25+
import java.util.ArrayList;
26+
import java.util.List;
2427

2528
@ScannerSide
2629
public final class XcodeResultReadObjectRunner extends XcodeResultReadObjectRunnable {
2730

28-
public XcodeResultReadObjectRunner() {
31+
private final XcodeResultLegacyRunnable legacyRunner;
32+
33+
public XcodeResultReadObjectRunner(
34+
final XcodeResultLegacyRunnable legacyRunner
35+
) {
2936
super("xcrun");
37+
this.legacyRunner = legacyRunner;
3038
}
3139

3240
protected String[] arguments(File resultBundle, Reference reference) {
33-
return new String[]{
34-
"xcresulttool", "get",
35-
"--format", "json",
36-
"--path", resultBundle.getAbsolutePath(),
37-
"--id", reference.id
38-
};
41+
List<String> arguments = new ArrayList<>();
42+
arguments.add("xcresulttool");
43+
arguments.add("get");
44+
arguments.add("--format");
45+
arguments.add("json");
46+
arguments.add("--path");
47+
arguments.add(resultBundle.getAbsolutePath());
48+
arguments.add("--id");
49+
arguments.add(reference.id);
50+
if (legacyRunner.check()) {
51+
arguments.add("--legacy");
52+
}
53+
return arguments.toArray(String[]::new);
3954
}
4055

4156
public String run(File resultBundle, Reference reference) {

sonar-apple-plugin/src/main/java/fr/insideapp/sonarqube/apple/xcode/runner/XcodeResultReadRunner.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,36 @@
1717
*/
1818
package fr.insideapp.sonarqube.apple.xcode.runner;
1919

20+
import fr.insideapp.sonarqube.apple.xcode.legacy.XcodeResultLegacyRunnable;
2021
import org.sonar.api.scanner.ScannerSide;
2122

2223
import java.io.File;
24+
import java.util.ArrayList;
25+
import java.util.List;
2326

2427
@ScannerSide
2528
public final class XcodeResultReadRunner extends XcodeResultReadRunnable {
2629

27-
public XcodeResultReadRunner() {
30+
private final XcodeResultLegacyRunnable legacyRunner;
31+
32+
public XcodeResultReadRunner(
33+
final XcodeResultLegacyRunnable legacyRunner
34+
) {
2835
super("xcrun");
36+
this.legacyRunner = legacyRunner;
2937
}
30-
3138
protected String[] arguments(File resultBundle) {
32-
return new String[]{
33-
"xcresulttool", "get",
34-
"--format", "json",
35-
"--path", resultBundle.getAbsolutePath()
36-
};
39+
List<String> arguments = new ArrayList<>();
40+
arguments.add("xcresulttool");
41+
arguments.add("get");
42+
arguments.add("--format");
43+
arguments.add("json");
44+
arguments.add("--path");
45+
arguments.add(resultBundle.getAbsolutePath());
46+
if (legacyRunner.check()) {
47+
arguments.add("--legacy");
48+
}
49+
return arguments.toArray(String[]::new);
3750
}
3851

3952
public String run(File resultBundle) {

sonar-apple-plugin/src/test/java/fr/insideapp/sonarqube/apple/ApplePluginTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,6 @@ public void define() {
4040
plugin.define(context);
4141

4242
List<?> extensions = context.getExtensions();
43-
assertThat(extensions).hasSize(79);
43+
assertThat(extensions).hasSize(80);
4444
}
4545
}

sonar-apple-plugin/src/test/java/fr/insideapp/sonarqube/apple/XcodeResultExtensionProviderTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public void prepare() {
4444

4545
@Test
4646
public void extensions() {
47-
assertThat(provider.extensions()).hasSize(4);
47+
assertThat(provider.extensions()).hasSize(5);
4848
}
4949

5050
@Test
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* SonarQube Apple Plugin - Enables analysis of Swift and Objective-C projects into SonarQube.
3+
* Copyright © 2022 inside|app ([email protected])
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Lesser General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package fr.insideapp.sonarqube.apple.xcode.legacy;
19+
20+
import org.junit.Before;
21+
import org.junit.Test;
22+
23+
import static org.assertj.core.api.Assertions.assertThat;
24+
25+
public final class XcodeResultLegacyRunnerTest {
26+
27+
private XcodeResultLegacyRunner runner;
28+
29+
@Before
30+
public void prepare() {
31+
runner = new XcodeResultLegacyRunner();
32+
}
33+
34+
@Test
35+
public void arguments() {
36+
String[] options = runner.arguments();
37+
assertThat(options).isEqualTo(new String[]{
38+
"xcresulttool",
39+
"version",
40+
});
41+
}
42+
43+
}

sonar-apple-plugin/src/test/java/fr/insideapp/sonarqube/apple/xcode/runner/XcodeResultReadObjectRunnerTest.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,36 @@
1818
package fr.insideapp.sonarqube.apple.xcode.runner;
1919

2020
import fr.insideapp.sonarqube.apple.commons.result.models.Reference;
21+
import fr.insideapp.sonarqube.apple.xcode.legacy.XcodeResultLegacyRunnable;
2122
import org.junit.Before;
2223
import org.junit.Test;
2324

2425
import java.io.File;
2526

2627
import static org.assertj.core.api.Assertions.assertThat;
28+
import static org.mockito.Mockito.mock;
29+
import static org.mockito.Mockito.when;
2730

2831
public final class XcodeResultReadObjectRunnerTest {
2932

3033
private static final String BASE_DIR = "/xcode";
3134

35+
private XcodeResultLegacyRunnable legacy;
3236
private XcodeResultReadObjectRunner runner;
3337

3438
@Before
3539
public void prepare() {
36-
runner = new XcodeResultReadObjectRunner();
40+
legacy = mock(XcodeResultLegacyRunnable.class);
41+
runner = new XcodeResultReadObjectRunner(legacy);
3742
}
3843

3944
@Test
40-
public void arguments() {
45+
public void arguments_no_legacy() {
46+
// When
47+
when(legacy.check()).thenReturn(false);
48+
// Then
4149
String[] options = runner.arguments(new File(BASE_DIR), new Reference("test"));
50+
// Assert
4251
assertThat(options).isEqualTo(new String[]{
4352
"xcresulttool",
4453
"get",
@@ -48,4 +57,21 @@ public void arguments() {
4857
});
4958
}
5059

60+
@Test
61+
public void arguments_legacy() {
62+
// When
63+
when(legacy.check()).thenReturn(true);
64+
// Then
65+
String[] options = runner.arguments(new File(BASE_DIR), new Reference("test"));
66+
// Assert
67+
assertThat(options).isEqualTo(new String[]{
68+
"xcresulttool",
69+
"get",
70+
"--format", "json",
71+
"--path", "/xcode",
72+
"--id", "test",
73+
"--legacy"
74+
});
75+
}
76+
5177
}

sonar-apple-plugin/src/test/java/fr/insideapp/sonarqube/apple/xcode/runner/XcodeResultReadRunnerTest.java

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,32 +17,57 @@
1717
*/
1818
package fr.insideapp.sonarqube.apple.xcode.runner;
1919

20+
import fr.insideapp.sonarqube.apple.xcode.legacy.XcodeResultLegacyRunnable;
2021
import org.junit.Before;
2122
import org.junit.Test;
2223

2324
import java.io.File;
2425

2526
import static org.assertj.core.api.Assertions.assertThat;
27+
import static org.mockito.Mockito.mock;
28+
import static org.mockito.Mockito.when;
2629

2730
public final class XcodeResultReadRunnerTest {
2831

2932
private static final String BASE_DIR = "/xcode";
3033

34+
private XcodeResultLegacyRunnable legacy;
3135
private XcodeResultReadRunner runner;
3236

3337
@Before
3438
public void prepare() {
35-
runner = new XcodeResultReadRunner();
39+
legacy = mock(XcodeResultLegacyRunnable.class);
40+
runner = new XcodeResultReadRunner(legacy);
3641
}
3742

3843
@Test
39-
public void arguments() {
44+
public void arguments_no_legacy() {
45+
// When
46+
when(legacy.check()).thenReturn(false);
47+
// Then
4048
String[] options = runner.arguments(new File(BASE_DIR));
49+
// Assert
4150
assertThat(options).isEqualTo(new String[]{
4251
"xcresulttool",
4352
"get",
4453
"--format", "json",
45-
"--path", "/xcode"
54+
"--path", "/xcode",
55+
});
56+
}
57+
58+
@Test
59+
public void arguments_legacy() {
60+
// When
61+
when(legacy.check()).thenReturn(true);
62+
// Then
63+
String[] options = runner.arguments(new File(BASE_DIR));
64+
// Assert
65+
assertThat(options).isEqualTo(new String[]{
66+
"xcresulttool",
67+
"get",
68+
"--format", "json",
69+
"--path", "/xcode",
70+
"--legacy"
4671
});
4772
}
4873

0 commit comments

Comments
 (0)