有没有办法在Java中强制使用制表符而不是空格?

时间:2011-04-15 15:05:43

标签: java tabs whitespace static-analysis

CheckStyle提供检查空间的一致使用,但遗憾的是缺乏相反的想法:强制源代码使用选项卡。有没有办法添加此功能?它不一定是CheckStyle,也欢迎使用其他工具。

this question相同,但对于Java。

修改

我不需要代码美化,因为代码库的正常状态将是所有选项卡。我只需要一个可以报告备用缩进的工具。这样我就可以设置一个新的连续构建配置,当引入空格时它将失败。

7 个答案:

答案 0 :(得分:7)

首选使用空格而不是制表符缩进,因为它提供了所有编辑器/查看器的布局一致性。 但是如果您仍然想要它,您可以随时自定义检查checkstyle或自定义maven插件/ ant任务。 逻辑也不难实现 - 你必须检查任何一行上的前导空格是否大于标签长度。

编辑:包括一个蚂蚁示例。 自你发布以来它已经两周了,你仍然不开心,我有一些空闲时间:) 所以我为你准备了一个小蚂蚁自定义任务解决方案。

Ant任务

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());
            }
        }
    }

在ant build.xml中

  1. 首先编译任务
  2. 声明

    <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. 使用它

    <target name="rules.spaces">
        <detect-spaces
            failOnDetection="true">
            <fileset dir="${dir.src.java}">
                <include name="**/*.java"/>
            </fileset>
        </detect-spaces>
    </target>
    
  4. 编写maven / checkstyle插件也很困难。

答案 1 :(得分:6)

虽然Checkstyle没有内置检查,但您可以使用RegexpSinglelineJava检查强制执行仅限制表符缩进。请注意,这只会检查哪个字符用于缩进,而不是用于缩进的正确级别

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>

答案 2 :(得分:4)

这种方式比其他提出的方法简单得多。

在其他组下创建Regexp测试,然后设置

格式:^[ \t]*
消息:缩进必须是标签
非法模式:(已选中)

答案 3 :(得分:2)

使用此命令搜索前导空格:

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

然后翻转退出状态。

答案 4 :(得分:1)

Jalopy可能就是你想要的。它暂时没有更新,但它仍然可以工作。还有Triemax提供的商业版本。

答案 5 :(得分:0)

我们Java Formatter将直接执行此操作。 JavaFormatter prettyprints源文本(对于prettyprint的某些定义:-)和indents在逻辑上阻塞每个嵌套块的固定数量的空格(例如,indent = 3 [作为默认值])。

可以强制Java Formatter在左边距处使用TAB字符作为空格,并且它将使用TAB跳到与用户指定的制表位列号相对应的下一列。如果将制表位定义为与缩进距离具有相同的分隔,则每个缩进将获得一个制表符,只需格式化代码即可。如果您定义indent = 8,并且每8列(1,9,17,...)都有制表符,则您倾向于获得与许多编辑器一起使用的制表符,因为制表符的默认解释是“每8列”。

答案 6 :(得分:0)

在IntelliJ中,我让它在签入时执行标准格式的代码格式化。这样,您可以在输入时使用空格/制表符,但代码会定期更改为标准格式,并且在版本控制中始终是正确的(必须共享的地方)

如果没有IntelliJ,就必须有类似的东西,比如预先检查脚本。

在80年代使用制表符而不是空格是一个好主意,但你真的认为它在10年代很重要吗?这肯定不是关于磁盘空间的!