Eclipse jdt formatting Java code

目录

一、JDT

1、Eclipse jdt 格式化java代码

二、Eclipse JDT Java语法树

三、Eclipse中 插件 ASTVIEW安装

四、Java Model


一、JDT

JDT(java development tooling)是Eclipse提供的一组API。

Eclipse官方文档

Eclipse documentation

maven引入:org.eclipse.jdt.core>>3.29.0

<!-- https://mvnrepository.com/artifact/org.eclipse.jdt/org.eclipse.jdt.core -->
<dependency>
    <groupId>org.eclipse.jdt</groupId>
    <artifactId>org.eclipse.jdt.core</artifactId>
    <version>3.29.0</version>
</dependency>

引入jdt依赖要使用jdk11,否则会有异常java.lang.UnsupportedClassVersionError错误

java.lang.UnsupportedClassVersionError: org/eclipse/jface/text/IDocument has been 
compiled by a more recent version of the Java Runtime (class file version 55.0), 
this version of the Java Runtime only recognizes class file versions up to 52.0

原文链接:解决 org.eclipse.jface.text.Document class file version 61.0 报错_118路司机的博客-CSDN博客

解决 org.eclipse.jface.text.Document class file version 61.0 报错

问题描述

运行好好的项目,没有做任何改动,最近在编译时报以下错误

java.lang.UnsupportedClassVersionError: org/eclipse/jface/text/Document has been 
compiled by a more recent version of the Java Runtime (class file version 61.0), 
this version of the Java Runtime only recognizes class file versions up to 55.0

大概意思是org.eclipse.jface.text.Document是Java17编译的,而当前运行环境是Java11,这就奇怪了,工程的POM依赖也没变过,自己也没使用过Java17,怎么会引入Java17的类。

问题排查

首先找到这个jar包被依赖的地方

<dependency>
    <groupId>org.eclipse.jdt</groupId>
    <artifactId>org.eclipse.jdt.core</artifactId>
    <version>3.29.0</version>
</dependency>

再进去org.eclipse.jdt.core的pom查看,发现了org.eclipse.text的依赖版本是从 >= 3.6.0, < 4.0.0之间的一个最新版本

<dependency>
  <groupId>org.eclipse.platform</groupId>
  <artifactId>org.eclipse.core.resources</artifactId>
  <version>[3.14.0,4.0.0)</version>
</dependency>
<dependency>
  <groupId>org.eclipse.platform</groupId>
  <artifactId>org.eclipse.core.runtime</artifactId>
  <version>[3.13.0,4.0.0)</version>
</dependency>
<dependency>
  <groupId>org.eclipse.platform</groupId>
  <artifactId>org.eclipse.core.filesystem</artifactId>
  <version>[1.7.0,2.0.0)</version>
</dependency>
<dependency>
  <groupId>org.eclipse.platform</groupId>
  <artifactId>org.eclipse.text</artifactId>
  <version>[3.6.0,4.0.0)</version>
</dependency>

问题解决

知道了这个原因,限定使用Java11版本的相关组件就可以了:

<dependency>
    <groupId>org.eclipse.jdt</groupId>
    <artifactId>org.eclipse.jdt.core</artifactId>
    <version>${eclipse-jdt-core.version}</version>
    <exclusions>
        <exclusion>
           <groupId>org.eclipse.platform</groupId>
           <artifactId>*</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.eclipse.platform</groupId>
    <artifactId>org.eclipse.core.resources</artifactId>
    <version>3.18.200</version>
</dependency>
<dependency>
    <groupId>org.eclipse.platform</groupId>
    <artifactId>org.eclipse.core.runtime</artifactId>
    <version>3.26.100</version>
</dependency>
<dependency>
    <groupId>org.eclipse.platform</groupId>
    <artifactId>org.eclipse.core.filesystem</artifactId>
    <version>1.10.0</version>
</dependency>
<dependency>
    <groupId>org.eclipse.platform</groupId>
    <artifactId>org.eclipse.text</artifactId>
    <version>3.12.300</version>
</dependency>

1、Eclipse jdt 格式化java代码

