Apache shardingsphere code formatting practice — spotless

Time:2022-5-23

Longtai, Apache shardingsphere contributor, GitHub 2.2k star hippo4j author, GitHub ID: Longtai CN.

Why code formatting? The meaning of code formatting is to make the code moreEasy to read, understand and modify

Shardingsphere, as the top open source project of Apache, has 380 + contributors so far. Because the code styles of most developers are inconsistent, it is not easy to guarantee the overall code format of the project under the GitHub multi person cooperation mode.

Based on the above demands, shardingsphere adoptsSpotlessAct as a unified code format.

What is spotless

Spotless is a code formatting tool that supports multiple languages. It supports Maven and gradle to build in the form of plugin.

For developers, there are two ways to use spotless: check whether the code has format problems, and format the code.

Shardingsphere uses Maven to build the project. Unless otherwise stated below, spotless uses Maven for demonstration.

How to use

The following code is the official example of spotless.

[email protected] repo % mvn spotless:check
[ERROR]  > The following files had format violations:
[ERROR]  src\main\java\com\diffplug\gradle\spotless\FormatExtension.java
[ERROR]    -\t\t····if·(targets.length·==·0)·{
[ERROR]    +\t\tif·(targets.length·==·0)·{
[ERROR]  Run 'mvn spotless:apply' to fix these violations.
[email protected] repo % mvn spotless:apply
[INFO] BUILD SUCCESS
[email protected] repo % mvn spotless:check
[INFO] BUILD SUCCESS

adoptmvn spotless:checkCheck the project code and find the error, then usemvn spotless:applyCode formatting; When checked again, the formatting error disappears.

1. Project practice

Shardingsphere uses spotless to addJava file licenseheaderandJava code formatting

Spotless has a variety of Java code formatting methods, such as Google javaformat, eclipse, prettier, etc. Based on the consideration of customization, eclipse is finally used for Java code formatting.

Apache shardingsphere code formatting practice -- spotless

1) Add headerlicense 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 that licenseheaderLeave a blank line at the end。 Otherwise, there will be no gap between the licenseheader and the package.

2) Add shardingsphere_ eclipse_ formatter. xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
/**
 * 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.
 */
-->
<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.indent_empty_lines" 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.format_javadoc_comments" value="false"/>
        <setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="false"/>
        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
        <setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="16"/>
        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
        <setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
        <setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
        <setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="16"/>
        <setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
        <setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
        <setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="160"/>
        <setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="10"/>
        <setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="106"/>
        <setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="106"/>
        <setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="106"/>
        <setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call.count_dependent" value="16|5|80"/>
    </profile>
</profiles>

Shardingsphere latest rules viewshardingsphere_eclipse_formatter.xml, provide another copyeclipse-java-google-style.xmlFor reference

shardingsphere_ eclipse_ formatter. The content of XML is customized and developed according to shardingsphere code specification, which can be changed flexibly.

3) Add maven

<plugin>
    <groupId>com.diffplug.spotless</groupId>
    <artifactId>spotless-maven-plugin</artifactId>
    <version>2.22.1</version>
    <configuration>
        <java>
            <eclipse>
                <file>${maven.multiModuleProjectDirectory}/src/resources/shardingsphere_eclipse_formatter.xml</file>
            </eclipse>
            <licenseHeader>
                <file>${maven.multiModuleProjectDirectory}/src/resources/license-header</file>
            </licenseHeader>
        </java>
    </configuration>
</plugin>

Spotless supports the functions of formatting specified directories and excluding specified directories. For details, refer toplugin-maven#java。 If it is not specified, when check or apply is executed, the default item is the full code.

4) Perform code formatting

After executing the above three steps, you can execute commands in the project to check whether the Java code conforms to the specification and the code formatting function.

[email protected] repo % mvn spotless:apply
[INFO] BUILD SUCCESS
[email protected] repo % mvn spotless:check
[INFO] BUILD SUCCESS

Maven 2. Life cycle binding

In the practical application of shardingsphere, choose to bind the spotlight application to the compile phase, so that the MVN install can be automatically formatted when executed locally.

<plugin>
    <groupId>com.diffplug.spotless</groupId>
    <artifactId>spotless-maven-plugin</artifactId>
    <version>2.22.1</version>
    <configuration>
        <java>
            <eclipse>
                <file>${maven.multiModuleProjectDirectory}/src/resources/shardingsphere_eclipse_formatter.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>

3. Idea formatting

If a developer wants to check whether a single file conforms to the specification in the process of writing code, execute itmvn spotless:checkormvn spotless:applyIt’s a little cumbersome because the formatting range defaults to the entire project.

We can use shardingsphere_ eclipse_ formatter. XML replaces the original formatting function of IntelliJ idea, so that it can be formatted at any time in the process of writing code, which greatly improves the development efficiency.

Idea version 2019.3.4.

1) Install the plug-in eclipse code formatter

Apache shardingsphere code formatting practice -- spotless

2) Select shardingsphere_ eclipse_ formatter. XML is the default format template

Apache shardingsphere code formatting practice -- spotless

Use the idea code formatting shortcut to complete the spotless code formatting.

common problem

1. Conflict between spotless and checkstyle

CheckstyleA tool (or set of tools) used to verify that source code conforms to Java standards or best practices.

In extreme scenarios, after spotless formats the code, the code will fail to pass the checkstyle check.

The root cause lies in the conflict between the check configuration and format configuration set by the two. For example, 16 spaces are indented into the newline after spotless formatting, while the newline check of checkstyle is 12 spaces.

private static Collection<PreciseHintShadowValue<Comparable<?>>> createNoteShadowValues(final ShadowDetermineCondition shadowDetermineCondition) {
    //Checkstyle can be in different formats
    return shadowDetermineCondition.getSqlComments().stream().<PreciseHintShadowValue<Comparable<?>>>map(
        each -> new PreciseHintShadowValue<>(tableName, shadowOperationType, each)).collect(Collectors.toList());
    //After spotless formatting
    return shadowDetermineCondition.getSqlComments().stream().<PreciseHintShadowValue<Comparable<?>>>map(
            each -> new PreciseHintShadowValue<>(tableName, shadowOperationType, each)).collect(Collectors.toList());
}

In this case, developers need to measure how to choose. There are two solutions: modify the formatting rules of spotless or modify the inspection rules of checkstyle.

2. Format conflict between CRLF and LF

reference resourceshttps://github.com/diffplug/s…

Conclusion

This paper introduces that Apache shardingsphere uses spotless to complete the formatting of historical code and the unification of subsequent code formats, which is of great help to the neatness of project code.

Of course, the function of spotless is not only the formatting of Java code, but also the formatting of file types such as POM and markdown. These will be applied in shardingsphere in the future.

Welcome to the link to learn more:

Apache shardingsphere official website:https://shardingsphere.apache.org/

Apache shardingsphere GitHub address:https://github.com/apache/shardingsphere

Sphereex official website:https://www.sphere-ex.com

Welcome to join the community manager wechat (ss_assistant_1) to communicate with many shardingsphere lovers.
Apache shardingsphere code formatting practice -- spotless