blob: 8c4374bd1f8bd5c8beb469411f83c90498a10e53 [file] [log] [blame]
/*
* Copyright 2015 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.TreeLogger;
import com.google.gwt.dev.javac.testing.impl.JavaResourceBase;
import com.google.gwt.dev.javac.testing.impl.MockJavaResource;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JProgram;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.thirdparty.guava.common.collect.HashMultimap;
import com.google.gwt.thirdparty.guava.common.collect.ImmutableSet;
import com.google.gwt.thirdparty.guava.common.collect.Multimap;
/**
* Test for {@link ImplicitUpcastAnalyzer}.
*/
public class ImplicitUpcastAnalyzerTest extends OptimizerTestBase {
// TODO(rluble): populate with unit tests for all upcast scenarios.
// Currently only upcasts due to overriding are tested here.
public void testOverrides() throws Exception {
final MockJavaResource A =
JavaResourceBase.createMockJavaResource("test.A",
"package test;",
"public class A {",
" public A m() { return new B(); } ",
"}");
final MockJavaResource I =
JavaResourceBase.createMockJavaResource("test.I",
"package test;",
"public interface I {",
" public A m(); ",
"}");
final MockJavaResource B =
JavaResourceBase.createMockJavaResource("test.B",
"package test;",
"public class B extends A implements I {",
" public A m() { return new B(); } ",
"}");
final MockJavaResource C =
JavaResourceBase.createMockJavaResource("test.C",
"package test;",
"public class C implements I {",
" public A m() { return new A(); } ",
"}");
addAll(A, I, B, C);
Result result = optimize("void", "new A().m(); new B().m();");
Multimap<JType, JType> upcastTypesByType = computeImplicitUpcasts(result.getOptimizedProgram());
JType classA = result.findClass("A");
JType classB = result.findClass("B");
assertMapsToAll(upcastTypesByType, classB, classA);
}
public void testTightening() throws Exception {
final MockJavaResource A =
JavaResourceBase.createMockJavaResource("test.A",
"package test;",
"public class A {",
" public A m() { return new B(); } ",
"}");
final MockJavaResource I =
JavaResourceBase.createMockJavaResource("test.I",
"package test;",
"public interface I {",
" public A m(); ",
"}");
final MockJavaResource B =
JavaResourceBase.createMockJavaResource("test.B",
"package test;",
"public class B extends A implements I {",
" public A m() { return new B(); } ",
"}");
final MockJavaResource C =
JavaResourceBase.createMockJavaResource("test.C",
"package test;",
"public class C implements I {",
" public A m() { return new A(); } ",
"}");
addAll(A, I, B, C);
// Variable a will be typed by a non null analysis type.
Result result = optimize("void", "A a = new A(); a = new B(); a.m();");
Multimap<JType, JType> upcastTypesByType = computeImplicitUpcasts(result.getOptimizedProgram());
JType classA = result.findClass("A");
JType classB = result.findClass("B");
assertMapsToAll(upcastTypesByType, classB, classA);
}
private void assertMapsToAll(Multimap<JType, JType> upcastTypesByType,
JType fromType, JType... toTypes) {
assertEquals(ImmutableSet.copyOf(toTypes), upcastTypesByType.get(fromType));
}
private Multimap<JType, JType> computeImplicitUpcasts(JProgram program) {
final Multimap<JType, JType> upcastTypesByType = HashMultimap.create();
ImplicitUpcastAnalyzer implicitUpcastAnalyzer = new ImplicitUpcastAnalyzer(program) {
@Override
protected void processImplicitUpcast(JType fromType, JType destType, SourceInfo info) {
upcastTypesByType.put(fromType.getUnderlyingType(), destType.getUnderlyingType());
}
};
implicitUpcastAnalyzer.accept(program);
return upcastTypesByType;
}
@Override
protected boolean doOptimizeMethod(TreeLogger logger, JProgram program, JMethod method) {
program.addEntryMethod(findMainMethod(program));
TypeTightener.exec(program);
return false;
}
}