import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.text.edits.TextEdit;

public class FormatterTest {

    public static void main(String[] args) {
        String code = "public class Test{public static void main(String[] args){System.out.println(\"Hello World\");}}";
        CodeFormatter codeFormatter = ToolFactory.createCodeFormatter(null);

        TextEdit textEdit = codeFormatter.format(CodeFormatter.K_COMPILATION_UNIT, code, 0, code.length(), 0, null);
        IDocument doc = new Document(code);
        try {
            textEdit.apply(doc);
            System.out.println(doc.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

  注意点:
  1. 被格式化的java代码必须保证无语法错误,否则不能正确格式化.

import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.text.edits.TextEdit;

import java.util.Map;

public class FormatterTest {

    public static void main(String[] args) {
        String code = "public class Test{public static void main(String[] args){System.out.println(\"Hello World\");}}";

        Map<String,String> m= DefaultCodeFormatterConstants.getEclipseDefaultSettings();
        m.put(JavaCore.COMPILER_COMPLIANCE,"1.8");
        m.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM,"1.8");
        m.put(JavaCore.COMPILER_SOURCE,"1.8");
        m.put(DefaultCodeFormatterConstants.FORMATTER_LINE_SPLIT,"120");
        m.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR,"tab");
        try {
            CodeFormatter codeFormatter = ToolFactory.createCodeFormatter(m);
            TextEdit textEdit = codeFormatter.format(CodeFormatter.K_COMPILATION_UNIT, code, 0, code.length(), 0, null);
            if (textEdit != null){
                IDocument doc = new Document(code);
                System.out.println(doc.get());
                System.out.println("===============start===============");
                textEdit.apply(doc);
                System.out.println(doc.get());
                System.out.println("===============end===============");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

二、Eclipse JDT Java语法树

Eclipse中的Eclipse JDT提供了一组访问和操作Java源代码的API,Eclipse AST是其中一个重要组成部分,它提供了AST、ASTParser、ASTNode、ASTVisitor等类,通过这些类可以获取、创建、访问和修改抽象语法树。

        ● ASTNode:AST节点类,所有的节点类型都是ASTNode的子类,至于某一个节点源代码具体到底是什么节点,可以通过ASTView来查看。

       ● ASTVisitor:AST访问者类,它针对不同类型的节点提供了一系列重载的visit()和endvisit()方法,意思就是访问到该类型的节点时执行visit()方法,访问完该类型节点后执行endvisit()方法。其中,visit()方法需返回boolean类型的返回值,表示是否继续访问子节点。另外ASTVisitor还提供了preVisit()和postVisit()方法,参数类型为ASTNode,也就是说不论哪种类型的节点,访问前后都要分别执行preVisit()和postVisit()。这些方法的具体实现由ASTVisitor的子类负责,如果不需要对所访问到的节点做处理,则无需在ASTVisitor的子类中覆盖这些方法。

       首先需要掌握如何将Java源代码转换为AST,即解析源代码。Eclipse AST提供了ASTParser类用于解析源代码,ASTParser有两种导入源代码的方式,一种是以Java Model的形式,另一种是以字符数组的形式。ASTParser的创建与使用如下:

ASTParser astParser = ASTParser.newParser(/*API Level*/);
astParser.setSource(/*Source Code*/);

      参数说明如下:

       ● API Level:Java编程规范(Java Language Specification,简写为JLS),此参数为常量,例如AST.JLS3。

       ● Source Code:方法setSource()针对不同形式的源代码作为参数而进行了重载,主要分类为字符数组形式(char[])和JavaModel形式(ICompilationUnit、IClassFile等)。

       如果传入的字符数组不是完整的一个Java文件,而是一个表达式或语句,又怎么办呢?可以按照以下代码对ASTParser进行设置:

astParser.setKind(/*Kind of Construct*/);

       其中Kind of Construct是所需解析的代码的类型,包括:

       ● K_COMPILATION_UNIT:编译单元,即一个Java文件

       ● K_CLASS_BODY_DECLARATIONS:类的声明

       ● K_EXPRESSION:单个表达式、例:new String(), 4+6 or i

       ● K_STATEMENTS:语句块、例:new String(); or synchronized (this) { ... }

      创建并设定好ASTParser后,便可以开始源代码与AST的转换,代码如下:

CompilationUnit result = (CompilationUnit) (astParser.createAST(null));

       createAST()方法的参数类型为IProgressMonitor,用于对AST的转换进行监控,不需要的话就填个null即可。本代码示例是以待解析的源代码为一完整的Java文件(对应一个编译单元Compilation Unit)为前提的,所以在转换为AST后直接强制类型转换为CompilationUnit。CompilationUnit是ASTNode的子类,指的就是整个Java文件,也是AST的根节点。

        下面是一个简单的工具类,用于将源代码以字符数组形式解析为AST,其中getCompilationUnit()方法的输入参数为需解析的Java源代码文件路径,返回值为该文件对应的CompilationUnit节点:

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
 
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;
 
public class JdtAstUtil {
	
    /**
    * get compilation unit of source code
    * 
    * @param javaFilePath 
    * @return CompilationUnit
    */
    public static CompilationUnit getCompilationUnit(String javaFilePath){
        byte[] input = null;
        try {
            BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(javaFilePath));
            input = new byte[bufferedInputStream.available()];
                bufferedInputStream.read(input);
                bufferedInputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        @SuppressWarnings("deprecation")
		ASTParser astParser = ASTParser.newParser(AST.JLS3);
        astParser.setSource(new String(input).toCharArray());
        astParser.setKind(ASTParser.K_COMPILATION_UNIT);
 
        CompilationUnit result = (CompilationUnit) (astParser.createAST(null));
        
        return result;
    }
}

示例,实现输出给定Java文件中所声明的类名、方法名和属性名:

import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
 
public class DemoVisitor extends ASTVisitor {
 
    @Override
    public boolean visit(FieldDeclaration node) {
        for (Object obj: node.fragments()) {
            VariableDeclarationFragment v = (VariableDeclarationFragment)obj;
            System.out.println("Field:\t" + v.getName());
        }
        
        return true;
    }
 
    @Override
    public boolean visit(MethodDeclaration node) {
        System.out.println("Method:\t" + node.getName());
        return true;
    }
 
    @Override
    public boolean visit(TypeDeclaration node) {
        System.out.println("Class:\t" + node.getName());
        return true;
    }
}

待处理的Java文件:

public class ClassDemo {
    
    private String text = "Hello World!";
    private String text2;
    
    public void print(int value) {
        System.out.println(value);
        System.out.println(text);
    }
    
    public void input(String value) {
        text2 = value;
        System.out.println(text2);
    }
}

测试类:

import org.eclipse.jdt.core.dom.CompilationUnit;

public class DemoVisitorTest {
    
    public DemoVisitorTest(String path) {
        CompilationUnit comp = JdtAstUtil.getCompilationUnit(path);
        
        DemoVisitor visitor = new DemoVisitor();
        comp.accept(visitor);
    }
    
    public static void main(String[] args) {
    	DemoVisitorTest demoVisitorTest = new DemoVisitorTest("C:\\workspace\\study\\src\\main\\java\\com\\lwz\\study\\ClassDemo.java");
	}
    
}

执行结果如下:

Class:	ClassDemo
Field:	text
Field:	text2
Method:	print
Method:	input

三、Eclipse中 插件 ASTVIEW安装

打开Eclipse,Help > Install New Software...

输入地址:JDT UI update site

如下图顺序点击下一步

 

 

 

 上图右下角下载插件操作,下载过程中需要点击同意等按钮。点击完继续下载最终完成安装。

完事,重启Eclipse。

Window -->Show View-->找到ASTVIEW

 

 上图2个小按钮,显示语法树,和定位到当前行代码等快捷键。

四、Java Model

不是你觉的悟到的东西给了你,你也接不住!

干我们这行,啥时候懈怠,就意味着长进的停止,长进的停止就意味着被淘汰,只能往前冲,直到凤凰涅槃的一天!

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杀神lwz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值