blob: d573ba32b389e1d5b9b37a56b650a8138cd4d996 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*
*******************************************************************************/
package org.eclipse.jst.jsp.ui.internal.handlers;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IAccessRule;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IImportContainer;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.TypeNameMatch;
import org.eclipse.jdt.core.search.TypeNameMatchRequestor;
import org.eclipse.jdt.ui.SharedASTProvider;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.window.Window;
import org.eclipse.jst.jsp.core.internal.java.IJSPTranslation;
import org.eclipse.jst.jsp.core.internal.java.JSPTranslationAdapter;
import org.eclipse.jst.jsp.core.internal.java.JSPTranslationExtension;
import org.eclipse.jst.jsp.ui.internal.JSPUIMessages;
import org.eclipse.jst.jsp.ui.internal.Logger;
import org.eclipse.jst.jsp.ui.internal.java.views.TypeNameLabelProvider;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;
import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.wst.sse.core.internal.provisional.INodeAdapter;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
public class AddImportHandler extends AbstractHandler {
private static final TypeNameLabelProvider LABEL_PROVIDER = new TypeNameLabelProvider();
/* (non-Javadoc)
* @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
*/
public Object execute(ExecutionEvent event) throws ExecutionException {
final IEditorSite site = HandlerUtil.getActiveEditor(event).getEditorSite();
final ISelectionProvider provider = site.getSelectionProvider();
final ISelection selection = provider != null ? provider.getSelection() : null;
if (selection instanceof IStructuredSelection && selection instanceof ITextSelection) {
final IStructuredSelection structuredSelection = (IStructuredSelection) selection;
final int offset = ((ITextSelection) selection).getOffset();
final Object firstElement = structuredSelection.getFirstElement();
if (firstElement instanceof IDOMNode) {
final IDOMModel model = ((IDOMNode) firstElement).getModel();
INodeAdapter adapter = model.getDocument().getAdapterFor(IJSPTranslation.class);
if (adapter != null) {
JSPTranslationAdapter translationAdapter = (JSPTranslationAdapter) model.getDocument().getAdapterFor(IJSPTranslation.class);
final JSPTranslationExtension translation = translationAdapter.getJSPTranslation();
translation.reconcileCompilationUnit();
final ICompilationUnit cu = translation.getCompilationUnit();
CompilationUnit astRoot = SharedASTProvider.getAST(cu, SharedASTProvider.WAIT_YES, null);
if (astRoot != null) {
final ASTNode node = NodeFinder.perform(astRoot, translation.getJavaOffset(offset), 0);
if (node != null) {
SimpleName name = null;
if (node.getNodeType() == ASTNode.SIMPLE_NAME) {
name = (SimpleName) node;
}
else if (node.getNodeType() == ASTNode.QUALIFIED_NAME) {
name = ((QualifiedName) node).getName();
}
if (name != null) {
IBinding binding = name.resolveBinding();
if (binding instanceof ITypeBinding && (binding.getJavaElement() == null || !binding.getJavaElement().exists()) ) {
// Look it up!
ITypeBinding typeBinding = (ITypeBinding) binding;
final IImportContainer importContainer = cu.getImportContainer();
if (!importContainer.getImport(typeBinding.getQualifiedName()).exists()) {
final List typesFound = new ArrayList();
final TypeNameMatchRequestor collector = new TypeNameMatcher(typesFound);
IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[] { cu.getJavaProject() });
final int mode = SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE;
try {
new SearchEngine().searchAllTypeNames(null, mode, name.getIdentifier().toCharArray(), mode, IJavaSearchConstants.CLASS_AND_INTERFACE, scope, collector, IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, null);
final int length = typesFound.size();
final List elements = new ArrayList();
for (int i = 0; i < length; i++) {
final TypeNameMatch match = (TypeNameMatch) typesFound.get(i);
final int modifiers = match.getModifiers();
if (!Flags.isPrivate(modifiers) && !Flags.isPackageDefault(modifiers)) {
elements.add(match);
}
}
TypeNameMatch match = null;
// If there's only one match, insert it; otherwise, open the dialog to choose from the list
if (elements.size() == 1){
match = (TypeNameMatch) elements.get(0);
}
else if (elements.size() > 1) {
ElementListSelectionDialog dialog= new ElementListSelectionDialog(site.getShell(), LABEL_PROVIDER);
dialog.setElements(elements.toArray(new TypeNameMatch[elements.size()]));
dialog.setTitle(JSPUIMessages.AddImportHandler_title);
dialog.setMessage(JSPUIMessages.AddImportHandler_label);
if (dialog.open() == Window.OK) {
final Object result = dialog.getFirstResult();
if (result instanceof TypeNameMatch) {
match = (TypeNameMatch) result;
}
}
}
addImport(match, model.getStructuredDocument());
} catch (JavaModelException e) {
Logger.logException("Exception while determining import.", e); //$NON-NLS-1$
}
}
}
}
}
}
}
}
}
return null;
}
private void addImport(TypeNameMatch match, IDocument document) {
if (match != null) {
new PageImport(match.getFullyQualifiedName()).add(document);
}
}
private class TypeNameMatcher extends TypeNameMatchRequestor {
private Collection matches;
public TypeNameMatcher(Collection matches) {
this.matches = matches;
}
private boolean isFiltered(TypeNameMatch match) {
// TODO Java Type Filter support
int accessibility= match.getAccessibility();
switch (accessibility) {
case IAccessRule.K_NON_ACCESSIBLE:
return JavaCore.ENABLED.equals(JavaCore.getOption(JavaCore.CODEASSIST_FORBIDDEN_REFERENCE_CHECK));
case IAccessRule.K_DISCOURAGED:
return JavaCore.ENABLED.equals(JavaCore.getOption(JavaCore.CODEASSIST_DISCOURAGED_REFERENCE_CHECK));
default:
return false;
}
}
public void acceptTypeNameMatch(TypeNameMatch match) {
if (!isFiltered(match)) {
matches.add(match);
}
}
}
}