/******************************************************************************* * Copyright (c) 2012, 2013 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.springframework.ide.eclipse.quickfix.jdt.computers; import java.rmi.activation.Activator; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.core.IAnnotation; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IMemberValuePair; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.internal.core.AnnotatableInfo; import org.eclipse.jdt.internal.core.SourceField; import org.eclipse.jdt.internal.core.SourceMethod; import org.eclipse.jdt.internal.core.SourceRefElement; import org.eclipse.jdt.internal.core.SourceType; import org.eclipse.jdt.internal.ui.text.java.JavaCompletionProposalComputer; import org.eclipse.jdt.ui.text.java.ContentAssistInvocationContext; import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.text.source.SourceViewer; import org.springsource.ide.eclipse.commons.core.SpringCoreUtils; import org.springsource.ide.eclipse.commons.core.StatusHandler; /** * @author Terry Denney * @author Martin Lippert * @since 2.6 */ public class AnnotationArgumentProposalComputer extends JavaCompletionProposalComputer { // TODO: clean up code and make sure non attribute arguments are handled // better @Override public List<ICompletionProposal> computeCompletionProposals(ContentAssistInvocationContext context, IProgressMonitor monitor) { if (context instanceof JavaContentAssistInvocationContext) { JavaContentAssistInvocationContext javaContext = (JavaContentAssistInvocationContext) context; // check if project is a spring project if (SpringCoreUtils.isSpringProject(javaContext.getProject().getProject())) { ICompilationUnit cu = javaContext.getCompilationUnit(); try { List<ICompletionProposal> proposals = new ArrayList<ICompletionProposal>(); int invocationOffset = context.getInvocationOffset(); IJavaElement element = cu.getElementAt(invocationOffset); cu.makeConsistent(monitor); // check for type/method/field specific annotation // proposal computers if (element instanceof SourceRefElement && ((SourceRefElement) element).getElementInfo() instanceof AnnotatableInfo) { SourceRefElement sourceRefElement = (SourceRefElement) element; IAnnotation[] annotations = sourceRefElement.getAnnotations(); for (IAnnotation annotation : annotations) { String annotationName = annotation.getElementName(); if (javaContext.getViewer() instanceof SourceViewer) { // SourceViewer sourceViewer = (SourceViewer) // javaContext.getViewer(); // AssistContext assistContext = new // AssistContext(cu, sourceViewer, // invocationOffset, 0); if (annotation instanceof SourceRefElement) { if (isWithinRange((SourceRefElement) annotation, invocationOffset)) { IMemberValuePair[] memberValuePairs = annotation.getMemberValuePairs(); for (IMemberValuePair memberValuePair : memberValuePairs) { String attributeName = memberValuePair.getMemberName(); proposals.addAll(computeCompletionProposals(annotationName, attributeName, memberValuePair.getValue(), annotation, element, javaContext)); } } // ASTNode node = ((SourceRefElement) // annotation).findNode(assistContext.getASTRoot()); // // if (node instanceof NormalAnnotation) { // NormalAnnotation normalAnnotation = // (NormalAnnotation) node; // @SuppressWarnings("unchecked") // List<MemberValuePair> pairs = // normalAnnotation.values(); // // for (MemberValuePair pair : pairs) { // Expression value = pair.getValue(); // if (value != null) { // if (isWithinRange(value, // invocationOffset)) { // String attributeName = // pair.getName().getIdentifier(); // proposals.addAll(computeCompletionProposals(annotationName, // attributeName, value, normalAnnotation, // element, // javaContext)); // } // // } // } // } // else if (node instanceof // SingleMemberAnnotation) { // SingleMemberAnnotation // singleMemberAnnotation = // (SingleMemberAnnotation) node; // Expression value = // singleMemberAnnotation.getValue(); // if (isWithinRange(value, // invocationOffset)) { // proposals.addAll(computeCompletionProposals(annotationName, // null, value, // singleMemberAnnotation, element, // javaContext)); // } // } } } } } if (proposals.size() > 0) { return proposals; } // check for remaining registered proposal computers for (JavaCompletionProposalComputer computer : AnnotationComputerRegistry.computers) { List<ICompletionProposal> completionProposals = computer.computeCompletionProposals(context, monitor); if (completionProposals != null) { proposals.addAll(completionProposals); } } return proposals; } catch (JavaModelException e) { //Something went wrong obtaining java model infos. This could be for any number of reasons (including bad // code in user's workspace. Don't log this! (or 'aer' will report it back to us as a 'bug') //Activator.StatusHandler.log(new Status); } } } return Collections.emptyList(); } // private boolean isWithinRange(Expression value, int invocationOffset) { // int startPosition = value.getStartPosition(); // int length = value.getLength(); // return startPosition < invocationOffset && startPosition + length >= // invocationOffset; // } // private boolean isWithinRange(SourceRefElement element, int invocationOffset) throws JavaModelException { int startPosition = element.getSourceRange().getOffset(); int length = element.getSourceRange().getLength(); return startPosition < invocationOffset && startPosition + length >= invocationOffset; } // private List<ICompletionProposal> computeCompletionProposals(String // annotationName, String attributeName, // Expression value, Annotation annotation, IJavaElement element, // JavaContentAssistInvocationContext javaContext) throws JavaModelException // { // List<ICompletionProposal> proposals = new // ArrayList<ICompletionProposal>(); // // if (attributeName == null) { // attributeName = AnnotationComputerRegistry.DEFAULT_ATTRIBUTE_NAME; // } // // if (value instanceof StringLiteral) { // StringLiteral stringLiteral = (StringLiteral) value; // // proposals.addAll(computeCompletionProposalsHelper(element, // AnnotationComputerRegistry.getProposalComputer(annotationName, // attributeName), stringLiteral, // javaContext, annotation)); // } // // else if (value instanceof ArrayInitializer) { // ArrayInitializer arrayInit = (ArrayInitializer) value; // // @SuppressWarnings("unchecked") // List<Expression> expressions = arrayInit.expressions(); // // Set<AnnotationProposalComputer> computers = AnnotationComputerRegistry // .getProposalComputerForArrayAttribute(annotationName); // for (Expression expression : expressions) { // if (expression instanceof StringLiteral) { // proposals.addAll(computeCompletionProposalsHelper(element, computers, // (StringLiteral) expression, // javaContext, annotation)); // } // } // } // return proposals; // } private List<ICompletionProposal> computeCompletionProposals(String annotationName, String attributeName, Object value, IAnnotation annotation, IJavaElement element, JavaContentAssistInvocationContext javaContext) throws JavaModelException { List<ICompletionProposal> proposals = new ArrayList<ICompletionProposal>(); if (attributeName == null) { attributeName = AnnotationComputerRegistry.DEFAULT_ATTRIBUTE_NAME; } if (value instanceof String) { proposals.addAll(computeCompletionProposalsHelper(element, AnnotationComputerRegistry.getProposalComputer(annotationName, attributeName), (String) value, javaContext, annotation)); } else if (value instanceof Object[]) { Object[] values = (Object[]) value; for (Object v : values) { if (v instanceof String) { proposals.addAll(computeCompletionProposalsHelper(element, AnnotationComputerRegistry .getProposalComputerForArrayAttribute(annotationName, attributeName), (String) v, javaContext, annotation)); } } } // else if (value instanceof ArrayInitializer) { // ArrayInitializer arrayInit = (ArrayInitializer) value; // // @SuppressWarnings("unchecked") // List<Expression> expressions = arrayInit.expressions(); // // Set<AnnotationProposalComputer> computers = // AnnotationComputerRegistry // .getProposalComputerForArrayAttribute(annotationName); // for (Expression expression : expressions) { // if (expression instanceof StringLiteral) { // // TODO // // proposals.addAll(computeCompletionProposalsHelper(element, // // computers, (StringLiteral) expression, // // javaContext, annotation)); // } // } // } return proposals; } // private List<ICompletionProposal> // computeCompletionProposalsHelper(IJavaElement element, // Set<AnnotationProposalComputer> computers, StringLiteral stringLiteral, // JavaContentAssistInvocationContext javaContext, Annotation annotation) // throws JavaModelException { // List<ICompletionProposal> proposals = new // ArrayList<ICompletionProposal>(); // // for (AnnotationProposalComputer computer : computers) { // if (element instanceof SourceField) { // proposals.addAll(computer.computeCompletionProposals((SourceField) // element, // getLocationInformation(stringLiteral, javaContext), annotation, // javaContext)); // } // if (element instanceof SourceMethod) { // proposals.addAll(computer.computeCompletionProposals((SourceMethod) // element, // getLocationInformation(stringLiteral, javaContext), annotation, // javaContext)); // } // if (element instanceof SourceType) { // proposals.addAll(computer.computeCompletionProposals((SourceType) // element, // getLocationInformation(stringLiteral, javaContext), annotation, // javaContext)); // } // } // // return proposals; // } // private List<ICompletionProposal> computeCompletionProposalsHelper(IJavaElement element, Set<AnnotationProposalComputer> computers, String value, JavaContentAssistInvocationContext javaContext, IAnnotation annotation) throws JavaModelException { List<ICompletionProposal> proposals = new ArrayList<ICompletionProposal>(); for (AnnotationProposalComputer computer : computers) { if (element instanceof SourceField) { proposals.addAll(computer.computeCompletionProposals((SourceField) element, value, annotation, javaContext)); } if (element instanceof SourceMethod) { proposals.addAll(computer.computeCompletionProposals((SourceMethod) element, value, annotation, javaContext)); } if (element instanceof SourceType) { proposals.addAll(computer.computeCompletionProposals((SourceType) element, value, annotation, javaContext)); } } return proposals; } // private LocationInformation getLocationInformation(StringLiteral value, // JavaContentAssistInvocationContext javaContext) { // int startPos = value.getStartPosition(); // int invocationOffset = javaContext.getInvocationOffset(); // String literalValue = value.getLiteralValue(); // int length = invocationOffset - startPos; // if (length > literalValue.length()) { // length = literalValue.length(); // invocationOffset = startPos + length; // } // String filter = literalValue.substring(0, length); // // return new LocationInformation(startPos, invocationOffset, filter, // value); // } // }