/******************************************************************************* * Copyright (c) 2000, 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 v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Renaud Waldura <renaud+eclipse@waldura.com> * IBM Corporation - updates *******************************************************************************/ package org.eclipse.jdt.internal.ui.text.correction.proposals; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.CatchClause; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.Name; import org.eclipse.jdt.core.dom.ParameterizedType; import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility; import org.eclipse.jdt.internal.corext.dom.ASTNodes; import org.eclipse.jdt.internal.corext.dom.Bindings; import org.eclipse.jdt.internal.corext.util.Messages; import org.eclipse.jdt.internal.ui.JavaPlugin; import org.eclipse.jdt.internal.ui.JavaPluginImages; import org.eclipse.jdt.internal.ui.text.correction.ASTResolving; import org.eclipse.jdt.internal.ui.text.correction.CorrectionMessages; import org.eclipse.jdt.internal.ui.text.correction.UnresolvedElementsSubProcessor; import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels; import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider; import org.eclipse.jdt.ui.JavaElementLabels; import org.eclipse.jdt.ui.text.java.IInvocationContext; import org.eclipse.jdt.ui.text.java.IProblemLocation; import org.eclipse.jdt.ui.text.java.correction.ChangeCorrectionProposal; import org.eclipse.jface.text.IDocument; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * This proposal is listed in the corrections list for a "type not found" problem. * It offers to create a new type by running the class/interface wizard. * If selected, this proposal will open a {@link NewClassCreationWizard}, * {@link NewInterfaceCreationWizard}, {@link NewEnumCreationWizard} or {@link NewAnnotationCreationWizard}. * * @see UnresolvedElementsSubProcessor#getTypeProposals(IInvocationContext, IProblemLocation, Collection) */ public class NewCUUsingWizardProposal extends ChangeCorrectionProposal { public static final int K_CLASS= 1; public static final int K_INTERFACE= 2; public static final int K_ENUM= 3; public static final int K_ANNOTATION= 4; private Name fNode; private ICompilationUnit fCompilationUnit; private int fTypeKind; private IJavaElement fTypeContainer; // IType or IPackageFragment private String fTypeNameWithParameters; private IType fCreatedType; private boolean fShowDialog; public NewCUUsingWizardProposal(ICompilationUnit cu, Name node, int typeKind, IJavaElement typeContainer, int severity) { super("", null, severity, null); //$NON-NLS-1$ fCompilationUnit = cu; fNode = node; fTypeKind = typeKind; fTypeContainer = typeContainer; fTypeNameWithParameters = getTypeName(typeKind, node); fCreatedType = null; String containerName = ASTNodes.getQualifier(node); String typeName = fTypeNameWithParameters; String containerLabel = BasicElementLabels.getJavaElementName(containerName); String typeLabel = BasicElementLabels.getJavaElementName(typeName); boolean isInnerType = typeContainer instanceof IType; switch (typeKind) { case K_CLASS: setImage(JavaPluginImages.get(JavaPluginImages.IMG_OBJS_CLASS)); if (isInnerType) { if (containerName.length() == 0) { setDisplayName(Messages.format(CorrectionMessages.NewCUCompletionUsingWizardProposal_createinnerclass_description, typeLabel)); } else { setDisplayName( Messages.format(CorrectionMessages.NewCUCompletionUsingWizardProposal_createinnerclass_intype_description, new String[]{typeLabel, containerLabel})); } } else { if (containerName.length() == 0) { setDisplayName( Messages.format(CorrectionMessages.NewCUCompletionUsingWizardProposal_createclass_description, typeLabel)); } else { setDisplayName( Messages.format(CorrectionMessages.NewCUCompletionUsingWizardProposal_createclass_inpackage_description, new String[]{typeLabel, containerLabel})); } } break; case K_INTERFACE: setImage(JavaPluginImages.get(JavaPluginImages.IMG_OBJS_INTERFACE)); if (isInnerType) { if (containerName.length() == 0) { setDisplayName( Messages.format(CorrectionMessages.NewCUCompletionUsingWizardProposal_createinnerinterface_description, typeLabel)); } else { setDisplayName(Messages.format( CorrectionMessages.NewCUCompletionUsingWizardProposal_createinnerinterface_intype_description, new String[]{typeLabel, containerLabel})); } } else { if (containerName.length() == 0) { setDisplayName(Messages.format(CorrectionMessages.NewCUCompletionUsingWizardProposal_createinterface_description, typeLabel)); } else { setDisplayName( Messages.format(CorrectionMessages .NewCUCompletionUsingWizardProposal_createinterface_inpackage_description, new String[]{typeLabel, containerLabel})); } } break; case K_ENUM: setImage(JavaPluginImages.get(JavaPluginImages.IMG_OBJS_ENUM)); if (isInnerType) { if (containerName.length() == 0) { setDisplayName(Messages.format(CorrectionMessages.NewCUCompletionUsingWizardProposal_createinnerenum_description, typeLabel)); } else { setDisplayName( Messages.format(CorrectionMessages.NewCUCompletionUsingWizardProposal_createinnerenum_intype_description, new String[]{typeLabel, containerLabel})); } } else { if (containerName.length() == 0) { setDisplayName( Messages.format(CorrectionMessages.NewCUCompletionUsingWizardProposal_createenum_description, typeLabel)); } else { setDisplayName( Messages.format(CorrectionMessages.NewCUCompletionUsingWizardProposal_createenum_inpackage_description, new String[]{typeLabel, containerLabel})); } } break; case K_ANNOTATION: setImage(JavaPluginImages.get(JavaPluginImages.IMG_OBJS_ANNOTATION)); if (isInnerType) { if (containerName.length() == 0) { setDisplayName( Messages.format(CorrectionMessages.NewCUCompletionUsingWizardProposal_createinnerannotation_description, typeLabel)); } else { setDisplayName(Messages.format( CorrectionMessages.NewCUCompletionUsingWizardProposal_createinnerannotation_intype_description, new String[]{typeLabel, containerLabel})); } } else { if (containerName.length() == 0) { setDisplayName(Messages.format(CorrectionMessages.NewCUCompletionUsingWizardProposal_createannotation_description, typeLabel)); } else { setDisplayName(Messages.format( CorrectionMessages.NewCUCompletionUsingWizardProposal_createannotation_inpackage_description, new String[]{typeLabel, containerLabel})); } } break; default: throw new IllegalArgumentException("Unknown type kind"); //$NON-NLS-1$ } fShowDialog= true; } private static String getTypeName(int typeKind, Name node) { String name= ASTNodes.getSimpleNameIdentifier(node); if (typeKind == K_CLASS || typeKind == K_INTERFACE) { ASTNode parent= node.getParent(); if (parent.getLocationInParent() == ParameterizedType.TYPE_PROPERTY) { String typeArgBaseName= name.startsWith(String.valueOf('T')) ? String.valueOf('S') : String.valueOf('T'); // use 'S' or 'T' int nTypeArgs= ((ParameterizedType) parent.getParent()).typeArguments().size(); StringBuffer buf= new StringBuffer(name); buf.append('<'); if (nTypeArgs == 1) { buf.append(typeArgBaseName); } else { for (int i= 0; i < nTypeArgs; i++) { if (i != 0) buf.append(", "); //$NON-NLS-1$ buf.append(typeArgBaseName).append(i + 1); } } buf.append('>'); return buf.toString(); } } return name; } @Override public void apply(IDocument document) { // StructuredSelection selection= new StructuredSelection(fCompilationUnit); // NewElementWizard wizard= createWizard(selection); // wizard.init(JavaPlugin.getDefault().getWorkbench(), selection); // // IType createdType= null; // // if (fShowDialog) { // Shell shell= JavaPlugin.getActiveWorkbenchShell(); // WizardDialog dialog= new WizardDialog(shell, wizard); // // PixelConverter converter= new PixelConverter(JFaceResources.getDialogFont()); // dialog.setMinimumPageSize(converter.convertWidthInCharsToPixels(70), converter.convertHeightInCharsToPixels(20)); // dialog.create(); // dialog.getShell().setText(CorrectionMessages.NewCUCompletionUsingWizardProposal_dialogtitle); // // if (dialog.open() == Window.OK) { // createdType= (IType) wizard.getCreatedElement(); // } // } else { // wizard.addPages(); // try { // NewTypeWizardPage page= getPage(wizard); // page.createType(null); // createdType= page.getCreatedType(); // } catch (CoreException e) { // JavaPlugin.log(e); // } catch (InterruptedException e) { // } // } // // if (createdType != null) { // IJavaElement container= createdType.getParent(); // if (container instanceof ICompilationUnit) { // container= container.getParent(); // } // if (!container.equals(fTypeContainer)) { // // add import // try { // ImportRewrite rewrite= StubUtility.createImportRewrite(fCompilationUnit, true); // rewrite.addImport(createdType.getFullyQualifiedName('.')); // JavaModelUtil.applyEdit(fCompilationUnit, rewrite.rewriteImports(null), false, null); // } catch (CoreException e) { // } // } // fCreatedType= createdType; // } throw new UnsupportedOperationException("apply"); } // private NewTypeWizardPage getPage(NewElementWizard wizard) { // IWizardPage[] pages= wizard.getPages(); // Assert.isTrue(pages.length > 0 && pages[0] instanceof NewTypeWizardPage); // return (NewTypeWizardPage) pages[0]; // } // // private NewElementWizard createWizard(StructuredSelection selection) { // switch (fTypeKind) { // case K_CLASS: { // NewClassWizardPage page= new NewClassWizardPage(); // page.init(selection); // configureWizardPage(page); // return new NewClassCreationWizard(page, true); // } // case K_INTERFACE: { // NewInterfaceWizardPage page= new NewInterfaceWizardPage(); // page.init(selection); // configureWizardPage(page); // return new NewInterfaceCreationWizard(page, true); // } // case K_ENUM: { // NewEnumWizardPage page= new NewEnumWizardPage(); // page.init(selection); // configureWizardPage(page); // return new NewEnumCreationWizard(page, true); // } // case K_ANNOTATION: { // NewAnnotationWizardPage page= new NewAnnotationWizardPage(); // page.init(selection); // configureWizardPage(page); // return new NewAnnotationCreationWizard(page, true); // } // } // throw new IllegalArgumentException(); // } // // private void configureWizardPage(NewTypeWizardPage page) { // fillInWizardPageName(page); // fillInWizardPageSuperTypes(page); // } // // /** // * Fill-in the "Package" and "Name" fields. // * @param page the wizard page. // */ // private void fillInWizardPageName(NewTypeWizardPage page) { // // allow to edit when there are type parameters // page.setTypeName(fTypeNameWithParameters, fTypeNameWithParameters.indexOf('<') != -1); // // boolean isInEnclosingType= fTypeContainer instanceof IType; // if (isInEnclosingType) { // page.setEnclosingType((IType) fTypeContainer, true); // } else { // page.setPackageFragment((IPackageFragment) fTypeContainer, true); // } // page.setEnclosingTypeSelection(isInEnclosingType, true); // } // // /** // * Fill-in the "Super Class" and "Super Interfaces" fields. // * @param page the wizard page. // */ // private void fillInWizardPageSuperTypes(NewTypeWizardPage page) { // ITypeBinding type= getPossibleSuperTypeBinding(fNode); // type= Bindings.normalizeTypeBinding(type); // if (type != null) { // if (type.isArray()) { // type= type.getElementType(); // } // if (type.isTopLevel() || type.isMember()) { // if (type.isClass() && (fTypeKind == K_CLASS)) { // page.setSuperClass(type.getQualifiedName(), true); // } else if (type.isInterface()) { // List<String> superInterfaces= new ArrayList<String>(); // superInterfaces.add(type.getQualifiedName()); // page.setSuperInterfaces(superInterfaces, true); // } // } // } // } private ITypeBinding getPossibleSuperTypeBinding(ASTNode node) { if (fTypeKind == K_ANNOTATION) { return null; } AST ast= node.getAST(); node= ASTNodes.getNormalizedNode(node); ASTNode parent= node.getParent(); switch (parent.getNodeType()) { case ASTNode.METHOD_DECLARATION: if (node.getLocationInParent() == MethodDeclaration.THROWN_EXCEPTION_TYPES_PROPERTY) { return ast.resolveWellKnownType("java.lang.Exception"); //$NON-NLS-1$ } break; case ASTNode.THROW_STATEMENT : return ast.resolveWellKnownType("java.lang.Exception"); //$NON-NLS-1$ case ASTNode.SINGLE_VARIABLE_DECLARATION: if (parent.getLocationInParent() == CatchClause.EXCEPTION_PROPERTY) { return ast.resolveWellKnownType("java.lang.Exception"); //$NON-NLS-1$ } break; case ASTNode.VARIABLE_DECLARATION_STATEMENT: case ASTNode.FIELD_DECLARATION: return null; // no guessing for LHS types, cannot be a supertype of a known type case ASTNode.PARAMETERIZED_TYPE: return null; // Inheritance doesn't help: A<X> z= new A<String>(); -> } ITypeBinding binding= ASTResolving.guessBindingForTypeReference(node); if (binding != null && !binding.isRecovered()) { return binding; } return null; } /* * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension5#getAdditionalProposalInfo(org.eclipse.core.runtime.IProgressMonitor) * @since 3.5 */ @Override public Object getAdditionalProposalInfo(IProgressMonitor monitor) { StringBuffer buf= new StringBuffer(); switch (fTypeKind) { case K_CLASS: buf.append(CorrectionMessages.NewCUCompletionUsingWizardProposal_createclass_info); break; case K_INTERFACE: buf.append(CorrectionMessages.NewCUCompletionUsingWizardProposal_createinterface_info); break; case K_ENUM: buf.append(CorrectionMessages.NewCUCompletionUsingWizardProposal_createenum_info); break; case K_ANNOTATION: buf.append(CorrectionMessages.NewCUCompletionUsingWizardProposal_createannotation_info); break; } buf.append("<br>"); //$NON-NLS-1$ buf.append("<br>"); //$NON-NLS-1$ if (fTypeContainer instanceof IType) { buf.append(CorrectionMessages.NewCUCompletionUsingWizardProposal_tooltip_enclosingtype); } else { buf.append(CorrectionMessages.NewCUCompletionUsingWizardProposal_tooltip_package); } buf.append(" <b>"); //$NON-NLS-1$ buf.append(JavaElementLabels.getElementLabel(fTypeContainer, JavaElementLabels.T_FULLY_QUALIFIED)); buf.append("</b><br>"); //$NON-NLS-1$ buf.append("public "); //$NON-NLS-1$ switch (fTypeKind) { case K_CLASS: buf.append("class <b>"); //$NON-NLS-1$ break; case K_INTERFACE: buf.append("interface <b>"); //$NON-NLS-1$ break; case K_ENUM: buf.append("enum <b>"); //$NON-NLS-1$ break; case K_ANNOTATION: buf.append("@interface <b>"); //$NON-NLS-1$ break; } nameToHTML(fTypeNameWithParameters, buf); ITypeBinding superclass= getPossibleSuperTypeBinding(fNode); if (superclass != null) { if (superclass.isClass()) { if (fTypeKind == K_CLASS) { buf.append("</b> extends <b>"); //$NON-NLS-1$ nameToHTML(BindingLabelProvider.getBindingLabel(superclass, BindingLabelProvider.DEFAULT_TEXTFLAGS), buf); } } else { if (fTypeKind == K_INTERFACE) { buf.append("</b> extends <b>"); //$NON-NLS-1$ } else { buf.append("</b> implements <b>"); //$NON-NLS-1$ } nameToHTML(BindingLabelProvider.getBindingLabel(superclass, BindingLabelProvider.DEFAULT_TEXTFLAGS), buf); } } buf.append("</b> {<br>}<br>"); //$NON-NLS-1$ return buf.toString(); } private void nameToHTML(String name, StringBuffer buf) { for (int i= 0; i < name.length(); i++) { char ch= name.charAt(i); if (ch == '>') { buf.append(">"); //$NON-NLS-1$ } else if (ch == '<') { buf.append("<"); //$NON-NLS-1$ } else { buf.append(ch); } } } /** * Returns the showDialog. * @return boolean */ public boolean isShowDialog() { return fShowDialog; } /** * Sets the showDialog. * @param showDialog The showDialog to set */ public void setShowDialog(boolean showDialog) { fShowDialog= showDialog; } public IType getCreatedType() { return fCreatedType; } public int getTypeKind() { return fTypeKind; } }