9
9
import java .io .IOException ;
10
10
import java .net .URI ;
11
11
import java .util .Collections ;
12
+ import java .util .regex .Pattern ;
12
13
import javax .tools .JavaCompiler ;
13
14
import javax .tools .JavaFileObject ;
14
15
import javax .tools .SimpleJavaFileObject ;
@@ -26,6 +27,16 @@ public class JavacParseUtil {
26
27
/** Creates a JavacParseUtil. */
27
28
public JavacParseUtil () {}
28
29
30
+ // Pattern to reject clearly invalid expressions before parsing
31
+ private static final Pattern EXPRESSION_GATE =
32
+ Pattern .compile (
33
+ "^(?!.*;)\\ s*"
34
+ + "(?!\\ [?\\ s*error\\ s+for\\ s+expression:)"
35
+ + "(?:(?!(?:final\\ s+)?(?:byte|short|int|long|float|double|boolean|char|var)\\ b.*=).)*"
36
+ + "(?:(?!(?:if|switch|for|while|do|try|catch|finally|return|throw|break|continue|class|interface|enum)\\ b).)*"
37
+ + ".+\\ S.*$" ,
38
+ Pattern .CASE_INSENSITIVE | Pattern .DOTALL );
39
+
29
40
/**
30
41
* Parses the given Java expression string and returns it as a {@link ExpressionTree} using the
31
42
* {@code javac} compiler API.
@@ -36,16 +47,13 @@ public JavacParseUtil() {}
36
47
* @throws RuntimeException if parsing fails or the expression cannot be found in the AST
37
48
*/
38
49
public static ExpressionTree parseExpression (String expressionSource ) {
39
- // This method works by embedding the expression in a dummy class and variable declaration, then
40
- // parsing the resulting source to extract the expression tree.
41
- //
42
- // For example, the input {@code "1 + 2"} is transformed into:
43
- // class Dummy { Object expression = 1 + 2; }
44
- //
45
- // The initializer of the {@code expression} field is then extracted and returned.
50
+ String sanitized = expressionSource .replaceAll ("#num(\\ d+)" , "\\ $num$1" ).trim ();
51
+
52
+ // Quick pre-check to skip obvious non-expressions
53
+ if (!EXPRESSION_GATE .matcher (sanitized ).matches ()) {
54
+ throw new RuntimeException ("Not a valid Java expression: " + expressionSource );
55
+ }
46
56
47
- // Embed the expression inside a dummy class and variable declaration.
48
- String sanitized = expressionSource .replaceAll ("#num(\\ d+)" , "\\ $num$1" );
49
57
String dummySource = "class Dummy { Object expression = " + sanitized + "; }" ;
50
58
51
59
// Obtain the system Java compiler.
0 commit comments