简体   繁体   中英

Is there a way to enforce using tabs instead of spaces in Java?

CheckStyle offers to check for consistent use of spaces, but sadly lacks the opposite idea: Force source code to use tabs. Is there some way to add this functionality? It does not have to be CheckStyle, other tools are welcome as well.

Same as this question but for Java.

EDIT

I don't need a code beautifier, since the normal state of the codebase will be all tabs. I just need a tool which can report the presence of alternate indentation. That way I can set up a new continuous build configuration which will fail when spaces are introduced.

Although Checkstyle has no builtin check for this, you can enforce tabs-only indentation using the RegexpSinglelineJava check. Note that this only checks which character is used for indentation, not for the correct level of indentation.

Shamelessly stolen from the Hibernate OGM source :

<module name="RegexpSinglelineJava">
    <property name="format" value="^\t* +\t*\S"/>
    <property name="message" value="Line has leading space characters; indentation should be performed with tabs only."/>
    <property name="ignoreComments" value="true"/>
</module>

Using spaces instead of tabs to indent is preferred because it offers consistency of layout across all editors/viewers. But if you still want it, you can always make your own custom check for checkstyle or a custom maven plugin /ant task. Logic shouldnt be difficult to implement either - all you have to check whether leading space on any line is greater than the tab length.

Edit: including an ant example. Its two weeks now since you posted and you're still not happy, and I had some free time :) So I cooked up a little ant custom task solution for you.

The Ant task

public class SpaceDetectorTask extends Task {
    public static final String REGEX = "^[ ]+";
    public static final Pattern p = Pattern.compile(REGEX);

    private FileSet fileSet;
    private boolean failOnDetection;

    // Usual getters/setters

    public void addFileSet(FileSet fileSet) {
        this.fileSet = fileSet;
    }

    public void execute() {
        DirectoryScanner ds = fileSet.getDirectoryScanner();
        String[] files = ds.getIncludedFiles();
        for (int x = 0; x <= files.length -1; x++) {
            process(ds.getBasedir(), files[x]);
        }
    }

    public void process(File dir, String file) {
        try {
            BufferedReader reader = new BufferedReader(new FileReader(new File(dir, file)));
            String line;
            int linecount = 0;
            System.out.println("File: " + file);
            boolean ignore = false;
            while((line = reader.readLine()) != null) {
                linecount++;

                // exclude comment blocks
                if (line.contains("/**") || line.contains("*/")) {
                    ignore = !ignore;
                    continue;
                }

                if (!ignore) {
                    if (p.matcher(line).find()) {
                        int spcCount = line.length() - (line.replaceAll(REGEX, "")).length();
                        if (spcCount >= 4) { // break whenever 4 leading spaces are detected. Configure as you need.
                            String msg = "File: "+ file + " is using spaces as indentation.";
                            if (failOnDetection) {
                                throw new BuildException(msg);
                            } else {
                                getProject().log(msg);
                            }
                        }
                    }
                    reader.close();
                }
            }
        } catch (IOException e) {
            if (failOnDetection) {
                throw new BuildException(e);
            } else {
                getProject().log("File: " + file + "\n" + e.getMessage());
            }
        }
    }

In ant build.xml

  1. Compile the task first
  2. Declare it

     <taskdef name="detect-spaces" classname="com.blah.blah.build.tools.SpaceDetectorTask"> <classpath> <pathelement path="${dir.classes}"/> <fileset dir="C:/apache-ant-1.7.1/lib"> <include name="**/*.jar"/> </fileset> </classpath> </taskdef> 
  3. use it

     <target name="rules.spaces"> <detect-spaces failOnDetection="true"> <fileset dir="${dir.src.java}"> <include name="**/*.java"/> </fileset> </detect-spaces> </target> 

Writing up a maven/checkstyle plugin shoulnt be difficult either.

This way is a lot simpler than other proposed methods.

Create a Regexp test under Miscellaneous group, and set

Format : ^[ \\t]*
Message : Indentations must be tabs
Illegal Pattern : (checked)

Search for a leading space using this command:

grep -e "^\t* " `find . -name *.java`

Then flip the exit status.

Jalopy might be what your looking for. It hasn't been updated for a while but it should still work. There is also a commercial version available from Triemax .

Our Java Formatter will do this directly. The JavaFormatter prettyprints source text (for some definition of prettyprint :-) and indents blocks logically a fixed number of spaces per nested block (eg, indent=3 [as a default]).

It is possible to force the Java Formatter to use TAB characters at the left margin for white space, and it will use a TAB to skip to the the next column that corresponds to a user-specificed supply of tab stop column numbers. If you define tab stops to have the same separation as the indent distance, you will get one tab character per indent, just by formatting the code. If you define indent=8, with tab stops every 8 columns (1,9,17,...) you tend to get tabs that work with many editors, as the default interpretation of tabs is "every 8 columns".

In IntelliJ, I have it perform a code formatting to the standard format on check in. That way you can have spaces/tabs as you enter, but the code is changed to the standard format periodically and is always correct in version control (where it must be shared)

There must be something similar you can do without IntelliJ like a pre-check in script.

Using tabs instead of spaces was a good idea in the 80's but do you really think it matters in the 10's? This can't be about disk space surely!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM