Project: ShardingSphere (App Definition and Development / Database)
File: 2022_06_08_How_does_Apache_ShardingSphere_standardize_and_format_code_We_use_Spotless.en.md

+++ title = "How does Apache ShardingSphere standardize and format code? We use Spotless" weight = 59 chapter = true +++ Why do we need to format code? Simply put, its to make code easier to read, understand, and modify. As a Top-Level Apache open source project, has 400 contributors as of today. Since most developers do not have the same coding style, it is not easy to standardize the projects overall code format in a GitHub open collaboration model. To solve this issue, ShardingSphere uses to unify code formatting. Spotless is a multi-lingual code formatting tool that supports and building with plugin. Devs can use Spotless in two ways: reviewing code for format-related issues, and formatting code. The ShardingSphere community uses Maven to build its projects and Spotless uses Maven for its demos. Lets check the official demo below: ``` user@machine repo % mvn spotless:check [ERROR] > The following files had format violations: [ERROR] src\main\java\com\diffplug\gradle\spotless\FormatExtension.java [ERROR] -\t\tif(targets.length==0){ [ERROR] +\t\tif(targets.length==0){ [ERROR] Run 'mvn spotless:apply' to fix these violations. user@machine repo % mvn spotless:apply [INFO] BUILD SUCCESS user@machine repo % mvn spotless:check [INFO] BUILD SUCCESS ``` When you check the project code with `mvn spotless:check`an error occurs, then you format the code with `mvn spotless:apply`. And once you check it again, the formatting error has magically disappeared. Preparing your environment ShardingSphere uses Spotless to adding Java file `licenseHeader` and formatting Java code. Spotless has several Java code formatting methods, such as: `googleJavaFormat`, `eclipse`, `prettier` etc. For customization reasons, we chose `eclipse` for Java code formatting. ``` a) Add `licenseHeader` according to project requirements /* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ ``` Note: remember to include a space at the end of the `licenseHeader`. Otherwise there will be no space between the `licenseHeader` and the package. b) Add `shardingsphereeclipseformatter.xml` ```xml ?xml version="1.0" encoding="UTF-8" standalone="no"?> <profiles version="13"> <profile kind="CodeFormatterProfile" name="'ShardingSphere Apache Current'" version="13"> <setting id="org.eclipse.jdt.core.compiler.source" value="1.8"/> <setting id="org.eclipse.jdt.core.compiler.compliance" value="1.8"/> <setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.8"/> <setting id="org.eclipse.jdt.core.formatter.indentemptylines" value="true"/> <setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/> <setting id="org.eclipse.jdt.core.formatter.lineSplit" value="200"/> <setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="200"/> <setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/> <setting id="org.eclipse.jdt.core.formatter.indentation.size" value="1"/> <setting id="org.eclipse.jdt.core.formatter.comment.formatjavadoccomments" value="false"/> <setting id="org.eclipse.jdt.core.formatter.joinwrappedlines" value="false"/> <setting id="org.eclipse.jdt.core.formatter.insertspacebeforecolonin_conditional" value="insert"/> <setting id="org.eclipse.jdt.core.formatter.insertspacebeforecolonin_default" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignmentforenum_constants" value="16"/> <setting id="org.eclipse.jdt.core.formatter.insertspacebeforecoloninlabeledstatement" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.insertspacebeforecolonin_case" value="do not insert"/> <setting id="org.eclipse.jdt.core.formatter.alignmentforconditional_expression" value="80"/> <setting id="org.eclipse.jdt.core.formatter.alignmentforassignment" value="16"/> <setting id="org.eclipse.jdt.core.formatter.blanklinesafter_package" value="1"/> <setting id="org.eclipse.jdt.core.formatter.continuationindentationforarrayinitializer" value="2"/> <setting id="org.eclipse.jdt.core.formatter.alignmentforresourcesintry" value="160"/> <setting id="org.eclipse.jdt.core.formatter.alignmentforthrowsclauseinmethoddeclaration" value="10"/> <setting

value="106"/> <setting id="org.eclipse.jdt.core.formatter.alignmentforparametersinconstructor_declaration" value="106"/> <setting id="org.eclipse.jdt.core.formatter.alignmentforthrowsclauseinconstructordeclaration" value="106"/> <setting id="org.eclipse.jdt.core.formatter.alignmentforargumentsinexplicitconstructorcall.count_dependent" value="16|5|80"/> </profile> </profiles> ``` For latest rules of ShardingSphere, see ``. For references, check the `` file. The content of `shardingsphereeclipseformatter.xml` is tailor-made in accordance with the ShardingSphere code specification and can be changed flexibly. c) Add Maven plugin ```xml <plugin> <groupId>com.diffplug.spotless</groupId> <artifactId>spotless-maven-plugin</artifactId> <version>2.22.1</version> <configuration> <java> <eclipse> <file>${maven.multiModuleProjectDirectory}/src/resources/shardingsphereeclipseformatter.xml</file> </eclipse> <licenseHeader> <file>${maven.multiModuleProjectDirectory}/src/resources/license-header</file> </licenseHeader> </java> </configuration> </plugin> ``` Spotless supports specified formatting directories and the exclusion of specified directories. For further information, see `plugin-maven#java`. If not specified, when check or apply is executed, all of the project code will be affected by default. d) Execute code formatting After performing the above three steps, you can execute commands in your project to check the Java code for compliance with the specification, as well as the code formatting features. ``` user@machine repo % mvn spotless:apply [INFO] BUILD SUCCESS user@machine repo % mvn spotless:check [INFO] BUILD SUCCESS ``` In the actual ShardingSphere application, you can opt to bind Spotless apply to the compile phase so that it is automatically formatted when mvn install is executed locally. ```xml <plugin> <groupId>com.diffplug.spotless</groupId> <artifactId>spotless-maven-plugin</artifactId> <version>2.22.1</version> <configuration> <java> <eclipse> <file>${maven.multiModuleProjectDirectory}/src/resources/shardingsphereeclipseformatter.xml</file> </eclipse> <licenseHeader> <file>${maven.multiModuleProjectDirectory}/src/resources/license-header</file> </licenseHeader> </java> </configuration> <executions> <execution> <goals> <goal>apply</goal> </goals> <phase>compile</phase> </execution> </executions> </plugin> ``` If you want to check a single file for compliance when writing code, executing `mvn spotless:check` or `mvn spotless:apply` will be a bit unwieldy, as by default the formatting scope is the entire project. IntelliJ IDEAs native formatting functionality can be replaced by shardingsphereeclipseformatter.xml. This way, you can format your code at any time during the writing process, improving efficiency significantly. IDEA Version: 2019.3.4 a) Install the plugin Eclipse Code Formatter b) Select shardingsphereeclipseformatter.xml as the default formatting template Spotless code formatting can be done using IDEA code formatting shortcuts. Conflicts between Spotless and Checkstyle is a tool for checking Java source code for compliance with code standards or a set of validation rules (best practices). In extreme circumstances, Spotless formatted code cannot pass Checkstyle checking. The underlying cause is a conflict between the checking mechanism and formatting configurations set by both. For example, Spotless formats a newline with a 16-space indent, while Checkstyle checks for a 12-space newline. ```java private static Collection<PreciseHintShadowValue<Comparable<?>>> createNoteShadowValues(final ShadowDetermineCondition shadowDetermineCondition) { // format that can pass Checkstyle return shadowDetermineCondition.getSqlComments().stream().<PreciseHintShadowValue<Comparable<?>>>map( each -> new PreciseHintShadowValue<>(tableName, shadowOperationType, each)).collect(Collectors.toList()); // After being formatted by Spotless return shadowDetermineCondition.getSqlComments().stream().<PreciseHintShadowValue<Comparable<?>>>map( each -> new PreciseHintShadowValue<>(tableName, shadowOperationType, each)).collect(Collectors.toList()); } ``` This case requires devs to weigh the trade-offs. There are two solutions: modify Spotless formatting rules, or modify Checkstyles checking rules. Formatting conflict between CRLF & LF See Apache ShardingSphere uses Spotless to format legacy code, and the subsequent standardization of code formatting, which helps keeping the projects code tidy. Of course, Spotless is not limited to Java code formatting, but also includes the formatting of file types such as `Pom` and `Markdown`, which will soon be applied in ShardingSphere. Longtai : longtai-cn Contributor; hippo4j author (2.2K GitHub stars).