/* * Copyright 2008 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gwt.dev.jjs.impl; import com.google.gwt.core.ext.UnableToCompleteException; import com.google.gwt.dev.javac.testing.impl.MockJavaResource; import com.google.gwt.dev.jjs.ast.JMethod; import com.google.gwt.dev.jjs.ast.JMethodBody; import com.google.gwt.dev.jjs.ast.JProgram; import com.google.gwt.dev.jjs.ast.JReturnStatement; /** * Tests {@link ExpressionAnalyzer}. */ public class ExpressionAnalyzerTest extends JJSTestBase { private static class Result { private final ExpressionAnalyzer ea; private boolean accessesField; private boolean accessesFieldNonFinal; private boolean accessesLocal; private boolean accessesParameter; private boolean canThrowException; private boolean createsObject; private boolean hasAssignment; private boolean hasAssignmentToField; private boolean hasAssignmentToLocal; private boolean hasAssignmentToParameter; public Result(ExpressionAnalyzer ea) { this.ea = ea; } public Result accessesField() { accessesField = true; return this; } public Result accessesFieldNonFinal() { accessesField = true; accessesFieldNonFinal = true; return this; } public Result accessesLocal() { accessesLocal = true; return this; } public Result accessesParameter() { accessesParameter = true; return this; } public Result canThrowException() { canThrowException = true; return this; } public Result createsObject() { createsObject = true; return this; } public Result hasAssignment() { hasAssignment = true; return this; } public Result hasAssignmentToField() { hasAssignment = true; hasAssignmentToField = true; return this; } public Result hasAssignmentToLocal() { hasAssignment = true; hasAssignmentToLocal = true; return this; } public Result hasAssignmentToParameter() { hasAssignment = true; hasAssignmentToParameter = true; return this; } public void check() { assertEquals(accessesField, ea.accessesField()); assertEquals(accessesFieldNonFinal, ea.accessesFieldNonFinal()); assertEquals(accessesLocal, ea.accessesLocal()); assertEquals(accessesParameter, ea.accessesParameter()); assertEquals(canThrowException, ea.canThrowException()); assertEquals(createsObject, ea.createsObject()); assertEquals(hasAssignment, ea.hasAssignment()); assertEquals(hasAssignmentToField, ea.hasAssignmentToField()); assertEquals(hasAssignmentToLocal, ea.hasAssignmentToLocal()); assertEquals(hasAssignmentToParameter, ea.hasAssignmentToParameter()); } } public void testEmpty() throws Exception { analyzeExpression("int", "0").check(); } public void testFieldAccessClinit() throws Exception { sourceOracle.addOrReplace(new MockJavaResource("test.Foo") { @Override public CharSequence getContent() { StringBuffer code = new StringBuffer(); code.append("package test;\n"); code.append("public class Foo {\n"); code.append(" static final boolean value = trueMethod();"); code.append(" static boolean trueMethod() { return true; }"); code.append("}\n"); return code; } }); analyzeExpression("boolean", "Foo.value").accessesFieldNonFinal().canThrowException().createsObject().hasAssignmentToField().check(); } public void testFieldAccessInstance() throws Exception { sourceOracle.addOrReplace(new MockJavaResource("test.Foo") { @Override public CharSequence getContent() { StringBuffer code = new StringBuffer(); code.append("package test;\n"); code.append("import com.google.gwt.core.client.JavaScriptObject;\n"); code.append("public class Foo {\n"); code.append(" public final boolean BOOL_CONST = true;\n"); code.append(" public boolean FOO = true;\n"); code.append("}\n"); return code; } }); addSnippetImport("test.Foo"); addSnippetClassDecl("static final Foo f = new Foo();"); analyzeExpression("boolean", "f.BOOL_CONST").accessesField().canThrowException().check(); analyzeExpression("boolean", "f.FOO").accessesFieldNonFinal().canThrowException().check(); analyzeExpression("boolean", "f.FOO = false").accessesFieldNonFinal().canThrowException().hasAssignment().hasAssignmentToField().check(); } public void testFieldAccessStatic() throws Exception { addSnippetClassDecl("static boolean trueMethod() { return true; }"); addSnippetClassDecl("static final boolean BOOL_CONST = trueMethod();"); addSnippetClassDecl("static volatile boolean FOO;"); analyzeExpression("boolean", "BOOL_CONST").accessesField().check(); analyzeExpression("boolean", "FOO").accessesFieldNonFinal().check(); analyzeExpression("boolean", "FOO = false").accessesFieldNonFinal().hasAssignmentToField().check(); } private Result analyzeExpression(String type, String expression) throws UnableToCompleteException { JProgram program = compileSnippet(type, "return " + expression + ";"); ExpressionAnalyzer ea = new ExpressionAnalyzer(); JMethod mainMethod = findMainMethod(program); JMethodBody body = (JMethodBody) mainMethod.getBody(); JReturnStatement returnStmt = (JReturnStatement) body.getStatements().get(0); ea.accept(returnStmt.getExpr()); return new Result(ea); } }