Skip to content

Commit 27f9919

Browse files
committed
also allow to configure node executable only
1 parent f4f8da7 commit 27f9919

File tree

3 files changed

+74
-6
lines changed

3 files changed

+74
-6
lines changed

lib/src/main/java/com/diffplug/spotless/npm/NodeExecutableResolver.java

+5
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,9 @@ static Optional<File> tryFindNextTo(File npmExecutable) {
4242
}
4343
return Optional.empty();
4444
}
45+
46+
public static String explainMessage() {
47+
return "Spotless was unable to find a node executable.\n" +
48+
"Either specify the node executable explicitly or make sure it can be found next to the npm executable.";
49+
}
4550
}

lib/src/main/java/com/diffplug/spotless/npm/NpmPathResolver.java

+35-6
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,45 @@ public NpmPathResolver(File explicitNpmExecutable, File explicitNodeExecutable,
3838
this.additionalNpmrcLocations = Collections.unmodifiableList(new ArrayList<>(additionalNpmrcLocations));
3939
}
4040

41+
/**
42+
* Finds the npm executable to use.
43+
* <br>
44+
* Either the explicit npm executable is returned, or - if an explicit node executable is configured - tries to find
45+
* the npm executable relative to the node executable.
46+
* Falls back to looking for npm on the user's system using {@link NpmExecutableResolver}
47+
*
48+
* @return the npm executable to use
49+
* @throws IllegalStateException if no npm executable could be found
50+
*/
4151
public File resolveNpmExecutable() {
42-
return Optional.ofNullable(this.explicitNpmExecutable)
43-
.orElseGet(() -> NpmExecutableResolver.tryFind()
44-
.orElseThrow(() -> new IllegalStateException("Can't automatically determine npm executable and none was specifically supplied!\n\n" + NpmExecutableResolver.explainMessage())));
52+
if (this.explicitNpmExecutable != null) {
53+
return this.explicitNpmExecutable;
54+
}
55+
if (this.explicitNodeExecutable != null) {
56+
File nodeExecutableCandidate = new File(this.explicitNodeExecutable.getParentFile(), NpmExecutableResolver.npmExecutableName());
57+
if (nodeExecutableCandidate.canExecute()) {
58+
return nodeExecutableCandidate;
59+
}
60+
}
61+
return NpmExecutableResolver.tryFind()
62+
.orElseThrow(() -> new IllegalStateException("Can't automatically determine npm executable and none was specifically supplied!\n\n" + NpmExecutableResolver.explainMessage()));
4563
}
4664

65+
/**
66+
* Finds the node executable to use.
67+
* <br>
68+
* Either the explicit node executable is returned, or tries to find the node executable relative to the npm executable
69+
* found by {@link #resolveNpmExecutable()}.
70+
* @return the node executable to use
71+
* @throws IllegalStateException if no node executable could be found
72+
*/
4773
public File resolveNodeExecutable() {
48-
return Optional.ofNullable(this.explicitNodeExecutable)
49-
.orElseGet(() -> NodeExecutableResolver.tryFindNextTo(resolveNpmExecutable())
50-
.orElseThrow(() -> new IllegalStateException("Can't automatically determine node executable and none was specifically supplied!\n\n" + NpmExecutableResolver.explainMessage())));
74+
if (this.explicitNodeExecutable != null) {
75+
return this.explicitNodeExecutable;
76+
}
77+
File npmExecutable = resolveNpmExecutable();
78+
return NodeExecutableResolver.tryFindNextTo(npmExecutable)
79+
.orElseThrow(() -> new IllegalStateException("Can't automatically determine node executable and none was specifically supplied!\n\n" + NodeExecutableResolver.explainMessage()));
5180
}
5281

5382
public String resolveNpmrcContent() {

plugin-gradle/src/test/java/com/diffplug/gradle/spotless/NpmTestsWithoutNpmInstallationTest.java

+34
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,38 @@ void useNpmFromNodeGradlePlugin() throws Exception {
9292
Assertions.assertThat(spotlessApply.getOutput()).contains("BUILD SUCCESSFUL");
9393
assertFile("test.ts").sameAsResource("npm/prettier/config/typescript.configfile.clean");
9494
}
95+
96+
@Test
97+
void useNpmNextToConfiguredNodePluginFromNodeGradlePlugin() throws Exception {
98+
setFile("build.gradle").toLines(
99+
"plugins {",
100+
" id 'com.diffplug.spotless'",
101+
" id 'com.github.node-gradle.node' version '3.5.1'",
102+
"}",
103+
"repositories { mavenCentral() }",
104+
"node {",
105+
" download = true",
106+
" version = '18.13.0'",
107+
" workDir = file(\"${buildDir}/nodejs\")",
108+
"}",
109+
"def prettierConfig = [:]",
110+
"prettierConfig['printWidth'] = 50",
111+
"prettierConfig['parser'] = 'typescript'",
112+
"def nodeExecExtension = System.getProperty('os.name').toLowerCase().contains('windows') ? '.exe' : ''",
113+
"spotless {",
114+
" format 'mytypescript', {",
115+
" target 'test.ts'",
116+
" prettier()",
117+
" .nodeExecutable(\"${tasks.named('nodeSetup').get().nodeDir.get()}/bin/node${nodeExecExtension}\")",
118+
" .config(prettierConfig)",
119+
" }",
120+
"}");
121+
setFile("test.ts").toResource("npm/prettier/config/typescript.dirty");
122+
// make sure node binary is there
123+
gradleRunner().withArguments("nodeSetup", "npmSetup").build();
124+
// then run spotless using that node installation
125+
final BuildResult spotlessApply = gradleRunner().withArguments("--stacktrace", "spotlessApply").build();
126+
Assertions.assertThat(spotlessApply.getOutput()).contains("BUILD SUCCESSFUL");
127+
assertFile("test.ts").sameAsResource("npm/prettier/config/typescript.configfile.clean");
128+
}
95129
}

0 commit comments

Comments
 (0)