/******************************************************************************* * Copyright (c) 2007, 2011 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: * IBM Corporation - initial API and implementation * Nathan Beyer (Cerner) <nbeyer@cerner.com> - [content assist][5.0] when selected method from favorites is a member of a type with a * type variable an invalid static import is added - https://bugs.eclipse.org/bugs/show_bug.cgi?id=202221 *******************************************************************************/ package org.eclipse.che.ide.ext.java.jdt.codeassistant; import org.eclipse.che.ide.ext.java.jdt.core.CompletionProposal; import org.eclipse.che.ide.ext.java.jdt.core.JavaCore; import org.eclipse.che.ide.ext.java.jdt.core.Signature; import org.eclipse.che.ide.ext.java.jdt.core.dom.CompilationUnit; import org.eclipse.che.ide.ext.java.jdt.core.dom.rewrite.ImportRewrite; import org.eclipse.che.ide.ext.java.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext; import org.eclipse.che.ide.ext.java.jdt.internal.corext.codemanipulation.StubUtility; import org.eclipse.che.ide.ext.java.jdt.text.Document; import org.eclipse.che.ide.ext.java.jdt.text.edits.TextEdit; import org.eclipse.che.ide.runtime.Assert; import org.eclipse.che.ide.api.text.BadLocationException; /** Completion proposal for required imports. */ public class ImportCompletionProposal extends AbstractJavaCompletionProposal { private final int fParentProposalKind; private ImportRewrite fImportRewrite; private ContextSensitiveImportRewriteContext fImportContext; private final CompletionProposal fProposal; private boolean fReplacementStringComputed; private CompilationUnit fCompilationUnit; private Document document; public ImportCompletionProposal(Document document, CompilationUnit fCompilationUnit, CompletionProposal proposal, JavaContentAssistInvocationContext context, int parentProposalKind) { super(context); fProposal = proposal; fParentProposalKind = parentProposalKind; this.fCompilationUnit = fCompilationUnit; this.document = document; } /* * @see org.eclipse.jdt.internal.ui.text.java.AbstractJavaCompletionProposal#getReplacementString() */ @Override public final String getReplacementString() { if (!fReplacementStringComputed) { setReplacementString(computeReplacementString()); } return super.getReplacementString(); } /** * Computes the replacement string. * * @return the replacement string */ private String computeReplacementString() { int proposalKind = fProposal.getKind(); String qualifiedTypeName = null; char[] qualifiedType = null; if (proposalKind == CompletionProposal.TYPE_IMPORT) { qualifiedType = fProposal.getSignature(); qualifiedTypeName = String.valueOf(Signature.toCharArray(qualifiedType)); } else if (proposalKind == CompletionProposal.METHOD_IMPORT || proposalKind == CompletionProposal.FIELD_IMPORT) { qualifiedType = Signature.getTypeErasure(fProposal.getDeclarationSignature()); qualifiedTypeName = String.valueOf(Signature.toCharArray(qualifiedType)); } else { /* * In 3.3 we only support the above import proposals, see CompletionProposal#getRequiredProposals() */ Assert.isTrue(false); } /* Add imports if the preference is on. */ fImportRewrite = createImportRewrite(); if (fImportRewrite != null) { if (proposalKind == CompletionProposal.TYPE_IMPORT) { String simpleType = fImportRewrite.addImport(qualifiedTypeName, fImportContext); if (fParentProposalKind == CompletionProposal.METHOD_REF) { return simpleType + "."; //$NON-NLS-1$ } } else { String res = fImportRewrite.addStaticImport(qualifiedTypeName, String.valueOf(fProposal.getName()), proposalKind == CompletionProposal.FIELD_IMPORT, fImportContext); int dot = res.lastIndexOf('.'); if (dot != -1) { String typeName = fImportRewrite.addImport(res.substring(0, dot), fImportContext); return typeName + '.'; } } return ""; //$NON-NLS-1$ } // Case where we don't have an import rewrite (see allowAddingImports) // TODO // if (fCompilationUnit != null && JavaModelUtil.isImplicitImport(Signature.getQualifier(qualifiedTypeName), // fCompilationUnit)) { // /* No imports for implicit imports. */ // // if (fProposal.getKind() == CompletionProposal.TYPE_IMPORT && fParentProposalKind == CompletionProposal.FIELD_REF) // return ""; //$NON-NLS-1$ // qualifiedTypeName= String.valueOf(Signature.getSignatureSimpleName(qualifiedType)); // } return qualifiedTypeName + "."; //$NON-NLS-1$ } /* * @see org.eclipse.jdt.internal.ui.text.java.AbstractJavaCompletionProposal#apply(org.eclipse.jface.text.Document, char, int) */ @Override public void apply(Document document, char trigger, int offset) { try { super.apply(document, trigger, offset); if (fImportRewrite != null && fImportRewrite.hasRecordedChanges()) { int oldLen = document.getLength(); fImportRewrite.rewriteImports().apply(document, TextEdit.UPDATE_REGIONS); setReplacementOffset(getReplacementOffset() + document.getLength() - oldLen); } } catch (BadLocationException e) { // TODO log error e.printStackTrace();//NOSONAR } } /** * Creates and returns the import rewrite if imports should be added at all. * * @return the import rewrite or <code>null</code> if no imports can or should be added */ private ImportRewrite createImportRewrite() { if (fCompilationUnit != null && shouldAddImports()) { ImportRewrite rewrite = StubUtility.createImportRewrite(document, fCompilationUnit, true); fImportContext = new ContextSensitiveImportRewriteContext(fCompilationUnit, fInvocationContext.getInvocationOffset(), rewrite); return rewrite; } return null; } // private CompilationUnit getASTRoot(ICompilationUnit compilationUnit) { // return SharedASTProvider.getAST(compilationUnit, SharedASTProvider.WAIT_NO, null); // } /** * Returns <code>true</code> if imports should be added. The return value depends on the context and preferences only and does * not take into account the contents of the compilation unit or the kind of proposal. Even if <code>true</code> is returned, * there may be cases where no imports are added for the proposal. For example: * <ul> * <li>when completing within the import section</li> * <li>when completing informal javadoc references (e.g. within <code><code></code> tags)</li> * <li>when completing a type that conflicts with an existing import</li> * <li>when completing an implicitly imported type (same package, <code>java.lang</code> types)</li> * </ul> * <p> * The decision whether a qualified type or the simple type name should be inserted must take into account these different * scenarios. * </p> * * @return <code>true</code> if imports may be added, <code>false</code> if not */ private boolean shouldAddImports() { if (isInJavadoc() && !isJavadocProcessingEnabled()) { return false; } // // IPreferenceStore preferenceStore= JavaPlugin.getDefault().getPreferenceStore(); // return preferenceStore.getBoolean(PreferenceConstants.CODEASSIST_ADDIMPORT); return true; } /** * Returns whether Javadoc processing is enabled. * * @return <code>true</code> if Javadoc processing is enabled, <code>false</code> otherwise */ private boolean isJavadocProcessingEnabled() { // IJavaProject project= fCompilationUnit.getJavaProject(); boolean processJavadoc; // if (project == null) processJavadoc = JavaCore.ENABLED.equals(JavaCore.getOption(JavaCore.COMPILER_DOC_COMMENT_SUPPORT)); // else // processJavadoc= JavaCore.ENABLED.equals(project.getOption(JavaCore.COMPILER_DOC_COMMENT_SUPPORT, true)); return processJavadoc; } /** @see org.eclipse.che.ide.legacy.client.api.completion.editor.api.contentassist.CompletionProposal#isAutoInsertable() */ @Override public boolean isAutoInsertable() { return true; } }