/*
* Copyright 2009-2017 the original author or authors.
*
* 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 org.codehaus.groovy.eclipse.codeassist.factories;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.codehaus.groovy.eclipse.codeassist.GroovyContentAssist;
import org.codehaus.groovy.eclipse.codeassist.processors.GroovyCompletionProposal;
import org.codehaus.groovy.eclipse.codeassist.processors.IGroovyCompletionProcessor;
import org.codehaus.groovy.eclipse.codeassist.processors.TypeCompletionProcessor;
import org.codehaus.groovy.eclipse.codeassist.requestor.ContentAssistContext;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.IAnnotation;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.groovy.core.util.ReflectionUtils;
import org.eclipse.jdt.internal.core.BinaryType;
import org.eclipse.jdt.internal.core.SearchableEnvironment;
import org.eclipse.jdt.internal.ui.text.java.LazyJavaCompletionProposal;
import org.eclipse.jdt.internal.ui.text.java.LazyJavaTypeCompletionProposal;
import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
/**
* Groovy annotation declarations that are annotated with {@literal @}AnnotationCollector
* are transformed into classes. So binary types that have this annotation need some help
* to show up as completion proposals.
*/
public class AnnotationCollectorTypeCompletionProcessorFactory implements IGroovyCompletionProcessorFactory {
public IGroovyCompletionProcessor createProcessor(ContentAssistContext context,
final JavaContentAssistInvocationContext javaContext, SearchableEnvironment nameEnvironment) {
return new TypeCompletionProcessor(context, javaContext, nameEnvironment) {
@Override
public List<ICompletionProposal> generateProposals(IProgressMonitor monitor) {
List<ICompletionProposal> proposals = super.generateProposals(monitor);
if ((monitor != null && monitor.isCanceled()) || proposals.isEmpty()) {
return Collections.EMPTY_LIST;
}
// remove types that are not annotated with the AnnotationCollector transform
for (Iterator<ICompletionProposal> it = proposals.iterator(); it.hasNext();) {
ICompletionProposal proposal = it.next();
if (!isAnnotationCollectorType(proposal)) {
it.remove();
} else {
// change the displayed icon from 'C' to '@'
GroovyCompletionProposal gcp = (GroovyCompletionProposal) ReflectionUtils
.getPrivateField(LazyJavaCompletionProposal.class, "fProposal", proposal);
gcp.setFlags(gcp.getFlags() | 0x00002000 /*aka Modifier.ANNOTATION*/);
}
}
return proposals;
}
@Override
protected int getSearchFor() {
return IJavaSearchConstants.CLASS;
}
protected boolean isAnnotationCollectorType(ICompletionProposal proposal) {
if (proposal instanceof LazyJavaTypeCompletionProposal) {
LazyJavaTypeCompletionProposal p = (LazyJavaTypeCompletionProposal) proposal;
try {
IType t = javaContext.getCompilationUnit().getJavaProject().findType(p.getQualifiedTypeName());
if (t instanceof BinaryType) {
for (IAnnotation a : ((BinaryType) t).getAnnotations()) {
if (a.getElementName().equals("groovy.transform.AnnotationCollector")) {
return true;
}
}
}
} catch (JavaModelException e) {
GroovyContentAssist.logError("Failed to check for @AnnotationCollector in: " + p.getQualifiedTypeName(), e);
}
}
return false;
}
};
}
}