Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在读取java源文件时查找变量的类型_Java_Parsing - Fatal编程技术网

如何在读取java源文件时查找变量的类型

如何在读取java源文件时查找变量的类型,java,parsing,Java,Parsing,假设我有一个java源文件(source.java),如下所示 1 package demo; 2 3 public class Source { 4 5 public static void main(String[] args) { 6 7 String sample = "foo bar"; 8 9 System.out.println(sample.length()); 10 11 } 12 } 现在,我想编写一个java代码,逐

假设我有一个java源文件(
source.java
),如下所示

1  package demo;
2
3  public class Source {
4
5   public static void main(String[] args) {
6
7       String sample = "foo bar";
8       
9       System.out.println(sample.length());
10
11     }
12  }
现在,我想编写一个java代码,逐行读取这个源文件,当它在第9行遇到
sample
变量时,它会告诉我sample变量属于哪个类(即
java.lang.String
)。我该怎么做? 我已经看到了下面的链接,它不适合我,因为它在同一个源文件中打印类型名


要读取独立的java源文件,您必须从头开始,逐行读取,按照java语法解析文件中的每个单词,。。。太多的工作要做。或者我推荐

读取原始Java源文件并将其解析为可以检索信息的Java对象

这是您的问题的示例代码:

public String getSampleVariableType() throws Exception {
    // Use the raw text of file as input
    // `CompilationUnit` contains all information of your Java file.
    CompilationUnit compilationUnit = JavaParser.parse("package demo;\n" +
            "\n" +
            "public class Source {\n" +
            "    public static void main(String[] args) {\n" +
            "        String sample = \"foo bar\"; \n" +
            "        System.out.println(sample.length());\n" +
            "    }\n" +
            "}");

    // Find class by name
    ClassOrInterfaceDeclaration clazz = compilationUnit.getClassByName("Source")
                                                       .orElse(null);
    if (clazz == null) 
        throw new ClassNotFoundException();

    // Find method by name
    List<MethodDeclaration> methods = clazz.getMethodsByName("main");
    if (methods.size() == 0) 
        throw new MethodNotFoundException();

    // Get the content of method's body
    MethodDeclaration method = methods.get(0);
    BlockStmt block = method.getBody().orElse(null);
    if (block == null) 
        throw new MethodEmptyException();

    // Statement `String sample = "foo bar";` is a VariableDeclaration.
    // Find all VariableDeclaration in current method, filter as you want
    // and get its class type by using `getType()` method
    return block.findAll(VariableDeclarator.class).stream()
            .filter(v -> v.getName().asString().equals("sample"))
            .map(v -> v.getType().asString())
            .findFirst().orElse(null);
}

要读取独立的java源文件,您必须从头开始,逐行读取,按照java语法解析文件中的每个单词,。。。太多的工作要做。或者我推荐

读取原始Java源文件并将其解析为可以检索信息的Java对象

这是您的问题的示例代码:

public String getSampleVariableType() throws Exception {
    // Use the raw text of file as input
    // `CompilationUnit` contains all information of your Java file.
    CompilationUnit compilationUnit = JavaParser.parse("package demo;\n" +
            "\n" +
            "public class Source {\n" +
            "    public static void main(String[] args) {\n" +
            "        String sample = \"foo bar\"; \n" +
            "        System.out.println(sample.length());\n" +
            "    }\n" +
            "}");

    // Find class by name
    ClassOrInterfaceDeclaration clazz = compilationUnit.getClassByName("Source")
                                                       .orElse(null);
    if (clazz == null) 
        throw new ClassNotFoundException();

    // Find method by name
    List<MethodDeclaration> methods = clazz.getMethodsByName("main");
    if (methods.size() == 0) 
        throw new MethodNotFoundException();

    // Get the content of method's body
    MethodDeclaration method = methods.get(0);
    BlockStmt block = method.getBody().orElse(null);
    if (block == null) 
        throw new MethodEmptyException();

    // Statement `String sample = "foo bar";` is a VariableDeclaration.
    // Find all VariableDeclaration in current method, filter as you want
    // and get its class type by using `getType()` method
    return block.findAll(VariableDeclarator.class).stream()
            .filter(v -> v.getName().asString().equals("sample"))
            .map(v -> v.getType().asString())
            .findFirst().orElse(null);
}
这里有一个尝试用regex解析它的不完整(一些TODO项)实现,我们可以先用#luckfininscope()来尝试,如果失败,然后用复杂的源代码来尝试复杂的方法

package com.mytest.core.share;

import java.io.File;
import java.io.FileInputStream;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.IOUtils;

public class TestParse {
    public static void main(String[] args) throws Exception {
        //testHit();
        testNotHit();
    }

    public static void testNotHit() throws Exception {
        // input position
        int position = 511;
        String id = "sample";
        parse(position, id);
    }

