ããã¯ããªã«ãããããŠæžãããã®ïŒ
Javaã§ããã°ã©ã ãæžããŠããŠããœãŒã¹ã³ãŒããäžæ¬ã§ãã©ãŒããããããããã©ãŒãããããã®ãå¿ããªãããã«ããããšããã
話ããããšæããŸãã
ããããã®ã調ã¹ãŠã¿ããšããããŠãEclipseã®ãã©ãŒããã¿ãŒãCLIã§åããããšãIntelliJã®ãã©ãŒããã¿ãŒãCLIã§åãããã¿ãããªãã®ã
èŠã€ãããŸãã
How to Run the Eclipse Formatter From the Command Line
Format files from the command line | IntelliJ IDEA Documentation
ãã®ç®çã®ããã«IDEãæã¡åºãã®ã¯åŸ®åŠã ãªãšæã£ãŠããã¡ãã£ãšèª¿ã¹ãŠããããMavenãã©ã°ã€ã³ããã£ãã®ã§ã¡ãã£ãšè©ŠããŠã¿ãŸããã
以äžã®4ã€ãèŠã€ããŸããïŒSpotlessã¯æããŠããããŸããïŒã
- formatter-maven-plugin – Introduction
- GitHub - google/google-java-format: Reformats Java source code to comply with Google Java Style.
- GitHub - diffplug/spotless: Keep your code spotless
- GitHub - HubSpot/prettier-maven-plugin
ä»åã¯ãEclipseã®ãã©ãŒãããã䜿ãFormatter Maven Pluginãè©ŠããŠã¿ãããšæããŸãã
â» Prettier Javaã¯ãNode.jsãå¿
èŠã«ãªããŸã
IDEã§ä¿åæã«èªåãã©ãŒãããããããã«ããŠããã°ããã®ã§ã¯ããšãã話ã¯ããã§ã¯çœ®ããŠãããŸãã
Eclipse Tip - Format Source Code on Save | Cody Burleson
Reformat code | IntelliJ IDEA Documentation
Formatter Maven Plugin
Formatter Maven Pluginã®Webãµã€ãã¯ãã¡ãã
formatter-maven-plugin – Introduction
GitHubãªããžããªã¯ãã¡ãã
GitHub - revelc/formatter-maven-plugin: Formatter Maven Plugin
Formatter Maven Pluginãã©ããããã®ããšãããšãEclipseã®ã³ãŒããã©ãŒããã¿ãŒã䜿çšããŠJavaãœãŒã¹ã³ãŒãããã©ãŒããããã
Mavenãã©ã°ã€ã³ã§ãã
çŸæç¹ã§ãEclipseãšã®äºææ§ã¯ä»¥äžã®ããã«ãªã£ãŠããŸãã
formatter-maven-plugin – Eclipse Version Compatibility
ãŽãŒã«ã¯formatter:format
ãšformatter:validate
ã®2ã€ãããã以äžã®éãããããŸãã
- formatter:format ⊠èšå®ã«åŸã£ãŠãœãŒã¹ã³ãŒãããã©ãŒããããã
- formatter:validate ⊠èšå®ã«åŸã£ãŠãœãŒã¹ã³ãŒãããã©ãŒããããããŠããªãå Žåããã«ãã«å€±æãã
formatter:validate
ã®æ¹ã¯ãCIã«çµã¿èŸŒãã ãããããšãæ³å®ããŠããããã§ãã
æ©èœã»èšå®çã«ã¯ã以äžã®ãããªããšãã§ããŸãã
- JavaãJavaScriptãJSONãXMLãHTMLãCSSã®ãã©ãŒããã
- æ§æãã¡ã€ã«ã®æå®
- æ¹è¡ã³ãŒãã®æå®
- ãšã³ã³ãŒãã£ã³ã°ã®æå®
ãŽãŒã«ã¯åç¬ã§åããããšãã§ããŸãããexecutions / execution / goals / goal
ã«æå®ããããšã§compile
ãŽãŒã«ã®å®è¡æã«
formatter:format
ãformatter:validate
ãåããããšãã§ããŸãã
formatter-maven-plugin – Plugin Usage
ãµã³ãã«ã¯ãã¡ãã
formatter-maven-plugin – Examples
ã§ã¯ãé©åœã«ãœãŒã¹ã³ãŒããçšæããŠç°¡åã«è©ŠããŠã¿ãŸãã
ç°å¢
ä»åã®ç°å¢ã¯ããã¡ãã
$ java --version openjdk 17.0.5 2022-10-18 OpenJDK Runtime Environment (build 17.0.5+8-Ubuntu-2ubuntu122.04) OpenJDK 64-Bit Server VM (build 17.0.5+8-Ubuntu-2ubuntu122.04, mixed mode, sharing) $ mvn --version Apache Maven 3.8.7 (b89d5959fcde851dcb1c8946a785a163f14e1e29) Maven home: $HOME/.sdkman/candidates/maven/current Java version: 17.0.5, vendor: Private Build, runtime: /usr/lib/jvm/java-17-openjdk-amd64 Default locale: ja_JP, platform encoding: UTF-8 OS name: "linux", version: "5.15.0-57-generic", arch: "amd64", family: "unix"
ãµã³ãã«ã¢ããªã±ãŒã·ã§ã³ãäœæãã
ã§ã¯ãç°¡åãªã¢ããªã±ãŒã·ã§ã³ãäœæããŸããJAX-RSïŒCDIãªJavaã¢ããªã±ãŒã·ã§ã³ããJava SEç°å¢ã§åããããšã«ããŸãããã
MavenäŸåé¢ä¿ãªã©ã¯ãã¡ãã
<properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> <dependencies> <dependency> <groupId>org.jboss.resteasy</groupId> <artifactId>resteasy-undertow-cdi</artifactId> <version>6.2.2.Final</version> </dependency> </dependencies>
空ã®beans.xml
ã
src/main/resources/META-INF/beans.xml
ãœãŒã¹ã³ãŒãã¯ãã¡ãããã©ãŒãããåŸã§ãã
src/main/java/org/littlewings/formatter/App.java
package org.littlewings.formatter; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import jakarta.ws.rs.SeBootstrap; import org.jboss.logging.Logger; import org.littlewings.formatter.rest.JaxrsActivator; public class App { public static void main(String... args) throws ExecutionException, InterruptedException { Logger logger = Logger.getLogger(App.class); SeBootstrap.Configuration configuration = SeBootstrap.Configuration.builder().host("0.0.0.0").port(8080) .build(); SeBootstrap.Instance instance = SeBootstrap.start(new JaxrsActivator(), configuration).toCompletableFuture() .get(); logger.info("server startup."); while (true) { TimeUnit.SECONDS.sleep(5L); } /* * instance .stop() .toCompletableFuture() .get(); */ } }
src/main/java/org/littlewings/formatter/rest/HelloResource.java
package org.littlewings.formatter.rest; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; import org.littlewings.formatter.service.MessageService; @Path("hello") @ApplicationScoped public class HelloResource { @Inject MessageService messageService; @GET @Produces(MediaType.TEXT_PLAIN) public String message(@QueryParam("word") String word) { return messageService.create(word); } }
src/main/java/org/littlewings/formatter/rest/JaxrsActivator.java
package org.littlewings.formatter.rest; import java.util.Set; import jakarta.ws.rs.ApplicationPath; import jakarta.ws.rs.core.Application; @ApplicationPath("") public class JaxrsActivator extends Application { @Override public Set<Class<?>> getClasses() { return Set.of(HelloResource.class); } }
src/main/java/org/littlewings/formatter/service/MessageService.java
package org.littlewings.formatter.service; import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped public class MessageService { public String create(String word) { if (word != null) { return String.format("Hello %s!!", word); } else { return "Hello World!!"; } } }
åäœç¢ºèªã
$ mvn compile exec:java -Dexec.mainClass=org.littlewings.formatter.App
OKã§ããã
$ curl localhost:8080/hello?word=RESTEasy Hello RESTEasy!!
ã§ã¯ãããã§é©åœã«ãœãŒã¹ã³ãŒãã®ãã©ãŒãããã厩ããŠãããŸãã
src/main/java/org/littlewings/formatter/App.java
package org.littlewings.formatter; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import jakarta.ws.rs.SeBootstrap; import org.jboss.logging.Logger; import org.littlewings.formatter.rest.JaxrsActivator; public class App { public static void main(String... args) throws ExecutionException, InterruptedException { Logger logger = Logger.getLogger(App.class); SeBootstrap.Configuration configuration = SeBootstrap.Configuration.builder().host("0.0.0.0").port(8080) .build(); SeBootstrap.Instance instance = SeBootstrap.start(new JaxrsActivator(), configuration).toCompletableFuture() .get(); logger.info("server startup."); while (true){TimeUnit.SECONDS.sleep(5L);} /* * instance .stop() .toCompletableFuture() .get(); */ } }
src/main/java/org/littlewings/formatter/rest/HelloResource.java
package org.littlewings.formatter.rest; import jakarta.enterprise.context.ApplicationScoped; import jakarta.inject.Inject; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.QueryParam; import jakarta.ws.rs.core.MediaType; import org.littlewings.formatter.service.MessageService; @Path("hello") @ApplicationScoped public class HelloResource { @Inject MessageService messageService; @GET @Produces(MediaType.TEXT_PLAIN) public String message( @QueryParam("word") String word ) { return messageService.create(word); } }
src/main/java/org/littlewings/formatter/rest/JaxrsActivator.java
package org.littlewings.formatter.rest; import java.util.Set; import jakarta.ws.rs.ApplicationPath; import jakarta.ws.rs.core.Application; @ApplicationPath("") public class JaxrsActivator extends Application { @Override public Set<Class<?>> getClasses() { return Set.of(HelloResource.class); } }
src/main/java/org/littlewings/formatter/service/MessageService.java
package org.littlewings.formatter.service; import jakarta.enterprise.context.ApplicationScoped; @ApplicationScoped public class MessageService { public String create(String word) { if (word != null) {return String.format("Hello %s!!", word); } else { return "Hello World!!"; } } }
Formatter Maven Pluginãçµã¿èŸŒã
ããã§ã¯ãFormatter Maven Pluginãçµã¿èŸŒãã§ã¿ãŸãã
ãŸãã¯ããã©ã«ãã®ç¶æ ã§ã
<build> <plugins> <plugin> <groupId>net.revelc.code.formatter</groupId> <artifactId>formatter-maven-plugin</artifactId> <version>2.21.0</version> </plugin> </plugins> </build>
formatter:validate
ã§ããã©ãŒãããæžã¿ãã©ããã確èªããŠã¿ãŸãã
$ mvn formatter:validate
ãšã©ãŒã«ãªããŸããããã©ãŒãããã厩ããã®ã§åœç¶ã§ããã
[INFO] --- formatter-maven-plugin:2.21.0:validate (default-cli) @ formatter-maven-plugin-example --- [INFO] ------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1.202 s [INFO] Finished at: 2023-01-09T22:22:05+09:00 [INFO] ------------------------------------------------------------------------ [ERROR] Failed to execute goal net.revelc.code.formatter:formatter-maven-plugin:2.21.0:validate (default-cli) on project formatter-maven-plugin-example: File '/paht/to/src/main/java/org/littlewings/formatter/App.java' has not been previously formatted. Please format file (for example by invoking `mvn net.revelc.code.formatter:formatter-maven-plugin:2.21.0:format`) and commit before running validation! -> [Help 1]
ã²ãšã€NGã®ãã®ãèŠã€ãããšããã®æç¹ã§å€±æããããã§ããã
formatter:format
ã§ãã©ãŒãããããŠã¿ãŸãã
$ mvn formatter:format
4ãã¡ã€ã«ãã©ãŒããããããŸãããçµæã¯æåã«èŒãããœãŒã¹ã³ãŒããšåãã«ãªãã®ã§å²æããŸãã
[INFO] --- formatter-maven-plugin:2.21.0:format (default-cli) @ formatter-maven-plugin-example --- [INFO] Processed 4 files in 868ms (Formatted: 4, Unchanged: 0, Failed: 0, Readonly: 0) [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1.346 s [INFO] Finished at: 2023-01-09T22:29:24+09:00 [INFO] ------------------------------------------------------------------------
ããã1çªç°¡åãªäœ¿ãæ¹ã§ããã
ããã©ã«ãã§ã¯ãsrc/main/java
ãšsrc/test/java
ã®2ã€ã®ãã£ã¬ã¯ããªã察象ã«ãªããŸãããããããœãŒã¹ãã£ã¬ã¯ããªããã¹ããã£ã¬ã¯ããª
ãšããŠFormatter Maven PluginãèªèããŸãã
src/test/java
ã®æ¹ã«ã¯ãä»åã¯ãªã«ãå
¥ããŠããŸãããâŠã
èšå®ããŠã¿ã
Formatter Maven Pluginã®èšå®ãå€ããŠãã£ãŠã¿ãŸãã
åçš®èšå®ã¯ããããã®ãŽãŒã«ã«é¢ããããã¥ã¡ã³ããèŠãã°ããã®ã§ãããèšå®å¯èœãªé ç®ã¯ã»ãŒåãã§ããã
formatter-maven-plugin – formatter:format
formatter-maven-plugin – formatter:validate
ãããããExamplesã®ããŒãžãèŠããšã»ãšãã©åããããªããšããã£ãŠããŸãã
formatter-maven-plugin – Examples
compileæã«å®è¡ãã
以äžã®ããã«ããããšã§ãcompile
æã«formatter:format
ãå®è¡ããããã«ãªããŸãã
<executions> <execution> <goals> <goal>format</goal> </goals> </execution> </executions>
ã³ã³ãã€ã«ã«åãããŠãåæã«ãã©ãŒããããããåãã«ãªããŸããã
以äžã®ããã«ãããšãcompile
æã«formatter:validate
ãå®è¡ããããã«ãªããŸãã
<executions> <execution> <goals> <goal>validate</goal> </goals> </execution> </executions>
ãã®å Žåããã©ãŒããããããŠããªããœãŒã¹ã³ãŒãããããšãã«ãã«å€±æããããã«ãªããŸãã
確èªã¯ãcompile
ã§ã
$ mvn compile
ãã¡ãã«é¢ããããã¥ã¡ã³ãã¯ããã¡ãã
formatter-maven-plugin – Plugin Usage
ã³ã³ãã€ã©ãŒã®èšå®ãè¡ã
以äžã®ããã«èšå®ããŠãããšãFormatter Maven Pluginããã®å€ã«åŸã£ãŠåäœããŸãã
<properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> </properties>
æ瀺çã«æå®ããå Žåã¯ã以äžã®ããã«ãªããŸãã
<configuration> <compilerSource>17</compilerSource> <compilerCompliance>17</compilerCompliance> <compilerTargetPlatform>17</compilerTargetPlatform> </configuration>
compilerSource
ãšcompilerCompliance
ã«ã¯maven.compiler.source
çžåœã®å€ããcompilerTargetPlatform
ã«ã¯maven.compiler.target
çžåœã®
å€ãæå®ãã¹ãã§ããã
ãã¡ã€ã«ã®ãšã³ã³ãŒãã£ã³ã°ãæå®ãã
encoding
ã§ããã¡ã€ã«ã®ãšã³ã³ãŒãã£ã³ã°ãæå®ã§ããŸãã
<configuration> <encoding>UTF-8</encoding> </configuration>
ãªããšãªããããã§ããã®ã§ã¯ãšããæ°ãâŠã
<configuration> <encoding>${project.build.sourceEncoding}</encoding> </configuration>
ãã¡ã€ã«ã®æ¹è¡ã³ãŒããæå®ãã
lineEnding
ã§æ¹è¡ã³ãŒããæå®ã§ããŸãã
<configuration> <lineEnding>LF</lineEnding> </configuration>
ãã©ãŒããããã察象ãæå®ãã
includes
ã§ããã©ãŒããã察象ã«å«ãããã¡ã€ã«ãæå®ã§ããŸãã
<configuration>
<includes>
<include>**/*.java</include>
</includes>
</configuration>
ããã¥ã¡ã³ãäžã¯ä»¥äžã®ããã«æžãããŠããã®ã§ããã
When not specified, the default include is */.java
å®éã®ããã©ã«ãå€ã¯ä»¥äžã®ããã«ãªã£ãŠããŸãã
/** The Constant DEFAULT_INCLUDES. */ private static final String[] DEFAULT_INCLUDES = { "**/*.css", "**/*.json", "**/*.html", "**/*.java", "**/*.js", "**/*.xml" };
ãã©ãŒããã察象ã®ãã£ã¬ã¯ããªãããã©ã«ãã§src/main/java
ãšsrc/test/java
ãªã®ã§ãå®è³ªJavaãœãŒã¹ã³ãŒãã®ã¿ã察象ãšæããŠã
å·®ãæ¯ããªãã§ããã©ãã
ç¹å®ã®ãã¡ã€ã«ãé€å€ãããå Žåã¯ãexcludes
ã䜿ããŸãã
<configuration> <excludes> <exclude>org/littlewings/formatter/service/**/*Service.java</exclude> <exclude>org/littlewings/formatter/rest/**/*.java</exclude> </excludes> </configuration>
å€éšã®èšå®ãã¡ã€ã«ãæå®ãã
ç¹ã«æå®ããªãå ŽåãFormatter Maven Pluginã¯åãã¡ã€ã«ã以äžã®èšå®ã«åŸã£ãŠãã©ãŒãããããŸãã
- Java ⊠https://github.com/revelc/formatter-maven-plugin/blob/formatter-maven-plugin-2.21.0/src/main/resources/formatter-maven-plugin/eclipse/java.xml
- JavaScript ⊠https://github.com/revelc/formatter-maven-plugin/blob/formatter-maven-plugin-2.21.0/src/main/resources/formatter-maven-plugin/eclipse/javascript.xml
- JSON ⊠https://github.com/revelc/formatter-maven-plugin/blob/formatter-maven-plugin-2.21.0/src/main/resources/formatter-maven-plugin/jackson/json.properties
- XML ⊠https://github.com/revelc/formatter-maven-plugin/blob/formatter-maven-plugin-2.21.0/src/main/resources/formatter-maven-plugin/eclipse/xml.properties
- HTML ⊠https://github.com/revelc/formatter-maven-plugin/blob/formatter-maven-plugin-2.21.0/src/main/resources/formatter-maven-plugin/jsoup/html.properties
- CSS ⊠https://github.com/revelc/formatter-maven-plugin/blob/formatter-maven-plugin-2.21.0/src/main/resources/formatter-maven-plugin/ph-css/css.properties
ãããããããã以äžã®èšå®ã§ç¬èªã®ãã¡ã€ã«ãæå®ããããšãã§ããŸãã
- Java ⊠configFile
- JavaScript ⊠configJsFile
- JSON ⊠configJsonFile
- XML ⊠configXmlFile
- HTML ⊠configHtmlFile
- CSS ⊠configCssFile
ããšãã°ãGoogle Style Guideã§Javaã®Eclipseã®ãã©ãŒããããå ¬éãããŠããã®ã§ããã¡ããäŸã«ããŠã¿ãŸãããã
ãã¡ã€ã«ãååŸããŠ
$ curl -LO https://raw.githubusercontent.com/google/styleguide/gh-pages/eclipse-java-google-style.xml
以äžã®ããã«èšå®ããŸãã
<configuration> <configFile>${project.basedir}/eclipse-java-google-style.xml</configFile> </configuration>
ããã§ãæå®ãããã©ãŒããããé©çšãããããã«ãªããŸãã
ãã©ãŒããã察象ãšãããã£ã¬ã¯ããªãå€æŽãã
ããã¯ãdirectories
ã䜿ãã°ããããã§ãã
<configuration> <directories> <directory>${project.build.sourceDirectory}</directory> <directory>${project.build.directory}/generated-sources</directory> </directories> </configuration>
ãŸãšã
Formatter Maven Pluginãè©ŠããŠã¿ãŸããã
ãã£ããç°¡åã«äœ¿ããã®ã§äŸ¿å©ãªã®ã§ãããIDEã§ã®ä¿åæã«ãã©ãŒãããããŠããã®ããã£ã±ãè¯ããããªæ°ãããŸããâŠã
IntelliJã§ãœãŒã¹ã³ãŒããæžããŠãããšãEclipseã®ãã©ãŒããã¿ãŒèªäœã¯ã€ã³ããŒãå¯èœãªã®ã§ãããFormatter Maven Pluginã§validate
ããããããšè§£éãç°ãªããã©ãŒããããããŠããªããšæããããããŸããâŠã