/* * 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.quickassist; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.codehaus.groovy.eclipse.quickfix.GroovyQuickFixPlugin; import org.codehaus.groovy.eclipse.quickfix.templates.GroovyContext; import org.codehaus.jdt.groovy.model.GroovyCompilationUnit; import org.codehaus.jdt.groovy.model.GroovyNature; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.internal.corext.template.java.JavaContext; import org.eclipse.jdt.internal.ui.text.template.contentassist.TemplateProposal; import org.eclipse.jdt.ui.text.java.IInvocationContext; import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal; import org.eclipse.jdt.ui.text.java.IProblemLocation; import org.eclipse.jdt.ui.text.java.IQuickAssistProcessor; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.Region; import org.eclipse.jface.text.quickassist.IQuickAssistInvocationContext; import org.eclipse.jface.text.templates.ContextTypeRegistry; import org.eclipse.jface.text.templates.GlobalTemplateVariables; import org.eclipse.jface.text.templates.Template; import org.eclipse.jface.text.templates.TemplateContextType; import org.eclipse.jface.text.templates.persistence.TemplateStore; public class GroovyQuickAssist implements IQuickAssistProcessor { private static final String $_LINE_SELECTION= "${" + GlobalTemplateVariables.LineSelection.NAME + "}"; //$NON-NLS-1$ //$NON-NLS-2$ public boolean hasAssists(IInvocationContext context) throws CoreException { if (context != null && isContentInGroovyProject(context.getCompilationUnit())) { return new AddSuggestionsQuickAssistProposal(context).hasProposals() || new ConvertToClosureCompletionProposal(context).hasProposals() || new ConvertToMethodCompletionProposal(context).hasProposals() || new ConvertToMultiLineStringCompletionProposal(context).hasProposals() || new ConvertToSingleLineStringCompletionProposal(context).hasProposals() || new RemoveUnnecessarySemicolonsCompletionProposal(context).hasProposals() || new SwapOperandsCompletionProposal(context).hasProposals() || new SplitAssigmentCompletionProposal(context).hasProposals() || new AssignStatementToNewLocalProposal(context).hasProposals() || (context.getCompilationUnit() instanceof GroovyCompilationUnit && ( new ExtractToLocalProposal(context).hasProposals() || new ExtractToConstantProposal(context).hasProposals() || new ConvertLocalToFieldProposal(context).hasProposals())); } return false; } public IJavaCompletionProposal[] getAssists(IInvocationContext context, IProblemLocation[] locations) throws CoreException { if (!(context.getCompilationUnit() instanceof GroovyCompilationUnit)) { return new IJavaCompletionProposal[0]; } List<IJavaCompletionProposal> proposalList; if (context instanceof IQuickAssistInvocationContext) { proposalList = getTemplateAssists((IQuickAssistInvocationContext) context, (GroovyCompilationUnit) context.getCompilationUnit()); } else { proposalList = new ArrayList<IJavaCompletionProposal>(); } AddSuggestionsQuickAssistProposal javaProposal = new AddSuggestionsQuickAssistProposal( context); if (javaProposal.hasProposals()) { proposalList.add(javaProposal); } ConvertToClosureCompletionProposal convertToClosure = new ConvertToClosureCompletionProposal(context); if (convertToClosure.hasProposals()) { proposalList.add(convertToClosure); } ConvertToMethodCompletionProposal convertToMethod = new ConvertToMethodCompletionProposal(context); if (convertToMethod.hasProposals()) { proposalList.add(convertToMethod); } ConvertToMultiLineStringCompletionProposal convertToMultiLineString = new ConvertToMultiLineStringCompletionProposal(context); if (convertToMultiLineString.hasProposals()) { proposalList.add(convertToMultiLineString); } ConvertToSingleLineStringCompletionProposal convertToSingleLineString = new ConvertToSingleLineStringCompletionProposal(context); if (convertToSingleLineString.hasProposals()) { proposalList.add(convertToSingleLineString); } RemoveUnnecessarySemicolonsCompletionProposal unnecessarySemicolons = new RemoveUnnecessarySemicolonsCompletionProposal(context); if (unnecessarySemicolons.hasProposals()) { proposalList.add(unnecessarySemicolons); } SplitAssigmentCompletionProposal splitAssignment = new SplitAssigmentCompletionProposal(context); if (splitAssignment.hasProposals()) { proposalList.add(splitAssignment); } SwapOperandsCompletionProposal swapOperands = new SwapOperandsCompletionProposal(context); if (swapOperands.hasProposals()) { proposalList.add(swapOperands); } AssignStatementToNewLocalProposal assignStatement = new AssignStatementToNewLocalProposal(context); if (assignStatement.hasProposals()) { proposalList.add(assignStatement); } ExtractToLocalProposal extractToLocal = new ExtractToLocalProposal(context, false); if (extractToLocal.hasProposals()) { proposalList.add(extractToLocal); } ExtractToLocalProposal extractToLocalAllOccurences = new ExtractToLocalProposal(context, true); if (extractToLocalAllOccurences.hasProposals()) { proposalList.add(extractToLocalAllOccurences); } ExtractToConstantProposal extractToConstant = new ExtractToConstantProposal(context, false); if (extractToConstant.hasProposals()) { proposalList.add(extractToConstant); } ExtractToConstantProposal extractToConstantAllOccurrences = new ExtractToConstantProposal(context, true); if (extractToConstantAllOccurrences.hasProposals()) { proposalList.add(extractToConstantAllOccurrences); } ConvertLocalToFieldProposal convertToField = new ConvertLocalToFieldProposal(context); if (convertToField.hasProposals()) { proposalList.add(convertToField); } return proposalList.toArray(new IJavaCompletionProposal[0]); } public List<IJavaCompletionProposal> getTemplateAssists(IQuickAssistInvocationContext assistContext, GroovyCompilationUnit unit) { try { TemplateStore codeTemplates = GroovyQuickFixPlugin.getDefault().getTemplateStore(); List<IJavaCompletionProposal> templates = new ArrayList<IJavaCompletionProposal>(); Region region = new Region(assistContext.getOffset(), assistContext.getLength()); ContextTypeRegistry templateContextRegistry = GroovyQuickFixPlugin.getDefault().getTemplateContextRegistry(); TemplateContextType contextType = templateContextRegistry.getContextType(GroovyQuickFixPlugin.GROOVY_CONTEXT_TYPE); IDocument document = assistContext.getSourceViewer().getDocument(); JavaContext templateContext = new GroovyContext(contextType, document, region.getOffset(), region.getLength(), unit); templateContext.setForceEvaluation(true); templateContext.setVariable("selection", document.get(region.getOffset(), region.getLength())); for (Template template : codeTemplates.getTemplates()) { if (isSurroundWith(template, templateContext)) { templates.add(new TemplateProposal(template, templateContext, region, null)); } } return templates; } catch (BadLocationException e) { GroovyQuickFixPlugin.log(e); return Collections.emptyList(); } } private boolean isSurroundWith(Template template, JavaContext templateContext) { String contextId = templateContext.getContextType().getId(); return GroovyQuickFixPlugin.GROOVY_CONTEXT_TYPE.equals(contextId) && template.getPattern().indexOf($_LINE_SELECTION) != -1; } /** * Determines if the problem is contained in an accessible (open and existing) * Groovy project in the workspace. * * @param unit compilation unit containing the resource with the problem * @return {@code true} iff the problem is contained in an accessible Groovy project */ protected boolean isProblemInGroovyProject(IInvocationContext context) { if (context == null) { return false; } return isContentInGroovyProject(context.getCompilationUnit()); } /** * Determines if the problem is contained in an accessible (open and existing) * Groovy project in the workspace. * * @param unit compilation unit containing the resource with the problem * @return {@code true} iff the problem is contained in an accessible Groovy project */ protected boolean isContentInGroovyProject(ICompilationUnit unit) { if (unit != null) { IResource resource = unit.getResource(); if (resource != null) { IProject project = resource.getProject(); if (project != null && project.isAccessible() && GroovyNature.hasGroovyNature(project)) { return true; } } } return false; } }