/*******************************************************************************
* Copyright (c) 2012 VMWare, Inc. All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 which accompanies this
* distribution, and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors: VMWare, Inc. - initial API and implementation
*******************************************************************************/
package org.grails.ide.eclipse.test.inferencing;
import org.codehaus.jdt.groovy.model.GroovyCompilationUnit;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.groovy.tests.search.AbstractInferencingTest;
import org.eclipse.jdt.groovy.search.TypeInferencingVisitorWithRequestor;
import org.eclipse.jdt.groovy.search.TypeLookupResult.TypeConfidence;
import org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner;
import org.eclipse.jdt.internal.core.JavaModelManager;
import org.grails.ide.eclipse.core.internal.plugins.GrailsCore;
import org.grails.ide.eclipse.core.internal.plugins.GrailsElementKind;
import org.grails.ide.eclipse.core.model.GrailsVersion;
import org.grails.ide.eclipse.editor.groovy.elements.GrailsProject;
import org.grails.ide.eclipse.editor.groovy.types.PerProjectServiceCache;
import org.grails.ide.eclipse.test.MockGrailsTestProjectUtils;
import org.grails.ide.eclipse.test.util.GrailsTest;
import org.grails.ide.eclipse.ui.internal.importfixes.GrailsProjectVersionFixer;
import org.springsource.ide.eclipse.commons.frameworks.core.ExceptionUtil;
import org.springsource.ide.eclipse.commons.frameworks.test.util.ACondition;
/**
* @author Andrew Eisenberg
* @author Nieraj Singh
* @created Feb 1, 2010
*/
public abstract class AbstractGrailsInferencingTests extends
AbstractInferencingTest {
private static final String DOMAIN_CLASS_SUFFIX = "\n}}";
private static final String DOMAIN_CLASS_PREFIX = "class Search {\nString dummyProp\ndef foo() {\n";
public AbstractGrailsInferencingTests(String name) {
super(name);
}
protected void assertDeclarationTypeInDomainClass(String contents,
String expectedType) throws JavaModelException {
assertDeclarationTypeInDomainClass(contents, 0, contents.length(),
expectedType);
}
protected void assertDeclarationTypeInDomainClass(String contents,
int exprStart, int exprEnd, String expectedDeclaringType)
throws JavaModelException {
GroovyCompilationUnit unit = createDomainClass("Search",
DOMAIN_CLASS_PREFIX + contents + DOMAIN_CLASS_SUFFIX);
unit.becomeWorkingCopy(null);
try {
TypeInferencingVisitorWithRequestor visitor = factory
.createVisitor(unit);
SearchRequestor requestor = new SearchRequestor(
DOMAIN_CLASS_PREFIX.length() + exprStart,
DOMAIN_CLASS_PREFIX.length() + exprEnd);
visitor.visitCompilationUnit(requestor);
assertNotNull("Did not find expected ASTNode", requestor.node);
if (!expectedDeclaringType.equals(requestor.getDeclaringTypeName())) {
fail(buildFailString(expectedDeclaringType, requestor));
}
} finally {
unit.discardWorkingCopy();
}
}
protected void assertDeclarationTypeInDomainClassNoPrefix(String contents,
int exprStart, int exprEnd, String expectedDeclaringType)
throws JavaModelException {
GroovyCompilationUnit unit = createDomainClass("Search", contents);
TypeInferencingVisitorWithRequestor visitor = factory
.createVisitor(unit);
SearchRequestor requestor = new SearchRequestor(exprStart, exprEnd);
visitor.visitCompilationUnit(requestor);
assertNotNull("Did not find expected ASTNode", requestor.node);
if (!expectedDeclaringType.equals(requestor.getDeclaringTypeName())) {
fail(buildFailString(expectedDeclaringType, requestor));
}
}
protected void assertTypeInBuildConfig(String contents, int exprStart,
int exprEnd, String expectedType) throws JavaModelException {
assertTypeInConfigClass(contents, expectedType, null,
GrailsElementKind.BUILD_CONFIG, exprStart, exprEnd);
}
protected void assertTypeInConfigClass(String contents,
String expectedType, TypeConfidence expectedConfidence,
GrailsElementKind configKind) throws JavaModelException {
assertTypeInConfigClass(contents, expectedType, expectedConfidence,
configKind, 0, contents.length());
}
protected void assertTypeInConfigClass(String contents,
String expectedType, TypeConfidence expectedConfidence,
GrailsElementKind configKind, int exprStart, int exprEnd)
throws JavaModelException {
GroovyCompilationUnit unit = createConfigClass("Search", contents,
configKind);
assertTypeInGrailsArtifact(exprStart, exprEnd, expectedType, unit,
expectedConfidence);
}
protected void assertTypeInControllerClass(String contents, int exprStart,
int exprEnd, String expectedType) throws JavaModelException {
GroovyCompilationUnit unit = createControllerClass("SearchController",
contents);
assertTypeInGrailsArtifact(exprStart, exprEnd, expectedType, unit, null);
}
protected void assertTypeInControllerClass(String contents,
String expectedType) throws JavaModelException {
assertTypeInControllerClass(contents, 0, contents.length(),
expectedType);
}
protected void assertTypeInDomainClass(String contents, String expectedType)
throws JavaModelException {
assertTypeInDomainClass(contents, 0, contents.length(), expectedType);
}
protected void assertTypeInDomainClass(String contents, int exprStart,
int exprEnd, String expectedType) throws JavaModelException {
GroovyCompilationUnit unit = createDomainClass("Search",
DOMAIN_CLASS_PREFIX + contents + DOMAIN_CLASS_SUFFIX);
assertTypeInGrailsArtifact(DOMAIN_CLASS_PREFIX.length() + exprStart,
DOMAIN_CLASS_PREFIX.length() + exprEnd, expectedType, unit,
null);
}
protected void assertTypeInDomainClassNoPrefix(String contents,
int exprStart, int exprEnd, String expectedType)
throws JavaModelException {
GroovyCompilationUnit unit = createDomainClass("Search", contents);
assertTypeInGrailsArtifact(exprStart, exprEnd, expectedType, unit, null);
}
protected void assertTypeInService(String contents, int exprStart,
int exprEnd, String expectedType) throws JavaModelException {
GroovyCompilationUnit unit = createServiceClass("Search", contents);
assertTypeInGrailsArtifact(exprStart, exprEnd, expectedType, unit, null);
}
protected void assertTypeInService(String contents, String expectedType)
throws JavaModelException {
assertTypeInService(contents, 0, contents.length(), expectedType);
}
protected void assertTypeInTagLib(String contents, int exprStart,
int exprEnd, String expectedType) throws JavaModelException {
GroovyCompilationUnit unit = createTagLib("Search", contents);
assertTypeInGrailsArtifact(exprStart, exprEnd, expectedType, unit, null);
}
protected void assertTypeInTagLib(String contents, String expectedType)
throws JavaModelException {
assertTypeInTagLib(contents, 0, contents.length(), expectedType);
}
protected String buildFailString(String expectedType,
SearchRequestor requestor) {
StringBuilder sb = new StringBuilder();
sb.append("Expected type not found.\n");
sb.append("Expected: " + expectedType + "\n");
sb.append("Found: " + printTypeName(requestor.result.type) + "\n");
sb.append("Declaring type: " + requestor.result.declaringType.getName()
+ "\n");
sb.append("ASTNode: " + requestor.node + "\n");
sb.append("Confidence: " + requestor.result.confidence + "\n");
return sb.toString();
}
protected void cleanUpElementKinds(GroovyCompilationUnit... units) {
for (GroovyCompilationUnit unit : units) {
GrailsProject.removeExtraGrailsElement(unit);
}
}
protected GroovyCompilationUnit createConfigClass(String name,
String contents, GrailsElementKind configKind) {
GroovyCompilationUnit unit = createUnit(name, contents);
GrailsProject.addExtraGrailsElement(unit, configKind);
return unit;
}
protected GroovyCompilationUnit createControllerClass(String name,
String contents) throws JavaModelException {
IPath root = env.addPackageFragmentRoot(project.getFullPath(),
"grails-app/controllers");
IPath path = env.addGroovyClassExtension(root, name, contents,
defaultFileExtension);
fullBuild(project.getFullPath());
GroovyCompilationUnit unit = (GroovyCompilationUnit) JavaCore
.createCompilationUnitFrom(env.getWorkspace().getRoot()
.getFile(path));
GrailsProject.addExtraGrailsElement(unit,
GrailsElementKind.CONTROLLER_CLASS);
return unit;
}
protected GroovyCompilationUnit createTestClass(String name, String contents)
throws JavaModelException {
IPath root = env.addPackageFragmentRoot(project.getFullPath(),
"test/unit");
IPath path = env.addGroovyClassExtension(root, name, contents,
defaultFileExtension);
fullBuild(project.getFullPath());
GroovyCompilationUnit unit = (GroovyCompilationUnit) JavaCore
.createCompilationUnitFrom(env.getWorkspace().getRoot()
.getFile(path));
GrailsProject.addExtraGrailsElement(unit, GrailsElementKind.UNIT_TEST);
return unit;
}
protected GroovyCompilationUnit createDomainClass(String name,
String contents) throws JavaModelException {
IPath root = env.addPackageFragmentRoot(project.getFullPath(),
"grails-app/domain");
IPath path = env.addGroovyClassExtension(root, name, contents,
defaultFileExtension);
fullBuild(project.getFullPath());
GroovyCompilationUnit unit = (GroovyCompilationUnit) JavaCore
.createCompilationUnitFrom(env.getWorkspace().getRoot()
.getFile(path));
GrailsProject.addExtraGrailsElement(unit,
GrailsElementKind.DOMAIN_CLASS);
return unit;
}
protected String createDomainText(String finderName, String... properties) {
return createDomainTextWithSuper(finderName, null, false, properties);
}
protected String createDomainTextWithSuper(String finderName,
String superClass, boolean isSuper, String... properties) {
StringBuilder sb = new StringBuilder();
sb.append("class ");
if (isSuper) {
sb.append("SearchSuper ");
} else {
sb.append("Search ");
}
if (superClass != null) {
sb.append(" extends " + superClass);
}
sb.append("{\n");
for (String property : properties) {
sb.append(" def " + property + "\n");
}
sb.append(" def method() {\n" + " " + finderName + "\n }\n" + "}");
return sb.toString();
}
protected GroovyCompilationUnit createServiceClass(String name,
String contents) throws JavaModelException {
IPath root = env.addPackageFragmentRoot(project.getFullPath(),
"grails-app/services");
IPath path = env.addGroovyClassExtension(root, name, contents,
defaultFileExtension);
fullBuild(project.getFullPath());
GroovyCompilationUnit unit = (GroovyCompilationUnit) JavaCore
.createCompilationUnitFrom(env.getWorkspace().getRoot()
.getFile(path));
GrailsProject.addExtraGrailsElement(unit,
GrailsElementKind.SERVICE_CLASS);
PerProjectServiceCache cache = GrailsCore.get().connect(project,
PerProjectServiceCache.class);
cache.addService(unit, name);
return unit;
}
protected GroovyCompilationUnit createTagLib(String name, String contents) {
GroovyCompilationUnit unit = createUnit(name, contents);
GrailsProject.addExtraGrailsElement(unit,
GrailsElementKind.TAGLIB_CLASS);
return unit;
}
private void assertTypeInGrailsArtifact(int exprStart, int exprEnd,
String expectedType, GroovyCompilationUnit unit,
TypeConfidence expectedConfidence) throws JavaModelException {
unit.becomeWorkingCopy(null);
TypeInferencingVisitorWithRequestor visitor = factory
.createVisitor(unit);
SearchRequestor requestor = new SearchRequestor(exprStart, exprEnd);
visitor.visitCompilationUnit(requestor);
assertNotNull("Did not find expected ASTNode", requestor.node);
String failString = buildFailString(expectedType, requestor);
if (!expectedType.equals(printTypeName(requestor.result.type))) {
fail(failString);
}
if (expectedConfidence != null) {
assertEquals("Type confidence problem.\n" + failString,
expectedConfidence, requestor.result.confidence);
}
unit.discardWorkingCopy();
}
private void superSetup() throws Exception {
super.setUp();
}
@Override
protected void setUp() throws Exception {
GrailsProjectVersionFixer.testMode();
// Map<String, String> e = System.getenv();
// for (String var : e.keySet()) {
// System.out.println(var + " = "+e.get(var));
// }
//Warning Race condtion: if the grails.test.util bundle is not activated yet then
// it will be activated by referencing the GrailsTest class but...
// unfortunately this may be after the expression GrailsVersion.MOST_RECENT was
// exeucted. In that case GrailsVersion.MOST_RECENT will not yey have been seet to
// to the correct value by GrailsTestUtilActivator!
// So solve this reference the class once
System.out.println(GrailsTest.class);
final GrailsVersion grailsVersion = GrailsVersion.MOST_RECENT;
GrailsTest.ensureDefaultGrailsVersion(grailsVersion);
final Job setupJob = new Job("grails test setup job") {
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
superSetup();
MockGrailsTestProjectUtils.mockGrailsProject(project, grailsVersion);
return Status.OK_STATUS;
} catch (Exception e) {
return new Status(IStatus.ERROR, "", "", e);
}
}
};
setupJob.setPriority(Job.SHORT);
setupJob.schedule();
new ACondition("Grails test setup") {
@Override
public boolean test() throws Exception {
return setupJob.getResult()!=null;
}
}.waitFor(10*60000); // Had to bump this up again for Grails 2.3 as takes much longer to create projects
// (maven downloading the internet)
assertJobOk(setupJob);
}
private void assertJobOk(Job job) throws CoreException {
IStatus status = job.getResult();
if (status==null) {
fail("Job not finished: "+job.getName());
} else {
if (!status.isOK()) {
throw ExceptionUtil.coreException(status);
}
}
}
@Override
protected void tearDown() throws Exception {
ICompilationUnit[] units = JavaModelManager.getJavaModelManager()
.getWorkingCopies(DefaultWorkingCopyOwner.PRIMARY, true);
if (units != null) {
for (int i = 0; i < units.length; i++) {
if (units[i] instanceof GroovyCompilationUnit) {
GrailsProject
.removeExtraGrailsElement((GroovyCompilationUnit) units[i]);
units[i].delete(true, null);
}
}
}
// remove the project from the testing environment so that it is not auto-deleted
// ((Hashtable) ReflectionUtils.getPrivateField(env.getClass(), "fProjects", env)).remove(project.getName());
super.tearDown();
}
protected void assertDynamicFinderType(boolean expectSuccess,
String finderName, String... properties) throws JavaModelException {
assertDynamicFinderType(finderName,
createDomainText(finderName, properties),
expectSuccess ? "Search" : "java.lang.Object");
}
protected void assertDynamicFinderTypeArray(String finderName,
String... properties) throws JavaModelException {
assertDynamicFinderType(finderName,
createDomainText(finderName, properties),
"java.util.List<Search>");
}
protected void assertDynamicFinderTypeInt(String finderName,
String... properties) throws JavaModelException {
assertDynamicFinderType(finderName,
createDomainText(finderName, properties), "java.lang.Integer");
}
protected void assertDynamicFinderType(String finderName, String contents,
String typeName) throws JavaModelException {
assertTypeInDomainClassNoPrefix(contents, contents.indexOf(finderName),
contents.indexOf(finderName) + finderName.length(), typeName);
}
protected void assertDynamicFinderTypeDeclaration(String finderName,
String... properties) throws JavaModelException {
String contents = createDomainText(finderName, properties);
assertDeclarationTypeInDomainClassNoPrefix(contents,
contents.indexOf(finderName), contents.indexOf(finderName)
+ finderName.length(), "Search");
}
}