diff --git a/lib/src/main/java/com/diffplug/spotless/FileSignature.java b/lib/src/main/java/com/diffplug/spotless/FileSignature.java index 10bba7a716..3d37ec2983 100644 --- a/lib/src/main/java/com/diffplug/spotless/FileSignature.java +++ b/lib/src/main/java/com/diffplug/spotless/FileSignature.java @@ -125,6 +125,10 @@ public static Promised promise(Iterable files) { return new Promised(MoreIterables.toNullHostileList(files), null); } + public static Promised promise(File file) { + return new Promised(List.of(file), null); + } + /** Returns all of the files in this signature, throwing an exception if there are more or less than 1 file. */ public Collection files() { return Collections.unmodifiableList(files); diff --git a/lib/src/main/java/com/diffplug/spotless/npm/EslintConfig.java b/lib/src/main/java/com/diffplug/spotless/npm/EslintConfig.java index 3499b3face..8db9cf07af 100644 --- a/lib/src/main/java/com/diffplug/spotless/npm/EslintConfig.java +++ b/lib/src/main/java/com/diffplug/spotless/npm/EslintConfig.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 DiffPlug + * Copyright 2016-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,37 +16,22 @@ package com.diffplug.spotless.npm; import java.io.File; -import java.io.IOException; import java.io.Serializable; import javax.annotation.Nullable; import com.diffplug.spotless.FileSignature; -import com.diffplug.spotless.ThrowingEx; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; public class EslintConfig implements Serializable { - - private static final long serialVersionUID = -6196834313082791248L; - - @SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED") - @Nullable - private final transient File eslintConfigPath; + private static final long serialVersionUID = 1L; @SuppressWarnings("unused") - private final FileSignature eslintConfigPathSignature; - + private final FileSignature.Promised eslintConfigPathSignature; private final String eslintConfigJs; public EslintConfig(@Nullable File eslintConfigPath, @Nullable String eslintConfigJs) { - try { - this.eslintConfigPath = eslintConfigPath; - this.eslintConfigPathSignature = eslintConfigPath != null ? FileSignature.signAsList(this.eslintConfigPath) : FileSignature.signAsList(); - this.eslintConfigJs = eslintConfigJs; - } catch (IOException e) { - throw ThrowingEx.asRuntime(e); - } + this.eslintConfigPathSignature = eslintConfigPath == null ? null : FileSignature.promise(eslintConfigPath); + this.eslintConfigJs = eslintConfigJs; } public EslintConfig withEslintConfigPath(@Nullable File eslintConfigPath) { @@ -55,7 +40,7 @@ public EslintConfig withEslintConfigPath(@Nullable File eslintConfigPath) { @Nullable public File getEslintConfigPath() { - return eslintConfigPath; + return eslintConfigPathSignature == null ? null : eslintConfigPathSignature.get().getOnlyFile(); } @Nullable @@ -64,7 +49,7 @@ public String getEslintConfigJs() { } public EslintConfig verify() { - if (eslintConfigPath == null && eslintConfigJs == null) { + if (eslintConfigPathSignature == null && eslintConfigJs == null) { throw new IllegalArgumentException("ESLint must be configured using either a configFile or a configJs - but both are null."); } return this; diff --git a/lib/src/main/java/com/diffplug/spotless/npm/EslintFormatterStep.java b/lib/src/main/java/com/diffplug/spotless/npm/EslintFormatterStep.java index cee51b8518..70beaf91ca 100644 --- a/lib/src/main/java/com/diffplug/spotless/npm/EslintFormatterStep.java +++ b/lib/src/main/java/com/diffplug/spotless/npm/EslintFormatterStep.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 DiffPlug + * Copyright 2016-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,8 +39,6 @@ import com.diffplug.spotless.ThrowingEx; import com.diffplug.spotless.npm.EslintRestService.FormatOption; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - public class EslintFormatterStep { private static final Logger logger = LoggerFactory.getLogger(EslintFormatterStep.class); @@ -81,12 +79,10 @@ public static FormatterStep create(Map devDependencies, Provisio } private static class State extends NpmFormatterStepStateBase implements Serializable { + private static final long serialVersionUID = 1L; - private static final long serialVersionUID = -539537027004745812L; private final EslintConfig origEslintConfig; - - @SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED") - private transient EslintConfig eslintConfigInUse; + private EslintConfig eslintConfigInUse; State(String stepName, Map devDependencies, File projectDir, File buildDir, File cacheDir, NpmPathResolver npmPathResolver, EslintConfig eslintConfig) throws IOException { super(stepName, @@ -102,15 +98,14 @@ private static class State extends NpmFormatterStepStateBase implements Serializ projectDir, buildDir, cacheDir, - npmPathResolver::resolveNpmExecutable, - npmPathResolver::resolveNodeExecutable)); + npmPathResolver)); this.origEslintConfig = requireNonNull(eslintConfig.verify()); this.eslintConfigInUse = eslintConfig; } @Override - protected void prepareNodeServerLayout() throws IOException { - super.prepareNodeServerLayout(); + protected void prepareNodeServerLayout(NodeServerLayout nodeServerLayout) throws IOException { + super.prepareNodeServerLayout(nodeServerLayout); if (origEslintConfig.getEslintConfigPath() != null) { // If any config files are provided, we need to make sure they are at the same location as the node modules // as eslint will try to resolve plugin/config names relatively to the config file location and some @@ -126,9 +121,10 @@ protected void prepareNodeServerLayout() throws IOException { public FormatterFunc createFormatterFunc() { try { logger.info("Creating formatter function (starting server)"); - ServerProcessInfo eslintRestServer = npmRunServer(); + Runtime runtime = toRuntime(); + ServerProcessInfo eslintRestServer = runtime.npmRunServer(); EslintRestService restService = new EslintRestService(eslintRestServer.getBaseUrl()); - return Closeable.ofDangerous(() -> endServer(restService, eslintRestServer), new EslintFilePathPassingFormatterFunc(locations.projectDir(), nodeServerLayout.nodeModulesDir(), eslintConfigInUse, restService)); + return Closeable.ofDangerous(() -> endServer(restService, eslintRestServer), new EslintFilePathPassingFormatterFunc(locations.projectDir(), runtime.nodeServerLayout().nodeModulesDir(), eslintConfigInUse, restService)); } catch (IOException e) { throw ThrowingEx.asRuntime(e); } diff --git a/lib/src/main/java/com/diffplug/spotless/npm/EslintTypescriptConfig.java b/lib/src/main/java/com/diffplug/spotless/npm/EslintTypescriptConfig.java index ea3e2046b3..42dec6837a 100644 --- a/lib/src/main/java/com/diffplug/spotless/npm/EslintTypescriptConfig.java +++ b/lib/src/main/java/com/diffplug/spotless/npm/EslintTypescriptConfig.java @@ -1,5 +1,5 @@ /* - * Copyright 2022-2023 DiffPlug + * Copyright 2022-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,43 +16,29 @@ package com.diffplug.spotless.npm; import java.io.File; -import java.io.IOException; import javax.annotation.Nullable; import com.diffplug.spotless.FileSignature; -import com.diffplug.spotless.ThrowingEx; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; public class EslintTypescriptConfig extends EslintConfig { - - private static final long serialVersionUID = -126864670181617006L; - - @SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED") - @Nullable - private final transient File typescriptConfigPath; + private static final long serialVersionUID = 2L; @SuppressWarnings("unused") - private final FileSignature typescriptConfigPathSignature; + private final FileSignature.Promised typescriptConfigPathSignature; public EslintTypescriptConfig(@Nullable File eslintConfigPath, @Nullable String eslintConfigJs, @Nullable File typescriptConfigPath) { super(eslintConfigPath, eslintConfigJs); - try { - this.typescriptConfigPath = typescriptConfigPath; - this.typescriptConfigPathSignature = typescriptConfigPath != null ? FileSignature.signAsList(this.typescriptConfigPath) : FileSignature.signAsList(); - } catch (IOException e) { - throw ThrowingEx.asRuntime(e); - } + this.typescriptConfigPathSignature = typescriptConfigPath != null ? FileSignature.promise(typescriptConfigPath) : null; } @Override public EslintConfig withEslintConfigPath(@Nullable File eslintConfigPath) { - return new EslintTypescriptConfig(eslintConfigPath, this.getEslintConfigJs(), this.typescriptConfigPath); + return new EslintTypescriptConfig(eslintConfigPath, this.getEslintConfigJs(), getTypescriptConfigPath()); } @Nullable public File getTypescriptConfigPath() { - return typescriptConfigPath; + return typescriptConfigPathSignature == null ? null : this.typescriptConfigPathSignature.get().getOnlyFile(); } } diff --git a/lib/src/main/java/com/diffplug/spotless/npm/NpmFormatterStepLocations.java b/lib/src/main/java/com/diffplug/spotless/npm/NpmFormatterStepLocations.java index 67763e59ec..4df5736dd9 100644 --- a/lib/src/main/java/com/diffplug/spotless/npm/NpmFormatterStepLocations.java +++ b/lib/src/main/java/com/diffplug/spotless/npm/NpmFormatterStepLocations.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 DiffPlug + * Copyright 2023-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,36 +19,23 @@ import java.io.File; import java.io.Serializable; -import java.util.function.Supplier; import javax.annotation.Nonnull; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - class NpmFormatterStepLocations implements Serializable { private static final long serialVersionUID = -1055408537924029969L; - @SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED") - private final transient File projectDir; - - @SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED") - private final transient File buildDir; - - @SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED") - private final transient File cacheDir; - - @SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED") - private final transient Supplier npmExecutable; - @SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED") - private final transient Supplier nodeExecutable; + private final File projectDir; + private final File buildDir; + private final File cacheDir; + private final NpmPathResolver resolver; - public NpmFormatterStepLocations(@Nonnull File projectDir, @Nonnull File buildDir, File cacheDir, @Nonnull Supplier npmExecutable, @Nonnull Supplier nodeExecutable) { + public NpmFormatterStepLocations(@Nonnull File projectDir, @Nonnull File buildDir, File cacheDir, @Nonnull NpmPathResolver resolver) { this.projectDir = requireNonNull(projectDir); this.buildDir = requireNonNull(buildDir); this.cacheDir = cacheDir; - this.npmExecutable = requireNonNull(npmExecutable); - this.nodeExecutable = requireNonNull(nodeExecutable); + this.resolver = requireNonNull(resolver); } public File projectDir() { @@ -64,10 +51,10 @@ public File cacheDir() { } public File npmExecutable() { - return npmExecutable.get(); + return resolver.resolveNpmExecutable(); } public File nodeExecutable() { - return nodeExecutable.get(); + return resolver.resolveNodeExecutable(); } } diff --git a/lib/src/main/java/com/diffplug/spotless/npm/NpmFormatterStepStateBase.java b/lib/src/main/java/com/diffplug/spotless/npm/NpmFormatterStepStateBase.java index 3f262c813c..3ec06e0434 100644 --- a/lib/src/main/java/com/diffplug/spotless/npm/NpmFormatterStepStateBase.java +++ b/lib/src/main/java/com/diffplug/spotless/npm/NpmFormatterStepStateBase.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 DiffPlug + * Copyright 2016-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,8 +35,6 @@ import com.diffplug.spotless.ProcessRunner.LongRunningProcess; import com.diffplug.spotless.ThrowingEx; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - abstract class NpmFormatterStepStateBase implements Serializable { private static final Logger logger = LoggerFactory.getLogger(NpmFormatterStepStateBase.class); @@ -45,83 +43,100 @@ abstract class NpmFormatterStepStateBase implements Serializable { private static final long serialVersionUID = 1460749955865959948L; - @SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED") - protected final transient NodeServerLayout nodeServerLayout; - - public final NpmFormatterStepLocations locations; - - private final NpmConfig npmConfig; - private final String stepName; + private final NpmConfig npmConfig; - private final transient NodeServeApp nodeServeApp; + public final NpmFormatterStepLocations locations; protected NpmFormatterStepStateBase(String stepName, NpmConfig npmConfig, NpmFormatterStepLocations locations) throws IOException { this.stepName = requireNonNull(stepName); this.npmConfig = requireNonNull(npmConfig); this.locations = locations; - this.nodeServerLayout = new NodeServerLayout(locations.buildDir(), npmConfig.getPackageJsonContent()); - this.nodeServeApp = new NodeServeApp(nodeServerLayout, npmConfig, locations); } - protected void prepareNodeServerLayout() throws IOException { - nodeServeApp.prepareNodeAppLayout(); + public Runtime toRuntime() { + return new Runtime(this); } - protected void prepareNodeServer() throws IOException { - nodeServeApp.npmInstall(); + protected void prepareNodeServerLayout(NodeServerLayout layout) throws IOException { + } - protected void assertNodeServerDirReady() throws IOException { - if (needsPrepareNodeServerLayout()) { - // reinstall if missing - prepareNodeServerLayout(); + public static class Runtime { + private final NpmFormatterStepStateBase parent; + private final NodeServerLayout nodeServerLayout; + private final NodeServeApp nodeServeApp; + + Runtime(NpmFormatterStepStateBase parent) { + this.parent = parent; + this.nodeServerLayout = new NodeServerLayout(parent.locations.buildDir(), parent.npmConfig.getPackageJsonContent()); + this.nodeServeApp = new NodeServeApp(nodeServerLayout, parent.npmConfig, parent.locations); } - if (needsPrepareNodeServer()) { - // run npm install if node_modules is missing - prepareNodeServer(); + + public NodeServerLayout nodeServerLayout() { + return nodeServerLayout; } - } - protected boolean needsPrepareNodeServer() { - return nodeServeApp.needsNpmInstall(); - } + protected void prepareNodeServerLayout() throws IOException { + nodeServeApp.prepareNodeAppLayout(); + parent.prepareNodeServerLayout(nodeServerLayout); + } - protected boolean needsPrepareNodeServerLayout() { - return nodeServeApp.needsPrepareNodeAppLayout(); - } + protected void prepareNodeServer() throws IOException { + nodeServeApp.npmInstall(); + } + + protected void assertNodeServerDirReady() throws IOException { + if (needsPrepareNodeServerLayout()) { + // reinstall if missing + prepareNodeServerLayout(); + } + if (needsPrepareNodeServer()) { + // run npm install if node_modules is missing + prepareNodeServer(); + } + } - protected ServerProcessInfo npmRunServer() throws ServerStartException, IOException { - assertNodeServerDirReady(); - LongRunningProcess server = null; - try { - // The npm process will output the randomly selected port of the http server process to 'server.port' file - // so in order to be safe, remove such a file if it exists before starting. - final File serverPortFile = new File(this.nodeServerLayout.nodeModulesDir(), "server.port"); - NpmResourceHelper.deleteFileIfExists(serverPortFile); - // start the http server in node - server = nodeServeApp.startNpmServeProcess(); - - // await the readiness of the http server - wait for at most 60 seconds + protected boolean needsPrepareNodeServer() { + return nodeServeApp.needsNpmInstall(); + } + + protected boolean needsPrepareNodeServerLayout() { + return nodeServeApp.needsPrepareNodeAppLayout(); + } + + protected ServerProcessInfo npmRunServer() throws ServerStartException, IOException { + assertNodeServerDirReady(); + LongRunningProcess server = null; try { - NpmResourceHelper.awaitReadableFile(serverPortFile, Duration.ofSeconds(60)); - } catch (TimeoutException timeoutException) { - // forcibly end the server process + // The npm process will output the randomly selected port of the http server process to 'server.port' file + // so in order to be safe, remove such a file if it exists before starting. + final File serverPortFile = new File(this.nodeServerLayout.nodeModulesDir(), "server.port"); + NpmResourceHelper.deleteFileIfExists(serverPortFile); + // start the http server in node + server = nodeServeApp.startNpmServeProcess(); + + // await the readiness of the http server - wait for at most 60 seconds try { - if (server.isAlive()) { - server.destroyForcibly(); - server.waitFor(); + NpmResourceHelper.awaitReadableFile(serverPortFile, Duration.ofSeconds(60)); + } catch (TimeoutException timeoutException) { + // forcibly end the server process + try { + if (server.isAlive()) { + server.destroyForcibly(); + server.waitFor(); + } + } catch (Throwable t) { + // ignore } - } catch (Throwable t) { - // ignore + throw timeoutException; } - throw timeoutException; + // read the server.port file for resulting port and remember the port for later formatting calls + String serverPort = NpmResourceHelper.readUtf8StringFromFile(serverPortFile).trim(); + return new ServerProcessInfo(server, serverPort, serverPortFile); + } catch (IOException | TimeoutException e) { + throw new ServerStartException("Starting server failed." + (server != null ? "\n\nProcess result:\n" + ThrowingEx.get(server::result) : ""), e); } - // read the server.port file for resulting port and remember the port for later formatting calls - String serverPort = NpmResourceHelper.readUtf8StringFromFile(serverPortFile).trim(); - return new ServerProcessInfo(server, serverPort, serverPortFile); - } catch (IOException | TimeoutException e) { - throw new ServerStartException("Starting server failed." + (server != null ? "\n\nProcess result:\n" + ThrowingEx.get(server::result) : ""), e); } } diff --git a/lib/src/main/java/com/diffplug/spotless/npm/NpmPathResolver.java b/lib/src/main/java/com/diffplug/spotless/npm/NpmPathResolver.java index 1a7db1c9b8..317c2a479b 100644 --- a/lib/src/main/java/com/diffplug/spotless/npm/NpmPathResolver.java +++ b/lib/src/main/java/com/diffplug/spotless/npm/NpmPathResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 DiffPlug + * Copyright 2020-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,10 +16,12 @@ package com.diffplug.spotless.npm; import java.io.File; +import java.io.Serializable; import java.util.List; import java.util.Optional; -public class NpmPathResolver { +public class NpmPathResolver implements Serializable { + private static final long serialVersionUID = 1L; private final File explicitNpmExecutable; diff --git a/lib/src/main/java/com/diffplug/spotless/npm/PrettierConfig.java b/lib/src/main/java/com/diffplug/spotless/npm/PrettierConfig.java index 328cb25a4e..8a51910205 100644 --- a/lib/src/main/java/com/diffplug/spotless/npm/PrettierConfig.java +++ b/lib/src/main/java/com/diffplug/spotless/npm/PrettierConfig.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 DiffPlug + * Copyright 2016-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ package com.diffplug.spotless.npm; import java.io.File; -import java.io.IOException; import java.io.Serializable; import java.util.Map; import java.util.TreeMap; @@ -24,36 +23,23 @@ import javax.annotation.Nullable; import com.diffplug.spotless.FileSignature; -import com.diffplug.spotless.ThrowingEx; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; public class PrettierConfig implements Serializable { private static final long serialVersionUID = -8709340269833126583L; - @SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED") - @Nullable - private final transient File prettierConfigPath; - - @SuppressWarnings("unused") - private final FileSignature prettierConfigPathSignature; + private final FileSignature.Promised prettierConfigPathSignature; private final TreeMap options; public PrettierConfig(@Nullable File prettierConfigPath, @Nullable Map options) { - try { - this.prettierConfigPath = prettierConfigPath; - this.prettierConfigPathSignature = prettierConfigPath != null ? FileSignature.signAsList(this.prettierConfigPath) : FileSignature.signAsList(); - this.options = options == null ? new TreeMap<>() : new TreeMap<>(options); - } catch (IOException e) { - throw ThrowingEx.asRuntime(e); - } + this.prettierConfigPathSignature = prettierConfigPath == null ? null : FileSignature.promise(prettierConfigPath); + this.options = options == null ? new TreeMap<>() : new TreeMap<>(options); } @Nullable public File getPrettierConfigPath() { - return prettierConfigPath; + return prettierConfigPathSignature == null ? null : prettierConfigPathSignature.get().getOnlyFile(); } public Map getOptions() { diff --git a/lib/src/main/java/com/diffplug/spotless/npm/PrettierFormatterStep.java b/lib/src/main/java/com/diffplug/spotless/npm/PrettierFormatterStep.java index 72fecded1f..27a1002df5 100644 --- a/lib/src/main/java/com/diffplug/spotless/npm/PrettierFormatterStep.java +++ b/lib/src/main/java/com/diffplug/spotless/npm/PrettierFormatterStep.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 DiffPlug + * Copyright 2016-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -79,8 +79,7 @@ private static class State extends NpmFormatterStepStateBase implements Serializ projectDir, buildDir, cacheDir, - npmPathResolver::resolveNpmExecutable, - npmPathResolver::resolveNodeExecutable)); + npmPathResolver)); this.prettierConfig = requireNonNull(prettierConfig); } @@ -89,7 +88,7 @@ private static class State extends NpmFormatterStepStateBase implements Serializ public FormatterFunc createFormatterFunc() { try { logger.info("creating formatter function (starting server)"); - ServerProcessInfo prettierRestServer = npmRunServer(); + ServerProcessInfo prettierRestServer = toRuntime().npmRunServer(); PrettierRestService restService = new PrettierRestService(prettierRestServer.getBaseUrl()); String prettierConfigOptions = restService.resolveConfig(this.prettierConfig.getPrettierConfigPath(), this.prettierConfig.getOptions()); return Closeable.ofDangerous(() -> endServer(restService, prettierRestServer), new PrettierFilePathPassingFormatterFunc(prettierConfigOptions, restService)); diff --git a/lib/src/main/java/com/diffplug/spotless/npm/TsFmtFormatterStep.java b/lib/src/main/java/com/diffplug/spotless/npm/TsFmtFormatterStep.java index 6b55610be0..b171b0ca7f 100644 --- a/lib/src/main/java/com/diffplug/spotless/npm/TsFmtFormatterStep.java +++ b/lib/src/main/java/com/diffplug/spotless/npm/TsFmtFormatterStep.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 DiffPlug + * Copyright 2016-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -83,8 +83,7 @@ public State(String stepName, Map versions, File projectDir, Fil projectDir, buildDir, cacheDir, - npmPathResolver::resolveNpmExecutable, - npmPathResolver::resolveNodeExecutable)); + npmPathResolver)); this.buildDir = requireNonNull(buildDir); this.configFile = configFile; this.inlineTsFmtSettings = inlineTsFmtSettings == null ? new TreeMap<>() : new TreeMap<>(inlineTsFmtSettings); @@ -95,7 +94,7 @@ public State(String stepName, Map versions, File projectDir, Fil public FormatterFunc createFormatterFunc() { try { Map tsFmtOptions = unifyOptions(); - ServerProcessInfo tsfmtRestServer = npmRunServer(); + ServerProcessInfo tsfmtRestServer = toRuntime().npmRunServer(); TsFmtRestService restService = new TsFmtRestService(tsfmtRestServer.getBaseUrl()); return Closeable.ofDangerous(() -> endServer(restService, tsfmtRestServer), input -> restService.format(input, tsFmtOptions)); } catch (IOException e) { diff --git a/lib/src/main/java/com/diffplug/spotless/npm/TypedTsFmtConfigFile.java b/lib/src/main/java/com/diffplug/spotless/npm/TypedTsFmtConfigFile.java index 75257711f6..c9b80394a8 100644 --- a/lib/src/main/java/com/diffplug/spotless/npm/TypedTsFmtConfigFile.java +++ b/lib/src/main/java/com/diffplug/spotless/npm/TypedTsFmtConfigFile.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 DiffPlug + * Copyright 2016-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,15 +18,9 @@ import static java.util.Objects.requireNonNull; import java.io.File; -import java.io.IOException; import java.io.Serializable; import java.util.Locale; -import com.diffplug.spotless.FileSignature; -import com.diffplug.spotless.ThrowingEx; - -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; - public class TypedTsFmtConfigFile implements Serializable { private static final long serialVersionUID = -4442310349275775501L; @@ -35,18 +29,9 @@ public class TypedTsFmtConfigFile implements Serializable { private final File configFile; - @SuppressFBWarnings("SE_TRANSIENT_FIELD_NOT_RESTORED") - @SuppressWarnings("unused") - private final FileSignature configFileSignature; - public TypedTsFmtConfigFile(TsConfigFileType configFileType, File configFile) { this.configFileType = requireNonNull(configFileType); this.configFile = requireNonNull(configFile); - try { - this.configFileSignature = FileSignature.signAsList(configFile); - } catch (IOException e) { - throw ThrowingEx.asRuntime(e); - } } TsConfigFileType configFileType() { diff --git a/testlib/src/test/java/com/diffplug/spotless/npm/NpmFormatterStepCommonTests.java b/testlib/src/test/java/com/diffplug/spotless/npm/NpmFormatterStepCommonTests.java index 5eff34ef29..2672785453 100644 --- a/testlib/src/test/java/com/diffplug/spotless/npm/NpmFormatterStepCommonTests.java +++ b/testlib/src/test/java/com/diffplug/spotless/npm/NpmFormatterStepCommonTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 DiffPlug + * Copyright 2016-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,10 +16,10 @@ package com.diffplug.spotless.npm; import java.io.File; -import java.io.IOException; import java.util.Collections; import com.diffplug.spotless.ResourceHarness; +import com.diffplug.spotless.ThrowingEx; public abstract class NpmFormatterStepCommonTests extends ResourceHarness { @@ -41,18 +41,18 @@ private File npmrc() { private File buildDir = null; - protected File buildDir() throws IOException { + protected File buildDir() { if (this.buildDir == null) { - this.buildDir = newFolder("build-dir"); + this.buildDir = ThrowingEx.get(() -> newFolder("build-dir")); } return this.buildDir; } private File projectDir = null; - protected File projectDir() throws IOException { + protected File projectDir() { if (this.projectDir == null) { - this.projectDir = newFolder("project-dir"); + this.projectDir = ThrowingEx.get(() -> newFolder("project-dir")); } return this.projectDir; } diff --git a/testlib/src/test/java/com/diffplug/spotless/npm/PrettierFormatterStepTest.java b/testlib/src/test/java/com/diffplug/spotless/npm/PrettierFormatterStepTest.java index 769d91bc01..fb92eb9d39 100644 --- a/testlib/src/test/java/com/diffplug/spotless/npm/PrettierFormatterStepTest.java +++ b/testlib/src/test/java/com/diffplug/spotless/npm/PrettierFormatterStepTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 DiffPlug + * Copyright 2016-2024 DiffPlug * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,14 +26,14 @@ import com.diffplug.common.collect.ImmutableMap; import com.diffplug.spotless.FormatterStep; -import com.diffplug.spotless.ResourceHarness; +import com.diffplug.spotless.SerializableEqualityTester; import com.diffplug.spotless.StepHarness; import com.diffplug.spotless.StepHarnessWithFile; import com.diffplug.spotless.TestProvisioner; import com.diffplug.spotless.tag.NpmTest; @NpmTest -class PrettierFormatterStepTest extends ResourceHarness { +class PrettierFormatterStepTest extends NpmFormatterStepCommonTests { private static final String PRETTIER_VERSION_2 = PrettierFormatterStep.DEFAULT_VERSION; @@ -189,4 +189,35 @@ private String major(String semVer) { return semVer.split("\\.")[0]; } } + + @Test + void equality() { + new SerializableEqualityTester() { + String prettierVersion = "3.0.0"; + PrettierConfig config = new PrettierConfig(null, Map.of("parser", "typescript")); + + @Override + protected void setupTest(API api) { + // same version == same + api.areDifferentThan(); + // change the groupArtifact, and it's different + prettierVersion = "2.8.8"; + api.areDifferentThan(); + config = new PrettierConfig(null, Map.of("parser", "css")); + api.areDifferentThan(); + } + + @Override + protected FormatterStep create() { + return PrettierFormatterStep.create( + ImmutableMap.of("prettier", prettierVersion), + TestProvisioner.mavenCentral(), + projectDir(), + buildDir(), + null, + npmPathResolver(), + config); // should select parser based on this name + } + }.testEquals(); + } }