    public static void testHit() throws Exception {
        // input position
        int position = 955;
        String id = "sample";
        parse(position, id);
    }

    public static void parse(int position, String id) throws Exception {
        int end = position;
        FileInputStream fs = new FileInputStream(new File("TestFile.java"));
        String source = IOUtils.toString(fs, "UTF-8");
        source = source.substring(0, end);
        System.out.println("### look from" +source);
        // remove all String in source code;
        source = removeStringInSource(source);
        int start = 0;
        int stack = 0;// for nested scope
        boolean hit = false;
        // find the char '{' from the end of source
        for (int i = source.length(); i > 0; i--) {
            String current = source.substring(i - 1, i);
            if (stack == 0) {
                if (current.equals("{")) {
                    start = i;// lookup from start to end;
                    System.err.println("from this {, start to search from the location at " + i);
                    hit = findInScope(source, id, start, end);
                    end = start; // skip, search next scope;
                    if (hit) {
                        break;
                    } else {
                        continue;
                    }
                }
            }
            // skip bracket pair {}
            if (current.equals("}")) {
                stack++;
                end = i;// skip it;
            }
            if (current.equals("{")) {
                stack--;
                end = i;// skip it;
            }
        }
        if (hit == false) {
            // TODO: find the type in the class members and super class members
        }

        // TODO: find full class name in the java.lang.* or in the header of the source
        // of import section.

    }

    private static boolean findInScope(String source, String id, int start, int end) {
        String regex = "[A-Za-z0-9_$]+\\s+" + id;
        String text = source.substring(start, end);
        Matcher matcher = Pattern.compile(regex).matcher(text);
        boolean result = matcher.find();
        if (result) {
            hitString = matcher.group();
            System.err.println("hitString = " + hitString + " ,in the text scope: " + text);

        }
        return result;
    }

    private static boolean luckFindInScope(String source, String id) {
        String regex = "[A-Za-z0-9_$]+\\s+" + id;
        Matcher matcher = Pattern.compile(regex).matcher(source);
        int count = 0;
        while (matcher.find()) {
            count++;
            hitString= matcher.group();
        }
        return count == 1;
    }

    private static String hitString = "";

    // fill star * in the string value
    private static String removeStringInSource(String input) {
        Matcher matcher = Pattern.compile("\".*?\"").matcher(input);
        String match = "";
        while(matcher.find()) {
            match = matcher.group();
            char[] symbols = new char[match.length()];
            Arrays.fill(symbols, '*');
            input = input.replace(match, new String(symbols));
        }
        System.out.println("$$ removed: " + input);
        return input;
    }
}
它的源代码更复杂,如下所示:

package com.mytest.test.parse;

public class TestFile {
    public static void main(String[] args) {
        String sample = "foo bar";
        System.out.println(sample.length());
    }

    public static String sample = null;

    public static void test1() {
        if (sample != null) {
            {
                String sample = "foo bar";
                System.out.println(sample);
                {
                    sample = "foo bar";
                    System.out.println(sample);
                }
            }
            {
                System.out.println(sample);
                int test = 0;
                {
                    if (test >= 0) {
                        sample = "foo bar";
                        System.out.println(sample);
                        String sample = "foo bar";
                        System.out.println(sample);
                    }

                }
            }
            if(sample.equals("foo bar")) {
                System.out.println(sample);
            }
        }

        if( sample == null) {
            String sample = "foo bar";
            if(sample.equals("foo bar")) {
                System.out.println(sample);
            }
        }
    }

    public static void test2{
        if( sample == null) {
            String sample = "foo bar";
            if(sample.equals("foo bar")) {
                System.out.println(sample);
            }
        }
    }
}
这里有一个尝试用regex解析它的不完整(一些TODO项)实现,我们可以先用#luckfininscope()来尝试,如果失败,然后用复杂的源代码来尝试复杂的方法

package com.mytest.core.share;

import java.io.File;
import java.io.FileInputStream;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.IOUtils;

public class TestParse {
    public static void main(String[] args) throws Exception {
        //testHit();
        testNotHit();
    }

    public static void testNotHit() throws Exception {
        // input position
        int position = 511;
        String id = "sample";
        parse(position, id);
    }

    public static void testHit() throws Exception {
        // input position
        int position = 955;
        String id = "sample";
        parse(position, id);
    }

