Eclipse JDT ASTParser - Issue with MethodVisitor

2019-07-06 12:00发布

I am writing some code to parse java source code. I am experimenting with Eclipse JDT AST Parser. My code is given below. (Parsing code). I am testing the parser against a Mailer application that I wrote in Java (second code snippet). My parser is visiting all methods except the generateEmail() and the debug() methods. I have looked all over the place but I am not able to understand for the life of me why its happening. Can anyone tell me what I am doing wrong? Is it a memory issue? I am not getting any OutOfMemoryException

I want to visit the specific methods with the MethodVisitor method to get access to statements and variables in a particular method.

My Parsing code

public class RuleEngine {

public static void parse(String file) {
    File java = new File(file);
    ASTParser parser = ASTParser.newParser(AST.JLS3);
    String code = readFile(java);
    parser.setSource(code.toCharArray());
    parser.setKind(ASTParser.K_COMPILATION_UNIT);
    final CompilationUnit cu = (CompilationUnit) parser.createAST(null);


    cu.accept(new ASTVisitor() {

        public boolean visit(ImportDeclaration id) {
            Name imp = id.getName();
            debug("import", id.getName().getFullyQualifiedName());
            return false;
        }

        public boolean visit(VariableDeclarationFragment node) {
            SimpleName name = node.getName();
            debug("var.declaration", (name.getFullyQualifiedName() + ":" + cu.getLineNumber(name.getStartPosition())));
            return false; // do not continue 
        }

        public boolean visit(MethodDeclaration method) {
            debug("method", method.getName().getFullyQualifiedName());
            debug("method.return", method.getReturnType2().toString());
            List<SingleVariableDeclaration> params = method.parameters();

            for(SingleVariableDeclaration param: params) {
                debug("param", param.getName().getFullyQualifiedName());
            }

            Block methodBlock = method.getBody();
            String myblock = methodBlock.toString();
            methodVisitor(myblock);
            return false;
        }


    });

}

public static void methodVisitor(String content) {
    debug("entering met visitor", "1");
    ASTParser metparse = ASTParser.newParser(AST.JLS3);
    metparse.setSource(content.toCharArray());
    metparse.setKind(ASTParser.K_STATEMENTS);
    Block block = (Block) metparse.createAST(null);

    block.accept(new ASTVisitor() {
        public boolean visit(VariableDeclarationFragment var) {
            debug("met.var", var.getName().getFullyQualifiedName());
            return false;
        }

        public boolean visit(SimpleName node) {
            debug("SimpleName node", node.getFullyQualifiedName());
            return false;
        }
        public boolean visit(IfStatement myif) {
            debug("if.statement", myif.toString());
            return false;
        }

    });
}

public static void debug(String ref, String message) {
    System.out.println(ref +": " + message);
}

public static void main(String[]args) {
    parse("MailerDaemon.java");
}

This is my MailerDaemon Code

public boolean isBccMode() {
    return bccMode;
}

public void setBccMode(boolean bccMode) {
    this.bccMode = bccMode;
}

public void setServerPort(String serverPortAddr) {
    String[] elems = serverPortAddr.split("\\:");
    this.setServerAddr(elems[0]);
    this.setSmtpPort(elems[1]);
}

public String getServerAddr() {
    int i = 0;
    return serverAddr;
}
public void setServerAddr(String serverAddr) {
    this.serverAddr = serverAddr;
}
public boolean isSslOn() {
    return isSslOn;
}
public void setSslOn(boolean isSslOn) {
    this.isSslOn = isSslOn;
}
public String getSmtpPort() {
    return smtpPort;
}
public void setSmtpPort(String smtpPort) {
    this.smtpPort = smtpPort;
}
public String getFromEmail() {
    return fromEmail;
}
public void setFromEmail(String fromEmail) {
    this.fromEmail = fromEmail;
}
public String getToEmails() {
    return toEmails;
}
public void setToEmails(String toEmails) {
    this.toEmails = toEmails;
}
public String getUsername() {
    return username;
}
public void setUsername(String username) {
    this.username = username;
}
public String getPassword() {
    return password;
}
public void setPassword(String password) {
    this.password = password;
}
public String getSubject() {
    return subject;
}
public void setSubject(String subject) {
    this.subject = subject;
}
public String getMessage() {
    return message;
}
public void setMessage(String message) {
    this.message = message;
}
public String getCcList() {
    return ccList;
}
public void setCcList(String ccList) {
    this.ccList = ccList;
}
public String getBccList() {
    return bccList;
}
public void setBccList(String bccList) {
    this.bccList = bccList;
}



public String getFile() {
    return file;
}
public void setFile(String file) {
    debug("filename: " + file);
    this.file = file;
}
public void generateEmail() {
    Properties props = new Properties();
    props.put("mail.smtp.auth", "true");
    props.put("mail.smtp.port", this.getSmtpPort());
    if(isSslOn()) {
        props.put("mail.smtp.socketFactory.port", this.getSmtpPort());
        props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
    }
    props.put("mail.smtp.host", getServerAddr());

    Session session = Session.getDefaultInstance(props, new Authenticator() {
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication(getUsername(), getPassword());
        }
    });


    Message msg = new MimeMessage(session);
    try {
        msg.setFrom(new InternetAddress(this.getFromEmail()));
        if (getToEmails() != null) {
            msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(getToEmails()));
        } else if (isBccMode()) {
            msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(getFromEmail()));
        }

        //msg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(getCcList()));
        msg.setSubject(getSubject());
        //msg.setText(getMessage());
        MimeBodyPart messagePart = new MimeBodyPart();
        messagePart.setText(getMessage());

        /*
        MimeBodyPart attachments = new MimeBodyPart();
        FileDataSource fd = new FileDataSource(getFile());
        attachments.setDataHandler(new DataHandler(fd));
        attachments.setFileName(fd.getName());
        */

        Multipart mp = new MimeMultipart();
        mp.addBodyPart(messagePart);
        //mp.addBodyPart(attachments);

        msg.setContent(mp);
        Transport.send(msg);
        debug("Done. Closing Session...");

    } catch (AddressException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (MessagingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

private static void debug(String message) {
    System.out.println("[DEBUG]: " + message);
}

2条回答
趁早两清
2楼-- · 2019-07-06 12:36

I see no evident problem with your parsing code. I hope its failing somewhere when its trying to parse the generateEmail() method. Since the parser follows a sequential approach, the debug() method is also not getting parsed. Try to enclose the statements within the public boolean visit(MethodDeclaration method) in a try-catch block with probably a Throwable clause.

Also have a check for your readFile() method. One issue that is mostly seen while reading a file is missing to append new line character to each line. Not appending a new line results in erroneous construction of the code, especially when there are comments in the code. You may inspect compilationUnit.getProblems() method to check any such problems.

查看更多
forever°为你锁心
3楼-- · 2019-07-06 12:39

@UnniKris - Thank you for your response. I changed the readFile() method and included a \n after the newline was written to the StringBuilder. This worked. All my methods were successfully parsed.

My code snippet for the readFile() method is posted here:

public static String readFile(File file) {
    StringBuilder sb = new StringBuilder();
    try {
        Scanner scan = new Scanner(file);

        while(scan.hasNext()) {
            sb.append(scan.nextLine()+"\n"); //added the new line feed here
        }
        scan.close();
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    String fullcode = sb.toString();
    //debug("full.code", fullcode);
    return fullcode;

}
查看更多
登录 后发表回答