15

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.

Community
  • 1
  • 1
Craig P. Motlin
  • 26,452
  • 17
  • 99
  • 126
  • 1
    Do you have a specific editor in mind, or are you looking for a solution based on checking SVN commits, or what? – jprete Apr 15 '11 at 15:07
  • My editor already does this, but I receive patches that don't conform. I already use CheckStyle to report on other style issues. I'd like something similar that can be run independently or as part of a build. – Craig P. Motlin Apr 15 '11 at 15:08
  • 1
    this is when you realize how great a language like Google's *"Go lang"* is. No more *spaces-vs-tab*, no more *two-or-four-spaces-indent*, no more *bracket-are-beter-on-next-line* "discussions" (more like religious beliefs but hey ;), no more *source-in-UTF-8-not-compatible-with-source-in-Latin-1* etc. The code formatting is defined by the language's specs and there's a code formatter generating the only correct formatting. Such a spec makes questions like yours irrelevant for Go. How shiny is that? Not that it helps you but at least it's cool seeing a better picture ;) – SyntaxT3rr0r Apr 15 '11 at 15:14
  • 1
    Can you please state what does _'enforce'_ mean? Is it mere _detection_ of non-conformant leading whitespace or also _fixing_ it to be conformant? – 9000 Apr 25 '11 at 15:18
  • It's not just tabs instead of spaces which is a good practice. In fact, using tabs after the initial indentation from the left is evil. If the user adjusts their tab setting, it will screw up the document like nobody's business. Tabs should only be used from the left. – Chris Dennett May 01 '11 at 03:26
  • @Chris the issue is not when you use more than one tab but when you use tabs to lineup code instead of just indenting... or when you are anal about the am length of your line. – Sled Apr 01 '13 at 19:19
  • 1
    Tab up to the current scope then use space from there. – Chris Dennett Apr 01 '13 at 20:56

7 Answers7

10

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>
Ben Blank
  • 54,908
  • 28
  • 127
  • 156
7

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.

d-live
  • 7,926
  • 3
  • 22
  • 16
  • 1
    "Using spaces instead of tabs to indent is preferred because it offers consistency of layout across all editors/viewers." Without igniting the tabs vs spaces religious war, I would like to point out that this is just an **opinion** – kurczynski Aug 07 '18 at 18:18
4

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)

lyomi
  • 4,230
  • 6
  • 30
  • 39
2

Search for a leading space using this command:

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

Then flip the exit status.

Craig P. Motlin
  • 26,452
  • 17
  • 99
  • 126
1

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.

Tim R
  • 814
  • 1
  • 5
  • 7
0

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 (e.g., 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".

Ira Baxter
  • 93,541
  • 22
  • 172
  • 341
  • 2
    Looks nice, but is a commercial :-| , windows-only :-( solution. If I'm going to use an extra tool anyway, why not just use the free Source Formatter included with Eclipse, which you can [even use on the command line](http://blogs.operationaldynamics.com/andrew/software/java-gnome/eclipse-code-format-from-command-line.html)? – Sean Patrick Floyd Apr 26 '11 at 12:57
0

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!

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 1
    I've written why tabs should be used whenever working in a team here: http://motlin.com/2010/tabs-vs-spaces/ – Craig P. Motlin May 01 '11 at 14:21
  • Given that spaces are preferred to tab in the Java Code Convention. Personally, I would prefer to stick to the 4 space per indent convention which is inforced in the IDE. i.e. it turn tabs into spaces and re-arranges code as required. I wouldn't suggest anyone use vim for Java development. I think you are trying very hard to prevent a relatively minor problem. I would be concerned that you don't enough to do if this is so important to you. ;) – Peter Lawrey May 01 '11 at 16:52
  • 1
    That's simply not true. See section 4 of the Java Code Convention. "Four spaces should be used as the unit of indentation. The exact construction of the indentation (spaces vs. tabs) is unspecified. Tabs must be set exactly every 8 spaces (not 4)." Look at the source code of ArrayList, it uses a mix of tabs and spaces where it's assumed that tabs represent 8 spaces. It's a bizarre and awful system that nobody uses except for Sun/Oracle. I wouldn't look to them for advice here. http://www.oracle.com/technetwork/java/codeconventions-136091.html#262 – Craig P. Motlin May 01 '11 at 22:54
  • @Craig, I would agree using a mix of spaces and tab is bizarre, however you appear to assume that tabs only is the only sensible/logical conclusion. I wouldn't agree with such an assumption. You also appear to place more importance on this opinion than is really merited. I would agree, you need to have a convention for your project, and you should stick to it. – Peter Lawrey May 02 '11 at 07:05