    public static void parse(int position, String id) throws Exception {
        int end = position;
        FileInputStream fs = new FileInputStream(new File("TestFile.java"));
        String source = IOUtils.toString(fs, "UTF-8");
        source = source.substring(0, end);
        System.out.println("### look from" +source);
        // remove all String in source code;
        source = removeStringInSource(source);
        int start = 0;
        int stack = 0;// for nested scope
        boolean hit = false;
        // find the char '{' from the end of source
        for (int i = source.length(); i > 0; i--) {
            String current = source.substring(i - 1, i);
            if (stack == 0) {
                if (current.equals("{")) {
                    start = i;// lookup from start to end;
                    System.err.println("from this {, start to search from the location at " + i);
                    hit = findInScope(source, id, start, end);
                    end = start; // skip, search next scope;
                    if (hit) {
                        break;
                    } else {
                        continue;
                    }
                }
            }
            // skip bracket pair {}
            if (current.equals("}")) {
                stack++;
                end = i;// skip it;
            }
            if (current.equals("{")) {
                stack--;
                end = i;// skip it;
            }
        }
        if (hit == false) {
            // TODO: find the type in the class members and super class members
        }

        // TODO: find full class name in the java.lang.* or in the header of the source
        // of import section.

    }

    private static boolean findInScope(String source, String id, int start, int end) {
        String regex = "[A-Za-z0-9_$]+\\s+" + id;
        String text = source.substring(start, end);
        Matcher matcher = Pattern.compile(regex).matcher(text);
        boolean result = matcher.find();
        if (result) {
            hitString = matcher.group();
            System.err.println("hitString = " + hitString + " ,in the text scope: " + text);

        }
        return result;
    }

    private static boolean luckFindInScope(String source, String id) {
        String regex = "[A-Za-z0-9_$]+\\s+" + id;
        Matcher matcher = Pattern.compile(regex).matcher(source);
        int count = 0;
        while (matcher.find()) {
            count++;
            hitString= matcher.group();
        }
        return count == 1;
    }

    private static String hitString = "";

    // fill star * in the string value
    private static String removeStringInSource(String input) {
        Matcher matcher = Pattern.compile("\".*?\"").matcher(input);
        String match = "";
        while(matcher.find()) {
            match = matcher.group();
            char[] symbols = new char[match.length()];
            Arrays.fill(symbols, '*');
            input = input.replace(match, new String(symbols));
        }
        System.out.println("$$ removed: " + input);
        return input;
    }
}
它的源代码更复杂,如下所示:

package com.mytest.test.parse;

public class TestFile {
    public static void main(String[] args) {
        String sample = "foo bar";
        System.out.println(sample.length());
    }

    public static String sample = null;

    public static void test1() {
        if (sample != null) {
            {
                String sample = "foo bar";
                System.out.println(sample);
                {
                    sample = "foo bar";
                    System.out.println(sample);
                }
            }
            {
                System.out.println(sample);
                int test = 0;
                {
                    if (test >= 0) {
                        sample = "foo bar";
                        System.out.println(sample);
                        String sample = "foo bar";
                        System.out.println(sample);
                    }

                }
            }
            if(sample.equals("foo bar")) {
                System.out.println(sample);
            }
        }

        if( sample == null) {
            String sample = "foo bar";
            if(sample.equals("foo bar")) {
                System.out.println(sample);
            }
        }
    }

    public static void test2{
        if( sample == null) {
            String sample = "foo bar";
            if(sample.equals("foo bar")) {
                System.out.println(sample);
            }
        }
    }
}

如果我理解您的问题,您要求将原始文本解析为代码。这不是一个小问题——您是否尝试过编写代码来实现这一点?如果是这样的话,请把它贴在你遇到麻烦的地方。你真的需要把java源代码当作原始文本吗?如果您愿意不支持局部变量,我将使用反射来实现这一点,这要简单得多。请看这里:您需要确定变量在代码中声明的位置,然后提取其类型的名称,然后计算该名称所指的类型。总而言之,绝对不是小事。当然,您可以使用编译器API,但我甚至不能说这使它特别容易。@ggorlen我还没有尝试过任何东西。我正在考虑解决办法。如果我在实现它时遇到麻烦,我会发布一些东西。@MarDev是的,我需要将java源代码视为原始文本,反射对我不起作用:(如果我理解你的问题,你是在要求将原始文本解析为代码。这不是一个小问题——你是否尝试过编写任何代码来实现这一点?如果是,请将其与遇到问题的区域一起发布。你真的需要将java源代码视为原始文本吗?如果你没有打开,我会对此使用反射,更简单o不支持局部变量。请参见此处:您需要确定变量在代码中声明的位置,然后提取其类型的名称,然后确定该名称所指的类型。总之,这绝对不是一件小事。当然,您可以使用编译器API,但我甚至不认为这使它特别容易。@ggorlen我没有尝试过任何东西。正在考虑解决方案。如果我在实现它时遇到问题,我会发布一些东西。@MarDev是的,我需要将java源代码视为原始文本,反射对我不起作用:(这看起来很有希望。我现在将在我的计算机上运行此代码。如果它解决了我提到的问题,我将接受它作为答案。这看起来很有希望。我现在将在我的计算机上运行此代码。如果它解决了我提到的问题,我将接受它作为答案。