CHE-139: add 'Organize Imports' functionality
Signed-off-by: Valeriy Svydenko <vsvydenko@codenvy.com>6.19.x
parent
0ac1fb0078
commit
af3bcd3874
|
|
@ -120,6 +120,10 @@
|
|||
<groupId>org.eclipse.che.plugin</groupId>
|
||||
<artifactId>org.eclipse.search</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.equinox</groupId>
|
||||
<artifactId>preferences</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.search</groupId>
|
||||
<artifactId>org.eclipse.search</artifactId>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import com.google.inject.Singleton;
|
|||
|
||||
import org.eclipse.che.dto.server.DtoFactory;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.Change;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.ConflictImportDTO;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.Problem;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.ProposalApplyResult;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.ProposalPresentation;
|
||||
|
|
@ -47,11 +48,15 @@ import org.eclipse.jdt.core.IJavaProject;
|
|||
import org.eclipse.jdt.core.IType;
|
||||
import org.eclipse.jdt.core.JavaModelException;
|
||||
import org.eclipse.jdt.core.WorkingCopyOwner;
|
||||
import org.eclipse.jdt.core.search.TypeNameMatch;
|
||||
import org.eclipse.jdt.internal.core.CompilationUnit;
|
||||
import org.eclipse.jdt.internal.core.DocumentAdapter;
|
||||
import org.eclipse.jdt.internal.core.JavaModelStatus;
|
||||
import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings;
|
||||
import org.eclipse.jdt.internal.corext.codemanipulation.OrganizeImportsOperation;
|
||||
import org.eclipse.jdt.internal.corext.refactoring.changes.MoveCompilationUnitChange;
|
||||
import org.eclipse.jdt.internal.corext.refactoring.changes.RenameCompilationUnitChange;
|
||||
import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings;
|
||||
import org.eclipse.jdt.internal.ui.text.correction.AssistContext;
|
||||
import org.eclipse.jdt.internal.ui.text.correction.JavaCorrectionProcessor;
|
||||
import org.eclipse.jdt.internal.ui.text.java.JavaAllCompletionProposalComputer;
|
||||
|
|
@ -59,12 +64,14 @@ import org.eclipse.jdt.internal.ui.text.java.RelevanceSorter;
|
|||
import org.eclipse.jdt.internal.ui.text.java.TemplateCompletionProposalComputer;
|
||||
import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext;
|
||||
import org.eclipse.jdt.ui.text.java.correction.ChangeCorrectionProposal;
|
||||
import org.eclipse.jface.text.BadLocationException;
|
||||
import org.eclipse.jface.text.DocumentEvent;
|
||||
import org.eclipse.jface.text.IDocument;
|
||||
import org.eclipse.jface.text.IDocumentListener;
|
||||
import org.eclipse.ltk.core.refactoring.CompositeChange;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.Point;
|
||||
import org.eclipse.text.edits.TextEdit;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
|
@ -216,6 +223,91 @@ public class CodeAssist {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Organizes the imports of a compilation unit.
|
||||
*
|
||||
* @param project
|
||||
* current java project
|
||||
* @param fqn
|
||||
* fully qualified name of the java file
|
||||
* @return list of imports which have conflicts
|
||||
*/
|
||||
public List<ConflictImportDTO> organizeImports(IJavaProject project, String fqn) throws CoreException, BadLocationException {
|
||||
ICompilationUnit compilationUnit = prepareCompilationUnit(project, fqn);
|
||||
return createOrganizeImportOperation(compilationUnit, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies chosen imports after resolving conflicts.
|
||||
*
|
||||
* @param project
|
||||
* current java project
|
||||
* @param fqn
|
||||
* fully qualified name of the java file
|
||||
* @param chosen
|
||||
* list of chosen imports as result of resolving conflicts which needed to add to all imports.
|
||||
*/
|
||||
public void applyChosenImports(IJavaProject project, String fqn, List<String> chosen) throws CoreException, BadLocationException {
|
||||
ICompilationUnit compilationUnit = prepareCompilationUnit(project, fqn);
|
||||
createOrganizeImportOperation(compilationUnit, chosen);
|
||||
}
|
||||
|
||||
private List<ConflictImportDTO> createOrganizeImportOperation(ICompilationUnit compilationUnit,
|
||||
List<String> chosen) throws CoreException {
|
||||
CodeGenerationSettings settings = JavaPreferencesSettings.getCodeGenerationSettings(compilationUnit.getJavaProject());
|
||||
|
||||
OrganizeImportsOperation operation = new OrganizeImportsOperation(compilationUnit,
|
||||
null,
|
||||
settings.importIgnoreLowercase,
|
||||
!compilationUnit.isWorkingCopy(),
|
||||
true,
|
||||
chosen,
|
||||
null);
|
||||
|
||||
NullProgressMonitor monitor = new NullProgressMonitor();
|
||||
TextEdit edit = operation.createTextEdit(monitor);
|
||||
|
||||
TypeNameMatch[][] choices = operation.getChoices();
|
||||
//Apply organize import declarations if operation doesn't have conflicts (choices.length == 0)
|
||||
//or all conflicts were resolved (!chosen.isEmpty())
|
||||
if ((chosen != null && !chosen.isEmpty()) || choices == null || choices.length == 0) {
|
||||
operation.applyChanges(edit, monitor);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return createListOfDTOMatches(choices);
|
||||
}
|
||||
|
||||
private List<ConflictImportDTO> createListOfDTOMatches(TypeNameMatch[][] choices) {
|
||||
List<ConflictImportDTO> typeMatches = new ArrayList<>();
|
||||
for (int i = 0; i < choices.length; i++) {
|
||||
List<String> nameMatches = new ArrayList<>();
|
||||
TypeNameMatch[] choice = choices[i];
|
||||
for (int j = 0; j < choice.length; j++) {
|
||||
nameMatches.add(choice[j].getFullyQualifiedName());
|
||||
}
|
||||
typeMatches.add(DtoFactory.newDto(ConflictImportDTO.class).withTypeMatches(nameMatches));
|
||||
}
|
||||
return typeMatches;
|
||||
}
|
||||
|
||||
private ICompilationUnit prepareCompilationUnit(IJavaProject project, String fqn) throws JavaModelException {
|
||||
ICompilationUnit compilationUnit;
|
||||
|
||||
IType type = project.findType(fqn);
|
||||
if (type == null) {
|
||||
throw new JavaModelException(
|
||||
new JavaModelStatus(IJavaModelStatusConstants.CORE_EXCEPTION, "Can't find a file: " + fqn));
|
||||
}
|
||||
if (type.isBinary()) {
|
||||
throw new JavaModelException(
|
||||
new JavaModelStatus(IJavaModelStatusConstants.CORE_EXCEPTION, "Can't organize imports on binary file"));
|
||||
} else {
|
||||
compilationUnit = type.getCompilationUnit();
|
||||
}
|
||||
return compilationUnit;
|
||||
}
|
||||
|
||||
private class CodeAssistContext {
|
||||
private TextViewer viewer;
|
||||
private int offset;
|
||||
|
|
|
|||
|
|
@ -11,15 +11,18 @@
|
|||
|
||||
package org.eclipse.che.jdt.rest;
|
||||
|
||||
import org.eclipse.che.api.core.NotFoundException;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.Problem;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.ProposalApplyResult;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.Proposals;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.ConflictImportDTO;
|
||||
import org.eclipse.che.jdt.CodeAssist;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.jdt.core.IJavaProject;
|
||||
import org.eclipse.jdt.core.JavaModelException;
|
||||
import org.eclipse.jdt.internal.core.JavaModel;
|
||||
import org.eclipse.jdt.internal.core.JavaModelManager;
|
||||
import org.eclipse.jface.text.BadLocationException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.Consumes;
|
||||
|
|
@ -30,6 +33,7 @@ import javax.ws.rs.Path;
|
|||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.util.List;
|
||||
|
||||
|
|
@ -69,9 +73,9 @@ public class CodeAssistService {
|
|||
@Produces("application/json")
|
||||
@Consumes("application/json")
|
||||
public Proposals computeAssistProposals(@QueryParam("projectpath") String projectPath,
|
||||
@QueryParam("fqn") String fqn,
|
||||
@QueryParam("offset") int offset,
|
||||
List<Problem> problems) throws CoreException {
|
||||
@QueryParam("fqn") String fqn,
|
||||
@QueryParam("offset") int offset,
|
||||
List<Problem> problems) throws CoreException {
|
||||
IJavaProject javaProject = model.getJavaProject(projectPath);
|
||||
return codeAssist.computeAssistProposals(javaProject, fqn, offset, problems);
|
||||
|
||||
|
|
@ -86,4 +90,46 @@ public class CodeAssistService {
|
|||
return codeAssist.getJavaDoc(sessionId, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Organizes the imports of a compilation unit.
|
||||
*
|
||||
* @param projectPath
|
||||
* path to the project
|
||||
* @param fqn
|
||||
* fully qualified name of the java file
|
||||
* @return list of imports which have conflicts
|
||||
*/
|
||||
@POST
|
||||
@Path("/organize-imports")
|
||||
@Produces({MediaType.APPLICATION_JSON})
|
||||
public List<ConflictImportDTO> organizeImports(@QueryParam("projectpath") String projectPath,
|
||||
@QueryParam("fqn") String fqn) throws NotFoundException,
|
||||
CoreException,
|
||||
BadLocationException {
|
||||
IJavaProject project = model.getJavaProject(projectPath);
|
||||
return codeAssist.organizeImports(project, fqn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies chosen imports after resolving conflicts.
|
||||
*
|
||||
* @param projectPath
|
||||
* path to the project
|
||||
* @param fqn
|
||||
* fully qualified name of the java file
|
||||
* @param chosen
|
||||
* list of chosen imports from conflicts which needed to add to all imports.
|
||||
*/
|
||||
@POST
|
||||
@Path("/apply-imports")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public void applyChosenImports(@QueryParam("projectpath") String projectPath,
|
||||
@QueryParam("fqn") String fqn,
|
||||
ConflictImportDTO chosen) throws NotFoundException,
|
||||
CoreException,
|
||||
BadLocationException {
|
||||
IJavaProject project = model.getJavaProject(projectPath);
|
||||
codeAssist.applyChosenImports(project, fqn, chosen.getTypeMatches());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,78 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2000, 2014 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
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.jdt.core;
|
||||
|
||||
import org.eclipse.che.ide.ext.java.BaseTest;
|
||||
import org.eclipse.che.jdt.testplugin.*;
|
||||
import org.eclipse.che.jdt.testplugin.ProjectTestSetup;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.jdt.core.ICompilationUnit;
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
|
||||
import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
||||
public class CoreTests extends BaseTest {
|
||||
|
||||
private org.eclipse.che.jdt.testplugin.ProjectTestSetup setup;
|
||||
|
||||
public CoreTests(ProjectTestSetup setup) {
|
||||
this.setup = setup;
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
setup.setUp();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
setup.tearDown();
|
||||
}
|
||||
|
||||
public static void assertEqualString(String actual, String expected) {
|
||||
StringAsserts.assertEqualString(actual, expected);
|
||||
}
|
||||
|
||||
public static void assertEqualStringIgnoreDelim(String actual, String expected) throws IOException {
|
||||
StringAsserts.assertEqualStringIgnoreDelim(actual, expected);
|
||||
}
|
||||
|
||||
public static void assertEqualStringsIgnoreOrder(String[] actuals, String[] expecteds) {
|
||||
StringAsserts.assertEqualStringsIgnoreOrder(actuals, expecteds);
|
||||
}
|
||||
|
||||
public static void assertNumberOf(String name, int is, int expected) {
|
||||
assertTrue("Wrong number of " + name + ", is: " + is + ", expected: " + expected, is == expected);
|
||||
}
|
||||
|
||||
protected ImportRewrite newImportsRewrite(ICompilationUnit cu, String[] order, int normalThreshold, int staticThreshold, boolean restoreExistingImports) throws CoreException {
|
||||
ImportRewrite rewrite= StubUtility.createImportRewrite(cu, restoreExistingImports);
|
||||
rewrite.setImportOrder(order);
|
||||
rewrite.setOnDemandImportThreshold(normalThreshold);
|
||||
rewrite.setStaticOnDemandImportThreshold(staticThreshold);
|
||||
return rewrite;
|
||||
}
|
||||
|
||||
protected ImportRewrite newImportsRewrite(CompilationUnit cu, String[] order, int normalThreshold, int staticThreshold, boolean restoreExistingImports) {
|
||||
ImportRewrite rewrite= ImportRewrite.create(cu, restoreExistingImports);
|
||||
rewrite.setImportOrder(order);
|
||||
rewrite.setOnDemandImportThreshold(normalThreshold);
|
||||
rewrite.setStaticOnDemandImportThreshold(staticThreshold);
|
||||
return rewrite;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -22,6 +22,7 @@ import org.eclipse.jdt.core.IPackageFragment;
|
|||
import org.eclipse.jdt.core.IPackageFragmentRoot;
|
||||
import org.eclipse.jdt.core.JavaCore;
|
||||
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
|
||||
import org.eclipse.jdt.internal.core.JavaModelManager;
|
||||
import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
|
||||
import org.eclipse.jdt.internal.corext.fix.FixMessages;
|
||||
import org.eclipse.jdt.internal.corext.template.java.CodeTemplateContextType;
|
||||
|
|
@ -6376,6 +6377,7 @@ public class AssistQuickFixTest extends QuickFixTest {
|
|||
|
||||
@Test
|
||||
public void testConvertAnonymousToNested2() throws Exception {
|
||||
JavaModelManager.getIndexManager().indexAll(fJProject1.getProject());
|
||||
// Preferences corePrefs= JavaPlugin.getJavaCorePluginPreferences();
|
||||
fJProject1.setOption(JavaCore.CODEASSIST_FIELD_PREFIXES, "f");
|
||||
fJProject1.setOption(JavaCore.CODEASSIST_LOCAL_PREFIXES, "l");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,595 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2000, 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
|
||||
* <p/>
|
||||
* Contributors:
|
||||
* IBM Corporation - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.jdt.internal.corext.codemanipulation;
|
||||
|
||||
import org.eclipse.che.jdt.util.JavaModelUtil;
|
||||
import org.eclipse.core.resources.IWorkspaceRunnable;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||
import org.eclipse.core.runtime.OperationCanceledException;
|
||||
import org.eclipse.core.runtime.SubProgressMonitor;
|
||||
import org.eclipse.core.runtime.jobs.ISchedulingRule;
|
||||
import org.eclipse.jdt.core.Flags;
|
||||
import org.eclipse.jdt.core.ICompilationUnit;
|
||||
import org.eclipse.jdt.core.IJavaElement;
|
||||
import org.eclipse.jdt.core.IJavaProject;
|
||||
import org.eclipse.jdt.core.IPackageFragment;
|
||||
import org.eclipse.jdt.core.ISourceRange;
|
||||
import org.eclipse.jdt.core.JavaCore;
|
||||
import org.eclipse.jdt.core.JavaModelException;
|
||||
import org.eclipse.jdt.core.SourceRange;
|
||||
import org.eclipse.jdt.core.compiler.IProblem;
|
||||
import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
|
||||
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.ImportDeclaration;
|
||||
import org.eclipse.jdt.core.dom.Modifier;
|
||||
import org.eclipse.jdt.core.dom.Name;
|
||||
import org.eclipse.jdt.core.dom.SimpleName;
|
||||
import org.eclipse.jdt.core.dom.Type;
|
||||
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
|
||||
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.TypeNameMatch;
|
||||
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
|
||||
import org.eclipse.jdt.internal.corext.dom.Bindings;
|
||||
import org.eclipse.jdt.internal.corext.dom.ScopeAnalyzer;
|
||||
import org.eclipse.jdt.internal.corext.util.Messages;
|
||||
import org.eclipse.jdt.internal.corext.util.Strings;
|
||||
import org.eclipse.jdt.internal.corext.util.TypeNameMatchCollector;
|
||||
import org.eclipse.jdt.internal.ui.text.correction.ASTResolving;
|
||||
import org.eclipse.jdt.internal.ui.text.correction.SimilarElementsRequestor;
|
||||
import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
|
||||
import org.eclipse.jdt.ui.SharedASTProvider;
|
||||
import org.eclipse.text.edits.TextEdit;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class OrganizeImportsOperation implements IWorkspaceRunnable {
|
||||
public static interface IChooseImportQuery {
|
||||
/**
|
||||
* Selects imports from a list of choices.
|
||||
*
|
||||
* @param openChoices
|
||||
* From each array, a type reference has to be selected
|
||||
* @param ranges
|
||||
* For each choice the range of the corresponding type reference.
|
||||
* @return Returns <code>null</code> to cancel the operation, or the
|
||||
* selected imports.
|
||||
*/
|
||||
TypeNameMatch[] chooseImports(TypeNameMatch[][] openChoices, ISourceRange[] ranges);
|
||||
}
|
||||
|
||||
|
||||
private static class TypeReferenceProcessor {
|
||||
|
||||
private static class UnresolvedTypeData {
|
||||
final SimpleName ref;
|
||||
final int typeKinds;
|
||||
final List<TypeNameMatch> foundInfos;
|
||||
|
||||
public UnresolvedTypeData(SimpleName ref) {
|
||||
this.ref = ref;
|
||||
this.typeKinds = ASTResolving.getPossibleTypeKinds(ref, true);
|
||||
this.foundInfos = new ArrayList<TypeNameMatch>(3);
|
||||
}
|
||||
|
||||
public void addInfo(TypeNameMatch info) {
|
||||
for (int i = this.foundInfos.size() - 1; i >= 0; i--) {
|
||||
TypeNameMatch curr = this.foundInfos.get(i);
|
||||
if (curr.getTypeContainerName().equals(info.getTypeContainerName())) {
|
||||
return; // not added. already contains type with same name
|
||||
}
|
||||
}
|
||||
foundInfos.add(info);
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> fOldSingleImports;
|
||||
private Set<String> fOldDemandImports;
|
||||
|
||||
private Set<String> fImplicitImports;
|
||||
|
||||
private ImportRewrite fImpStructure;
|
||||
|
||||
private boolean fDoIgnoreLowerCaseNames;
|
||||
|
||||
private IPackageFragment fCurrPackage;
|
||||
|
||||
private ScopeAnalyzer fAnalyzer;
|
||||
private boolean fAllowDefaultPackageImports;
|
||||
|
||||
private Map<String, UnresolvedTypeData> fUnresolvedTypes;
|
||||
private Set<String> fImportsAdded;
|
||||
private TypeNameMatch[][] fOpenChoices;
|
||||
private SourceRange[] fSourceRanges;
|
||||
|
||||
|
||||
public TypeReferenceProcessor(Set<String> oldSingleImports, Set<String> oldDemandImports, CompilationUnit root,
|
||||
ImportRewrite impStructure, boolean ignoreLowerCaseNames) {
|
||||
fOldSingleImports = oldSingleImports;
|
||||
fOldDemandImports = oldDemandImports;
|
||||
fImpStructure = impStructure;
|
||||
fDoIgnoreLowerCaseNames = ignoreLowerCaseNames;
|
||||
|
||||
ICompilationUnit cu = impStructure.getCompilationUnit();
|
||||
|
||||
fImplicitImports = new HashSet<String>(3);
|
||||
fImplicitImports.add(""); //$NON-NLS-1$
|
||||
fImplicitImports.add("java.lang"); //$NON-NLS-1$
|
||||
fImplicitImports.add(cu.getParent().getElementName());
|
||||
|
||||
fAnalyzer = new ScopeAnalyzer(root);
|
||||
|
||||
fCurrPackage = (IPackageFragment)cu.getParent();
|
||||
|
||||
fAllowDefaultPackageImports = cu.getJavaProject().getOption(JavaCore.COMPILER_SOURCE, true).equals(JavaCore.VERSION_1_3);
|
||||
|
||||
fImportsAdded = new HashSet<String>();
|
||||
fUnresolvedTypes = new HashMap<String, UnresolvedTypeData>();
|
||||
}
|
||||
|
||||
private boolean needsImport(ITypeBinding typeBinding, SimpleName ref) {
|
||||
if (!typeBinding.isTopLevel() && !typeBinding.isMember() || typeBinding.isRecovered()) {
|
||||
return false; // no imports for anonymous, local, primitive types or parameters types
|
||||
}
|
||||
int modifiers = typeBinding.getModifiers();
|
||||
if (Modifier.isPrivate(modifiers)) {
|
||||
return false; // imports for privates are not required
|
||||
}
|
||||
ITypeBinding currTypeBinding = Bindings.getBindingOfParentType(ref);
|
||||
if (currTypeBinding == null) {
|
||||
if (ASTNodes.getParent(ref, ASTNode.PACKAGE_DECLARATION) != null) {
|
||||
return true; // reference in package-info.java
|
||||
}
|
||||
return false; // not in a type
|
||||
}
|
||||
if (!Modifier.isPublic(modifiers)) {
|
||||
if (!currTypeBinding.getPackage().getName().equals(typeBinding.getPackage().getName())) {
|
||||
return false; // not visible
|
||||
}
|
||||
}
|
||||
|
||||
ASTNode parent = ref.getParent();
|
||||
while (parent instanceof Type) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
if (parent instanceof AbstractTypeDeclaration && parent.getParent() instanceof CompilationUnit) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeBinding.isMember()) {
|
||||
if (fAnalyzer.isDeclaredInScope(typeBinding, ref, ScopeAnalyzer.TYPES | ScopeAnalyzer.CHECK_VISIBILITY))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tries to find the given type name and add it to the import structure.
|
||||
*
|
||||
* @param ref
|
||||
* the name node
|
||||
*/
|
||||
public void add(SimpleName ref) {
|
||||
String typeName = ref.getIdentifier();
|
||||
|
||||
if (fImportsAdded.contains(typeName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
IBinding binding = ref.resolveBinding();
|
||||
if (binding != null) {
|
||||
if (binding.getKind() != IBinding.TYPE) {
|
||||
return;
|
||||
}
|
||||
ITypeBinding typeBinding = (ITypeBinding)binding;
|
||||
if (typeBinding.isArray()) {
|
||||
typeBinding = typeBinding.getElementType();
|
||||
}
|
||||
typeBinding = typeBinding.getTypeDeclaration();
|
||||
if (!typeBinding.isRecovered()) {
|
||||
if (needsImport(typeBinding, ref)) {
|
||||
fImpStructure.addImport(typeBinding);
|
||||
fImportsAdded.add(typeName);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (fDoIgnoreLowerCaseNames && typeName.length() > 0) {
|
||||
char ch = typeName.charAt(0);
|
||||
if (Strings.isLowerCase(ch) && Character.isLetter(ch)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
fImportsAdded.add(typeName);
|
||||
fUnresolvedTypes.put(typeName, new UnresolvedTypeData(ref));
|
||||
}
|
||||
|
||||
public boolean process(IProgressMonitor monitor) throws JavaModelException {
|
||||
try {
|
||||
int nUnresolved = fUnresolvedTypes.size();
|
||||
if (nUnresolved == 0) {
|
||||
return false;
|
||||
}
|
||||
char[][] allTypes = new char[nUnresolved][];
|
||||
int i = 0;
|
||||
for (Iterator<String> iter = fUnresolvedTypes.keySet().iterator(); iter.hasNext(); ) {
|
||||
allTypes[i++] = iter.next().toCharArray();
|
||||
}
|
||||
final ArrayList<TypeNameMatch> typesFound = new ArrayList<TypeNameMatch>();
|
||||
final IJavaProject project = fCurrPackage.getJavaProject();
|
||||
IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaElement[]{project});
|
||||
TypeNameMatchCollector collector = new TypeNameMatchCollector(typesFound);
|
||||
new SearchEngine()
|
||||
.searchAllTypeNames(null, allTypes, scope, collector, IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, monitor);
|
||||
|
||||
boolean is50OrHigher = JavaModelUtil.is50OrHigher(project);
|
||||
|
||||
for (i = 0; i < typesFound.size(); i++) {
|
||||
TypeNameMatch curr = typesFound.get(i);
|
||||
UnresolvedTypeData data = fUnresolvedTypes.get(curr.getSimpleTypeName());
|
||||
if (data != null && isVisible(curr) && isOfKind(curr, data.typeKinds, is50OrHigher)) {
|
||||
if (fAllowDefaultPackageImports || curr.getPackageName().length() > 0) {
|
||||
data.addInfo(curr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<TypeNameMatch[]> openChoices = new ArrayList<TypeNameMatch[]>(nUnresolved);
|
||||
ArrayList<SourceRange> sourceRanges = new ArrayList<SourceRange>(nUnresolved);
|
||||
for (Iterator<UnresolvedTypeData> iter = fUnresolvedTypes.values().iterator(); iter.hasNext(); ) {
|
||||
UnresolvedTypeData data = iter.next();
|
||||
TypeNameMatch[] openChoice = processTypeInfo(data.foundInfos);
|
||||
if (openChoice != null) {
|
||||
openChoices.add(openChoice);
|
||||
sourceRanges.add(new SourceRange(data.ref.getStartPosition(), data.ref.getLength()));
|
||||
}
|
||||
}
|
||||
if (openChoices.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
fOpenChoices = openChoices.toArray(new TypeNameMatch[openChoices.size()][]);
|
||||
fSourceRanges = sourceRanges.toArray(new SourceRange[sourceRanges.size()]);
|
||||
return true;
|
||||
} finally {
|
||||
monitor.done();
|
||||
}
|
||||
}
|
||||
|
||||
private TypeNameMatch[] processTypeInfo(List<TypeNameMatch> typeRefsFound) {
|
||||
int nFound = typeRefsFound.size();
|
||||
if (nFound == 0) {
|
||||
// nothing found
|
||||
return null;
|
||||
} else if (nFound == 1) {
|
||||
TypeNameMatch typeRef = typeRefsFound.get(0);
|
||||
fImpStructure.addImport(typeRef.getFullyQualifiedName());
|
||||
return null;
|
||||
} else {
|
||||
String typeToImport = null;
|
||||
boolean ambiguousImports = false;
|
||||
|
||||
// multiple found, use old imports to find an entry
|
||||
for (int i = 0; i < nFound; i++) {
|
||||
TypeNameMatch typeRef = typeRefsFound.get(i);
|
||||
String fullName = typeRef.getFullyQualifiedName();
|
||||
String containerName = typeRef.getTypeContainerName();
|
||||
if (fOldSingleImports.contains(fullName)) {
|
||||
// was single-imported
|
||||
fImpStructure.addImport(fullName);
|
||||
return null;
|
||||
} else if (fOldDemandImports.contains(containerName) || fImplicitImports.contains(containerName)) {
|
||||
if (typeToImport == null) {
|
||||
typeToImport = fullName;
|
||||
} else { // more than one import-on-demand
|
||||
ambiguousImports = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeToImport != null && !ambiguousImports) {
|
||||
fImpStructure.addImport(typeToImport);
|
||||
return null;
|
||||
}
|
||||
// return the open choices
|
||||
return typeRefsFound.toArray(new TypeNameMatch[nFound]);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isOfKind(TypeNameMatch curr, int typeKinds, boolean is50OrHigher) {
|
||||
int flags = curr.getModifiers();
|
||||
if (Flags.isAnnotation(flags)) {
|
||||
return is50OrHigher && (typeKinds & SimilarElementsRequestor.ANNOTATIONS) != 0;
|
||||
}
|
||||
if (Flags.isEnum(flags)) {
|
||||
return is50OrHigher && (typeKinds & SimilarElementsRequestor.ENUMS) != 0;
|
||||
}
|
||||
if (Flags.isInterface(flags)) {
|
||||
return (typeKinds & SimilarElementsRequestor.INTERFACES) != 0;
|
||||
}
|
||||
return (typeKinds & SimilarElementsRequestor.CLASSES) != 0;
|
||||
}
|
||||
|
||||
private boolean isVisible(TypeNameMatch curr) {
|
||||
int flags = curr.getModifiers();
|
||||
if (Flags.isPrivate(flags)) {
|
||||
return false;
|
||||
}
|
||||
if (Flags.isPublic(flags) || Flags.isProtected(flags)) {
|
||||
return true;
|
||||
}
|
||||
return curr.getPackageName().equals(fCurrPackage.getElementName());
|
||||
}
|
||||
|
||||
public TypeNameMatch[][] getChoices() {
|
||||
return fOpenChoices;
|
||||
}
|
||||
|
||||
public ISourceRange[] getChoicesSourceRanges() {
|
||||
return fSourceRanges;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean fDoSave;
|
||||
|
||||
private boolean fIgnoreLowerCaseNames;
|
||||
|
||||
private IChooseImportQuery fChooseImportQuery;
|
||||
|
||||
private int fNumberOfImportsAdded;
|
||||
private int fNumberOfImportsRemoved;
|
||||
|
||||
private IProblem fParsingError;
|
||||
private ICompilationUnit fCompilationUnit;
|
||||
|
||||
private CompilationUnit fASTRoot;
|
||||
private TextEdit edit;
|
||||
private TypeReferenceProcessor processor;
|
||||
private boolean hasOpenChoices;
|
||||
|
||||
private TypeNameMatch[][] choices;
|
||||
private List<String> chosenFQN;
|
||||
|
||||
private final boolean fAllowSyntaxErrors;
|
||||
|
||||
public OrganizeImportsOperation(ICompilationUnit cu,
|
||||
CompilationUnit astRoot,
|
||||
boolean ignoreLowerCaseNames,
|
||||
boolean save,
|
||||
boolean allowSyntaxErrors,
|
||||
List<String> chosen,
|
||||
IChooseImportQuery chooseImportQuery) {
|
||||
fCompilationUnit = cu;
|
||||
fASTRoot = astRoot;
|
||||
|
||||
fDoSave = save;
|
||||
fIgnoreLowerCaseNames = ignoreLowerCaseNames;
|
||||
fAllowSyntaxErrors = allowSyntaxErrors;
|
||||
fChooseImportQuery = chooseImportQuery;
|
||||
|
||||
fNumberOfImportsAdded = 0;
|
||||
fNumberOfImportsRemoved = 0;
|
||||
|
||||
fParsingError = null;
|
||||
|
||||
chosenFQN = chosen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the operation.
|
||||
*
|
||||
* @param monitor
|
||||
* the progress monitor
|
||||
* @throws CoreException
|
||||
* thrown when the operation failed
|
||||
* @throws OperationCanceledException
|
||||
* Runtime error thrown when operation is canceled.
|
||||
*/
|
||||
public void run(IProgressMonitor monitor) throws CoreException, OperationCanceledException {
|
||||
if (monitor == null) {
|
||||
monitor = new NullProgressMonitor();
|
||||
}
|
||||
try {
|
||||
monitor.beginTask(Messages.format(CodeGenerationMessages.OrganizeImportsOperation_description,
|
||||
BasicElementLabels.getFileName(fCompilationUnit)), 10);
|
||||
|
||||
edit = createTextEdit(new SubProgressMonitor(monitor, 9));
|
||||
if (edit == null)
|
||||
return;
|
||||
|
||||
JavaModelUtil.applyEdit(fCompilationUnit, edit, fDoSave, new SubProgressMonitor(monitor, 1));
|
||||
} finally {
|
||||
monitor.done();
|
||||
}
|
||||
}
|
||||
|
||||
public void applyChanges(TextEdit edit, IProgressMonitor monitor) throws CoreException {
|
||||
if (edit == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
JavaModelUtil.applyEdit(fCompilationUnit, edit, fDoSave, new SubProgressMonitor(monitor, 1));
|
||||
}
|
||||
|
||||
public TextEdit createTextEdit(IProgressMonitor monitor) throws CoreException, OperationCanceledException {
|
||||
if (monitor == null) {
|
||||
monitor = new NullProgressMonitor();
|
||||
}
|
||||
try {
|
||||
fNumberOfImportsAdded = 0;
|
||||
fNumberOfImportsRemoved = 0;
|
||||
|
||||
monitor.beginTask(Messages.format(CodeGenerationMessages.OrganizeImportsOperation_description,
|
||||
BasicElementLabels.getFileName(fCompilationUnit)), 9);
|
||||
|
||||
CompilationUnit astRoot = fASTRoot;
|
||||
if (astRoot == null) {
|
||||
astRoot = SharedASTProvider.getAST(fCompilationUnit, SharedASTProvider.WAIT_YES, new SubProgressMonitor(monitor, 2));
|
||||
if (monitor.isCanceled())
|
||||
throw new OperationCanceledException();
|
||||
} else {
|
||||
monitor.worked(2);
|
||||
}
|
||||
|
||||
ImportRewrite importsRewrite = StubUtility.createImportRewrite(astRoot, false);
|
||||
|
||||
Set<String> oldSingleImports = new HashSet<>();
|
||||
Set<String> oldDemandImports = new HashSet<>();
|
||||
List<SimpleName> typeReferences = new ArrayList<>();
|
||||
List<SimpleName> staticReferences = new ArrayList<>();
|
||||
|
||||
if (!collectReferences(astRoot, typeReferences, staticReferences, oldSingleImports, oldDemandImports))
|
||||
return null;
|
||||
|
||||
monitor.worked(1);
|
||||
|
||||
processor = new TypeReferenceProcessor(oldSingleImports, oldDemandImports, astRoot, importsRewrite, fIgnoreLowerCaseNames);
|
||||
|
||||
Iterator<SimpleName> refIterator = typeReferences.iterator();
|
||||
while (refIterator.hasNext()) {
|
||||
SimpleName typeRef = refIterator.next();
|
||||
processor.add(typeRef);
|
||||
}
|
||||
|
||||
hasOpenChoices = processor.process(new SubProgressMonitor(monitor, 3));
|
||||
addStaticImports(staticReferences, importsRewrite);
|
||||
|
||||
if (hasOpenChoices) {
|
||||
choices = processor.getChoices();
|
||||
ISourceRange[] ranges = processor.getChoicesSourceRanges();
|
||||
if (fChooseImportQuery != null) {
|
||||
TypeNameMatch[] chosen = fChooseImportQuery.chooseImports(choices, ranges);
|
||||
for (int i = 0; i < chosen.length; i++) {
|
||||
TypeNameMatch typeInfo = chosen[i];
|
||||
importsRewrite.addImport(typeInfo.getFullyQualifiedName());
|
||||
}
|
||||
} else if (chosenFQN != null) {
|
||||
chosenFQN.forEach(importsRewrite::addImport);
|
||||
}
|
||||
}
|
||||
|
||||
TextEdit result = importsRewrite.rewriteImports(new SubProgressMonitor(monitor, 3));
|
||||
|
||||
determineImportDifferences(importsRewrite, oldSingleImports, oldDemandImports);
|
||||
|
||||
return result;
|
||||
} finally {
|
||||
monitor.done();
|
||||
}
|
||||
}
|
||||
|
||||
public TypeNameMatch[][] getChoices() {
|
||||
return choices;
|
||||
}
|
||||
|
||||
private void determineImportDifferences(ImportRewrite importsStructure, Set<String> oldSingleImports, Set<String> oldDemandImports) {
|
||||
ArrayList<String> importsAdded = new ArrayList<String>();
|
||||
importsAdded.addAll(Arrays.asList(importsStructure.getCreatedImports()));
|
||||
importsAdded.addAll(Arrays.asList(importsStructure.getCreatedStaticImports()));
|
||||
|
||||
Object[] content = oldSingleImports.toArray();
|
||||
for (int i = 0; i < content.length; i++) {
|
||||
String importName = (String)content[i];
|
||||
if (importsAdded.remove(importName))
|
||||
oldSingleImports.remove(importName);
|
||||
}
|
||||
content = oldDemandImports.toArray();
|
||||
for (int i = 0; i < content.length; i++) {
|
||||
String importName = (String)content[i];
|
||||
if (importsAdded.remove(importName + ".*")) //$NON-NLS-1$
|
||||
oldDemandImports.remove(importName);
|
||||
}
|
||||
fNumberOfImportsAdded = importsAdded.size();
|
||||
fNumberOfImportsRemoved = oldSingleImports.size() + oldDemandImports.size();
|
||||
}
|
||||
|
||||
|
||||
private void addStaticImports(List<SimpleName> staticReferences, ImportRewrite importsStructure) {
|
||||
for (int i = 0; i < staticReferences.size(); i++) {
|
||||
Name name = staticReferences.get(i);
|
||||
IBinding binding = name.resolveBinding();
|
||||
if (binding != null) { // paranoia check
|
||||
importsStructure.addStaticImport(binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// find type references in a compilation unit
|
||||
private boolean collectReferences(CompilationUnit astRoot, List<SimpleName> typeReferences, List<SimpleName> staticReferences,
|
||||
Set<String> oldSingleImports, Set<String> oldDemandImports) {
|
||||
if (!fAllowSyntaxErrors) {
|
||||
IProblem[] problems = astRoot.getProblems();
|
||||
for (int i = 0; i < problems.length; i++) {
|
||||
IProblem curr = problems[i];
|
||||
if (curr.isError() && (curr.getID() & IProblem.Syntax) != 0) {
|
||||
fParsingError = problems[i];
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
List<ImportDeclaration> imports = astRoot.imports();
|
||||
for (int i = 0; i < imports.size(); i++) {
|
||||
ImportDeclaration curr = imports.get(i);
|
||||
String id = ASTResolving.getFullName(curr.getName());
|
||||
if (curr.isOnDemand()) {
|
||||
oldDemandImports.add(id);
|
||||
} else {
|
||||
oldSingleImports.add(id);
|
||||
}
|
||||
}
|
||||
|
||||
IJavaProject project = fCompilationUnit.getJavaProject();
|
||||
ImportReferencesCollector.collect(astRoot, project, null, typeReferences, staticReferences);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* After executing the operation, returns <code>null</code> if the operation has been executed successfully or
|
||||
* the range where parsing failed.
|
||||
*
|
||||
* @return returns the parse error
|
||||
*/
|
||||
public IProblem getParseError() {
|
||||
return fParsingError;
|
||||
}
|
||||
|
||||
public int getNumberOfImportsAdded() {
|
||||
return fNumberOfImportsAdded;
|
||||
}
|
||||
|
||||
public int getNumberOfImportsRemoved() {
|
||||
return fNumberOfImportsRemoved;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the scheduling rule for this operation
|
||||
*/
|
||||
public ISchedulingRule getScheduleRule() {
|
||||
return fCompilationUnit.getResource();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.jdt.ui;
|
||||
|
||||
import org.eclipse.core.resources.ProjectScope;
|
||||
import org.eclipse.core.runtime.preferences.InstanceScope;
|
||||
import org.eclipse.jdt.core.IJavaProject;
|
||||
import org.eclipse.jdt.core.JavaCore;
|
||||
|
|
@ -37,6 +38,8 @@ import java.util.StringTokenizer;
|
|||
*/
|
||||
public class PreferenceConstants {
|
||||
|
||||
public static final String ID_PLUGIN = "org.eclipse.jdt.ui";
|
||||
|
||||
private PreferenceConstants() {
|
||||
}
|
||||
|
||||
|
|
@ -4083,18 +4086,17 @@ public class PreferenceConstants {
|
|||
* @since 3.1
|
||||
*/
|
||||
public static String getPreference(String key, IJavaProject project) {
|
||||
// String val;
|
||||
// if (project != null) {
|
||||
// val = new ProjectScope(project.getProject()).getNode(JavaUI.ID_PLUGIN).get(key, null);
|
||||
// if (val != null) {
|
||||
// return val;
|
||||
// }
|
||||
// }
|
||||
// val = InstanceScope.INSTANCE.getNode(JavaUI.ID_PLUGIN).get(key, null);
|
||||
// if (val != null) {
|
||||
// return val;
|
||||
// }
|
||||
// return DefaultScope.INSTANCE.getNode(JavaUI.ID_PLUGIN).get(key, null);
|
||||
String val;
|
||||
if (project != null) {
|
||||
val = new ProjectScope(project.getProject()).getNode(ID_PLUGIN).get(key, null);
|
||||
if (val != null && !val.isEmpty()) {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
val = InstanceScope.INSTANCE.getNode(ID_PLUGIN).get(key, null);
|
||||
if (val != null) {
|
||||
return val;
|
||||
}
|
||||
return getPreferenceStore().getString(key);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,13 +24,14 @@ import org.eclipse.che.ide.api.icon.Icon;
|
|||
import org.eclipse.che.ide.api.icon.IconRegistry;
|
||||
import org.eclipse.che.ide.api.keybinding.KeyBindingAgent;
|
||||
import org.eclipse.che.ide.api.keybinding.KeyBuilder;
|
||||
import org.eclipse.che.ide.ext.java.client.action.FileStructureAction;
|
||||
import org.eclipse.che.ide.ext.java.client.action.FindUsagesAction;
|
||||
import org.eclipse.che.ide.ext.java.client.action.NewJavaSourceFileAction;
|
||||
import org.eclipse.che.ide.ext.java.client.action.NewPackageAction;
|
||||
import org.eclipse.che.ide.ext.java.client.action.OpenDeclarationAction;
|
||||
import org.eclipse.che.ide.ext.java.client.action.OpenImplementationAction;
|
||||
import org.eclipse.che.ide.ext.java.client.action.OrganizeImportsAction;
|
||||
import org.eclipse.che.ide.ext.java.client.action.QuickDocumentationAction;
|
||||
import org.eclipse.che.ide.ext.java.client.action.FileStructureAction;
|
||||
import org.eclipse.che.ide.ext.java.client.refactoring.move.CutJavaSourceAction;
|
||||
import org.eclipse.che.ide.ext.java.client.refactoring.move.MoveAction;
|
||||
import org.eclipse.che.ide.ext.java.client.refactoring.rename.RenameRefactoringAction;
|
||||
|
|
@ -72,6 +73,7 @@ public class JavaExtension {
|
|||
MoveAction moveAction,
|
||||
CutJavaSourceAction cutAction,
|
||||
FileStructureAction fileStructureAction,
|
||||
OrganizeImportsAction organizeImportsAction,
|
||||
RenameRefactoringAction renameRefactoringAction,
|
||||
QuickDocumentationAction quickDocumentationAction,
|
||||
OpenDeclarationAction openDeclarationAction,
|
||||
|
|
@ -106,9 +108,11 @@ public class JavaExtension {
|
|||
actionManager.registerAction("javaCutRefactoring", cutAction);
|
||||
actionManager.registerAction("javaFindUsages", findUsagesAction);
|
||||
actionManager.registerAction("javaClassStructure", fileStructureAction);
|
||||
actionManager.registerAction("organizeImports", organizeImportsAction);
|
||||
|
||||
assistantGroup.add(quickDocumentationAction, new Constraints(Anchor.BEFORE, GROUP_ASSISTANT_REFACTORING));
|
||||
assistantGroup.add(openDeclarationAction, new Constraints(Anchor.BEFORE, GROUP_ASSISTANT_REFACTORING));
|
||||
assistantGroup.add(organizeImportsAction, new Constraints(Anchor.BEFORE, GROUP_ASSISTANT_REFACTORING));
|
||||
assistantGroup.add(openImplementationAction, new Constraints(Anchor.BEFORE, GROUP_ASSISTANT_REFACTORING));
|
||||
assistantGroup.add(fileStructureAction, new Constraints(Anchor.BEFORE, GROUP_ASSISTANT_REFACTORING));
|
||||
assistantGroup.add(findUsagesAction, new Constraints(Anchor.BEFORE, GROUP_ASSISTANT_REFACTORING));
|
||||
|
|
@ -117,10 +121,12 @@ public class JavaExtension {
|
|||
keyBinding.getGlobal().addKey(new KeyBuilder().alt().control().charCode('b').build(), "openImplementation");
|
||||
keyBinding.getGlobal().addKey(new KeyBuilder().control().charCode('j').build(), "showQuickDoc");
|
||||
keyBinding.getGlobal().addKey(new KeyBuilder().control().charCode(KeyCodeMap.F12).build(), "javaClassStructure");
|
||||
keyBinding.getGlobal().addKey(new KeyBuilder().alt().control().charCode('o').build(), "organizeImports");
|
||||
} else {
|
||||
keyBinding.getGlobal().addKey(new KeyBuilder().alt().action().charCode('b').build(), "openImplementation");
|
||||
keyBinding.getGlobal().addKey(new KeyBuilder().action().charCode('q').build(), "showQuickDoc");
|
||||
keyBinding.getGlobal().addKey(new KeyBuilder().action().charCode(KeyCodeMap.F12).build(), "javaClassStructure");
|
||||
keyBinding.getGlobal().addKey(new KeyBuilder().alt().action().charCode('o').build(), "organizeImports");
|
||||
}
|
||||
keyBinding.getGlobal().addKey(new KeyBuilder().none().charCode(KeyCodeMap.F4).build(), "openJavaDeclaration");
|
||||
keyBinding.getGlobal().addKey(new KeyBuilder().shift().charCode(KeyCodeMap.F6).build(), "javaRenameRefactoring");
|
||||
|
|
|
|||
|
|
@ -129,6 +129,27 @@ public interface JavaLocalizationConstant extends Messages {
|
|||
@Key("file.structure.action.description")
|
||||
String fileStructureActionDescription();
|
||||
|
||||
@Key("organize.imports.name")
|
||||
String organizeImportsName();
|
||||
|
||||
@Key("organize.imports.description")
|
||||
String organizeImportsDescription();
|
||||
|
||||
@Key("organize.imports.failed.title")
|
||||
String failedToProcessOrganizeImports();
|
||||
|
||||
@Key("organize.imports.button.finish")
|
||||
String organizeImportsButtonFinish();
|
||||
|
||||
@Key("organize.imports.button.cancel")
|
||||
String organizeImportsButtonCancel();
|
||||
|
||||
@Key("organize.imports.button.next")
|
||||
String organizeImportsButtonNext();
|
||||
|
||||
@Key("organize.imports.button.back")
|
||||
String organizeImportsButtonBack();
|
||||
|
||||
@Key("show.inherited.members.label")
|
||||
String showInheritedMembersLabel();
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.ext.java.client.action;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.ide.api.action.ActionEvent;
|
||||
import org.eclipse.che.ide.api.editor.EditorAgent;
|
||||
import org.eclipse.che.ide.api.editor.EditorPartPresenter;
|
||||
import org.eclipse.che.ide.ext.java.client.JavaLocalizationConstant;
|
||||
import org.eclipse.che.ide.ext.java.client.organizeimports.OrganizeImportsPresenter;
|
||||
|
||||
/**
|
||||
* Organizes the imports of a compilation unit.
|
||||
*
|
||||
* @author Valeriy Svydenko
|
||||
*/
|
||||
@Singleton
|
||||
public class OrganizeImportsAction extends JavaEditorAction implements ProposalAction {
|
||||
public final static String JAVA_ORGANIZE_IMPORT_ID = "javaOrganizeImports";
|
||||
|
||||
private final EditorAgent editorAgent;
|
||||
private final OrganizeImportsPresenter organizeImportsPresenter;
|
||||
|
||||
@Inject
|
||||
public OrganizeImportsAction(JavaLocalizationConstant locale,
|
||||
EditorAgent editorAgent,
|
||||
OrganizeImportsPresenter organizeImportsPresenter) {
|
||||
super(locale.organizeImportsName(), locale.organizeImportsDescription(), null, editorAgent);
|
||||
this.editorAgent = editorAgent;
|
||||
this.organizeImportsPresenter = organizeImportsPresenter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performAsProposal() {
|
||||
actionPerformed(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return JAVA_ORGANIZE_IMPORT_ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final EditorPartPresenter editor = editorAgent.getActiveEditor();
|
||||
organizeImportsPresenter.organizeImports(editor);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.ext.java.client.action;
|
||||
|
||||
/**
|
||||
* This interface is a general type for all completion proposal actions.
|
||||
* You must implement the interface when you add new completion action.
|
||||
*
|
||||
* @author Valeriy Svydenko
|
||||
*/
|
||||
public interface ProposalAction {
|
||||
/** Implement this method to provide proposal action handler */
|
||||
void performAsProposal();
|
||||
|
||||
/** Returns action id */
|
||||
String getId();
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ package org.eclipse.che.ide.ext.java.client.editor;
|
|||
import com.google.gwt.user.client.ui.Widget;
|
||||
|
||||
import org.eclipse.che.ide.api.icon.Icon;
|
||||
import org.eclipse.che.ide.ext.java.client.action.ProposalAction;
|
||||
import org.eclipse.che.ide.jseditor.client.codeassist.CompletionProposal;
|
||||
import org.eclipse.che.ide.util.loging.Log;
|
||||
|
||||
|
|
@ -21,13 +22,15 @@ import org.eclipse.che.ide.util.loging.Log;
|
|||
*/
|
||||
public class ActionCompletionProposal implements CompletionProposal {
|
||||
|
||||
private final String display;
|
||||
private final String actionId;
|
||||
private final Icon icon;
|
||||
private final String display;
|
||||
private final String actionId;
|
||||
private final ProposalAction action;
|
||||
private final Icon icon;
|
||||
|
||||
public ActionCompletionProposal(String display, String actionId, Icon icon) {
|
||||
public ActionCompletionProposal(String display, String actionId, ProposalAction action, Icon icon) {
|
||||
this.display = display;
|
||||
this.actionId = actionId;
|
||||
this.action = action;
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
|
|
@ -48,6 +51,10 @@ public class ActionCompletionProposal implements CompletionProposal {
|
|||
|
||||
@Override
|
||||
public void getCompletion(CompletionCallback callback) {
|
||||
Log.error(getClass(), "Can't run Action " + actionId);
|
||||
if (action == null) {
|
||||
Log.error(getClass(), "Can't run Action " + actionId);
|
||||
} else {
|
||||
action.performAsProposal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import org.eclipse.che.api.promises.client.callback.AsyncPromiseHelper;
|
|||
import org.eclipse.che.ide.MimeType;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.Change;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.ConflictImportDTO;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.Problem;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.ProposalApplyResult;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.Proposals;
|
||||
|
|
@ -29,6 +30,8 @@ import org.eclipse.che.ide.rest.AsyncRequestCallback;
|
|||
import org.eclipse.che.ide.rest.AsyncRequestFactory;
|
||||
import org.eclipse.che.ide.rest.DtoUnmarshallerFactory;
|
||||
import org.eclipse.che.ide.rest.Unmarshallable;
|
||||
import org.eclipse.che.ide.ui.loaders.request.LoaderFactory;
|
||||
import org.eclipse.che.ide.ui.loaders.request.MessageLoader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -47,15 +50,18 @@ public class JavaCodeAssistClient {
|
|||
private final DtoUnmarshallerFactory unmarshallerFactory;
|
||||
private final AsyncRequestFactory asyncRequestFactory;
|
||||
private final String workspaceId;
|
||||
private final MessageLoader loader;
|
||||
|
||||
@Inject
|
||||
public JavaCodeAssistClient(@Named("cheExtensionPath") String machineExtPath,
|
||||
DtoUnmarshallerFactory unmarshallerFactory,
|
||||
AppContext appContext,
|
||||
LoaderFactory loaderFactory,
|
||||
AsyncRequestFactory asyncRequestFactory) {
|
||||
this.machineExtPath = machineExtPath;
|
||||
this.workspaceId = appContext.getWorkspace().getId();
|
||||
this.unmarshallerFactory = unmarshallerFactory;
|
||||
this.loader = loaderFactory.newLoader();
|
||||
this.asyncRequestFactory = asyncRequestFactory;
|
||||
}
|
||||
|
||||
|
|
@ -133,4 +139,46 @@ public class JavaCodeAssistClient {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Organizes the imports of a compilation unit.
|
||||
*
|
||||
* @param projectPath
|
||||
* path to the project
|
||||
* @param fqn
|
||||
* fully qualified name of the java file
|
||||
* @return list of imports which have conflicts
|
||||
*/
|
||||
public Promise<List<ConflictImportDTO>> organizeImports(String projectPath, String fqn) {
|
||||
String url = machineExtPath +
|
||||
"/jdt/" +
|
||||
workspaceId +
|
||||
"/code-assist/organize-imports?projectpath=" + projectPath +
|
||||
"&fqn=" + fqn;
|
||||
|
||||
return asyncRequestFactory.createPostRequest(url, null)
|
||||
.loader(loader)
|
||||
.send(unmarshallerFactory.newListUnmarshaller(ConflictImportDTO.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Organizes the imports of a compilation unit.
|
||||
*
|
||||
* @param projectPath
|
||||
* path to the project
|
||||
* @param fqn
|
||||
* fully qualified name of the java file
|
||||
*/
|
||||
public Promise<Void> applyChosenImports(String projectPath, String fqn, ConflictImportDTO chosen) {
|
||||
String url = machineExtPath +
|
||||
"/jdt/" +
|
||||
workspaceId +
|
||||
"/code-assist/apply-imports?projectpath=" + projectPath +
|
||||
"&fqn=" + fqn;
|
||||
|
||||
return asyncRequestFactory.createPostRequest(url, chosen)
|
||||
.loader(loader)
|
||||
.header(CONTENT_TYPE, MimeType.APPLICATION_JSON)
|
||||
.send();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import org.eclipse.che.ide.api.text.Position;
|
|||
import org.eclipse.che.ide.api.text.annotation.Annotation;
|
||||
import org.eclipse.che.ide.dto.DtoFactory;
|
||||
import org.eclipse.che.ide.ext.java.client.JavaResources;
|
||||
import org.eclipse.che.ide.ext.java.client.action.ProposalAction;
|
||||
import org.eclipse.che.ide.ext.java.client.projecttree.JavaSourceFolderUtil;
|
||||
import org.eclipse.che.ide.ext.java.client.refactoring.RefactoringUpdater;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.Problem;
|
||||
|
|
@ -42,28 +43,33 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.eclipse.che.ide.ext.java.client.editor.JavaCodeAssistProcessor.insertStyle;
|
||||
|
||||
/**
|
||||
* {@link QuickAssistProcessor} for java files.
|
||||
*/
|
||||
public class JavaQuickAssistProcessor implements QuickAssistProcessor {
|
||||
|
||||
private final JavaCodeAssistClient client;
|
||||
private final JavaCodeAssistClient client;
|
||||
/** The resources used for java assistants. */
|
||||
private final JavaResources javaResources;
|
||||
private final DtoUnmarshallerFactory unmarshallerFactory;
|
||||
private final DtoFactory dtoFactory;
|
||||
private final RefactoringUpdater refactoringUpdater;
|
||||
private final EditorAgent editorAgent;
|
||||
private final JavaResources javaResources;
|
||||
private final Map<String, ProposalAction> proposalActions;
|
||||
private final DtoUnmarshallerFactory unmarshallerFactory;
|
||||
private final DtoFactory dtoFactory;
|
||||
private final RefactoringUpdater refactoringUpdater;
|
||||
private final EditorAgent editorAgent;
|
||||
|
||||
@Inject
|
||||
public JavaQuickAssistProcessor(final JavaCodeAssistClient client,
|
||||
final JavaResources javaResources,
|
||||
Map<String, ProposalAction> proposalActions,
|
||||
DtoUnmarshallerFactory unmarshallerFactory,
|
||||
DtoFactory dtoFactory,
|
||||
RefactoringUpdater refactoringUpdater,
|
||||
EditorAgent editorAgent) {
|
||||
this.client = client;
|
||||
this.javaResources = javaResources;
|
||||
this.proposalActions = proposalActions;
|
||||
this.unmarshallerFactory = unmarshallerFactory;
|
||||
this.dtoFactory = dtoFactory;
|
||||
this.refactoringUpdater = refactoringUpdater;
|
||||
|
|
@ -119,17 +125,23 @@ public class JavaQuickAssistProcessor implements QuickAssistProcessor {
|
|||
HasLinkedMode linkedEditor = editor instanceof HasLinkedMode ? (HasLinkedMode)editor : null;
|
||||
for (ProposalPresentation proposal : presentations) {
|
||||
CompletionProposal completionProposal;
|
||||
if (proposal.getActionId() != null) {
|
||||
completionProposal =
|
||||
new ActionCompletionProposal(JavaCodeAssistProcessor.insertStyle(javaResources, proposal.getDisplayString()),
|
||||
proposal.getActionId(), JavaCodeAssistProcessor.getIcon(proposal.getImage())
|
||||
);
|
||||
String actionId = proposal.getActionId();
|
||||
if (actionId != null) {
|
||||
ProposalAction action = proposalActions.get(actionId);
|
||||
completionProposal = new ActionCompletionProposal(insertStyle(javaResources, proposal.getDisplayString()),
|
||||
actionId,
|
||||
action,
|
||||
JavaCodeAssistProcessor.getIcon(proposal.getImage())
|
||||
);
|
||||
} else {
|
||||
completionProposal = new JavaCompletionProposal(
|
||||
proposal.getIndex(),
|
||||
JavaCodeAssistProcessor.insertStyle(javaResources, proposal.getDisplayString()),
|
||||
JavaCodeAssistProcessor.getIcon(proposal.getImage()),
|
||||
client, responds.getSessionId(), linkedEditor, refactoringUpdater, editorAgent);
|
||||
completionProposal = new JavaCompletionProposal(proposal.getIndex(),
|
||||
insertStyle(javaResources, proposal.getDisplayString()),
|
||||
JavaCodeAssistProcessor.getIcon(proposal.getImage()),
|
||||
client,
|
||||
responds.getSessionId(),
|
||||
linkedEditor,
|
||||
refactoringUpdater,
|
||||
editorAgent);
|
||||
}
|
||||
proposals.add(completionProposal);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ import org.eclipse.che.ide.api.project.node.settings.SettingsProvider;
|
|||
import org.eclipse.che.ide.api.reference.FqnProvider;
|
||||
import org.eclipse.che.ide.ext.java.client.CurrentClassFQNProvider;
|
||||
import org.eclipse.che.ide.ext.java.client.JavaResources;
|
||||
import org.eclipse.che.ide.ext.java.client.action.OrganizeImportsAction;
|
||||
import org.eclipse.che.ide.ext.java.client.action.ProposalAction;
|
||||
import org.eclipse.che.ide.ext.java.client.dependenciesupdater.JavaClasspathServiceClient;
|
||||
import org.eclipse.che.ide.ext.java.client.dependenciesupdater.JavaClasspathServiceClientImpl;
|
||||
import org.eclipse.che.ide.ext.java.client.documentation.QuickDocPresenter;
|
||||
|
|
@ -50,6 +52,8 @@ import org.eclipse.che.ide.ext.java.client.settings.property.PropertyWidgetImpl;
|
|||
import org.eclipse.che.ide.extension.machine.client.command.valueproviders.CommandPropertyValueProvider;
|
||||
import org.eclipse.che.ide.settings.common.SettingsPagePresenter;
|
||||
|
||||
import static org.eclipse.che.ide.ext.java.client.action.OrganizeImportsAction.JAVA_ORGANIZE_IMPORT_ID;
|
||||
|
||||
/**
|
||||
* @author Evgen Vidolob
|
||||
* @author Artem Zatsarynnyi
|
||||
|
|
@ -60,6 +64,9 @@ public class JavaGinModule extends AbstractGinModule {
|
|||
/** {@inheritDoc} */
|
||||
@Override
|
||||
protected void configure() {
|
||||
GinMapBinder<String, ProposalAction> proposalActionMapBinder = GinMapBinder.newMapBinder(binder(), String.class, ProposalAction.class);
|
||||
proposalActionMapBinder.addBinding(JAVA_ORGANIZE_IMPORT_ID).to(OrganizeImportsAction.class);
|
||||
|
||||
bind(NewJavaSourceFileView.class).to(NewJavaSourceFileViewImpl.class).in(Singleton.class);
|
||||
bind(QuickDocumentation.class).to(QuickDocPresenter.class).in(Singleton.class);
|
||||
bind(JavaNavigationService.class).to(JavaNavigationServiceImpl.class);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,250 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.ext.java.client.organizeimports;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.api.project.gwt.client.ProjectServiceClient;
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.OperationException;
|
||||
import org.eclipse.che.api.promises.client.PromiseError;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.editor.EditorPartPresenter;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
import org.eclipse.che.ide.api.project.tree.VirtualFile;
|
||||
import org.eclipse.che.ide.api.texteditor.HandlesUndoRedo;
|
||||
import org.eclipse.che.ide.api.texteditor.UndoableEditor;
|
||||
import org.eclipse.che.ide.dto.DtoFactory;
|
||||
import org.eclipse.che.ide.ext.java.client.JavaLocalizationConstant;
|
||||
import org.eclipse.che.ide.ext.java.client.editor.JavaCodeAssistClient;
|
||||
import org.eclipse.che.ide.ext.java.client.projecttree.JavaSourceFolderUtil;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.ConflictImportDTO;
|
||||
import org.eclipse.che.ide.jseditor.client.document.Document;
|
||||
import org.eclipse.che.ide.jseditor.client.texteditor.TextEditor;
|
||||
import org.eclipse.che.ide.rest.AsyncRequestCallback;
|
||||
import org.eclipse.che.ide.rest.StringUnmarshaller;
|
||||
import org.eclipse.che.ide.util.loging.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.eclipse.che.ide.api.notification.StatusNotification.Status.FAIL;
|
||||
|
||||
/**
|
||||
* The class that manages conflicts with organize imports if if they occur.
|
||||
*
|
||||
* @author Valeriy Svydenko
|
||||
*/
|
||||
@Singleton
|
||||
public class OrganizeImportsPresenter implements OrganizeImportsView.ActionDelegate {
|
||||
private final OrganizeImportsView view;
|
||||
private final JavaCodeAssistClient javaCodeAssistClient;
|
||||
private final AppContext appContext;
|
||||
private final DtoFactory dtoFactory;
|
||||
private final JavaLocalizationConstant locale;
|
||||
private final NotificationManager notificationManager;
|
||||
|
||||
private int page;
|
||||
private List<ConflictImportDTO> choices;
|
||||
private Map<Integer, String> selected;
|
||||
private VirtualFile file;
|
||||
private ProjectServiceClient projectService;
|
||||
private Document document;
|
||||
private EditorPartPresenter editor;
|
||||
|
||||
@Inject
|
||||
public OrganizeImportsPresenter(OrganizeImportsView view,
|
||||
AppContext appContext,
|
||||
ProjectServiceClient projectService,
|
||||
JavaCodeAssistClient javaCodeAssistClient,
|
||||
DtoFactory dtoFactory,
|
||||
JavaLocalizationConstant locale,
|
||||
NotificationManager notificationManager) {
|
||||
this.view = view;
|
||||
this.projectService = projectService;
|
||||
this.javaCodeAssistClient = javaCodeAssistClient;
|
||||
this.view.setDelegate(this);
|
||||
|
||||
this.appContext = appContext;
|
||||
this.dtoFactory = dtoFactory;
|
||||
this.locale = locale;
|
||||
this.notificationManager = notificationManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make Organize imports operation. If the operation doesn't have conflicts all imports will be applied
|
||||
* otherwise a special window will be showed for resolving conflicts.
|
||||
*
|
||||
* @param editor
|
||||
* current active editor
|
||||
*/
|
||||
public void organizeImports(EditorPartPresenter editor) {
|
||||
this.editor = editor;
|
||||
this.document = ((TextEditor)editor).getDocument();
|
||||
this.file = editor.getEditorInput().getFile();
|
||||
|
||||
|
||||
final String projectPath = file.getProject().getProjectConfig().getPath();
|
||||
final String fqn = JavaSourceFolderUtil.getFQNForFile(file);
|
||||
|
||||
javaCodeAssistClient.organizeImports(projectPath, fqn)
|
||||
.then(new Operation<List<ConflictImportDTO>>() {
|
||||
@Override
|
||||
public void apply(List<ConflictImportDTO> choices) throws OperationException {
|
||||
if (!choices.isEmpty()) {
|
||||
show(choices);
|
||||
} else {
|
||||
applyChanges(file);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError arg) throws OperationException {
|
||||
notificationManager.notify(locale.failedToProcessOrganizeImports(), arg.getMessage(), FAIL, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onNextButtonClicked() {
|
||||
selected.put(page++, view.getSelectedImport());
|
||||
if (!selected.containsKey(page)) {
|
||||
String newSelection = choices.get(page).getTypeMatches().get(0);
|
||||
selected.put(page, newSelection);
|
||||
}
|
||||
view.setSelectedImport(selected.get(page));
|
||||
view.changePage(choices.get(page));
|
||||
updateButtonsState();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onBackButtonClicked() {
|
||||
selected.put(page--, view.getSelectedImport());
|
||||
view.setSelectedImport(selected.get(page));
|
||||
view.changePage(choices.get(page));
|
||||
updateButtonsState();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onFinishButtonClicked() {
|
||||
selected.put(page, view.getSelectedImport());
|
||||
|
||||
ConflictImportDTO result = dtoFactory.createDto(ConflictImportDTO.class).withTypeMatches(new ArrayList<>(selected.values()));
|
||||
|
||||
String projectPath = file.getProject().getProjectConfig().getPath();
|
||||
String fqn = JavaSourceFolderUtil.getFQNForFile(file);
|
||||
|
||||
javaCodeAssistClient.applyChosenImports(projectPath, fqn, result)
|
||||
.then(new Operation<Void>() {
|
||||
@Override
|
||||
public void apply(Void arg) throws OperationException {
|
||||
applyChanges(file);
|
||||
view.hide();
|
||||
((TextEditor)editor).setFocus();
|
||||
}
|
||||
})
|
||||
.catchError(new Operation<PromiseError>() {
|
||||
@Override
|
||||
public void apply(PromiseError arg) throws OperationException {
|
||||
notificationManager.notify(locale.failedToProcessOrganizeImports(), arg.getMessage(), FAIL, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void onCancelButtonClicked() {
|
||||
((TextEditor)editor).setFocus();
|
||||
}
|
||||
|
||||
/** Show Organize Imports panel with the special information. */
|
||||
private void show(List<ConflictImportDTO> choices) {
|
||||
if (choices == null || choices.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.choices = choices;
|
||||
|
||||
page = 0;
|
||||
selected = new HashMap<>(choices.size());
|
||||
|
||||
String selection = choices.get(0).getTypeMatches().get(0);
|
||||
selected.put(page, selection);
|
||||
view.setSelectedImport(selection);
|
||||
|
||||
updateButtonsState();
|
||||
|
||||
view.show(choices.get(page));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update content of the file.
|
||||
*
|
||||
* @param file
|
||||
* current file
|
||||
*/
|
||||
private void applyChanges(VirtualFile file) {
|
||||
HandlesUndoRedo undoRedo = null;
|
||||
if (editor instanceof UndoableEditor) {
|
||||
undoRedo = ((UndoableEditor)editor).getUndoRedo();
|
||||
}
|
||||
try {
|
||||
if (undoRedo != null) {
|
||||
undoRedo.beginCompoundChange();
|
||||
}
|
||||
replaceContent(file, document);
|
||||
} catch (final Exception e) {
|
||||
Log.error(getClass(), e);
|
||||
} finally {
|
||||
if (undoRedo != null) {
|
||||
undoRedo.endCompoundChange();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void replaceContent(VirtualFile file, final Document document) {
|
||||
projectService.getFileContent(appContext.getWorkspaceId(),
|
||||
file.getPath(),
|
||||
new AsyncRequestCallback<String>(new StringUnmarshaller()) {
|
||||
@Override
|
||||
protected void onSuccess(String result) {
|
||||
document.replace(0, document.getContents().length(), result);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFailure(Throwable exception) {
|
||||
Log.error(getClass(), exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateButtonsState() {
|
||||
view.setEnableBackButton(!isFirstPage());
|
||||
view.setEnableNextButton(!isLastPage());
|
||||
view.setEnableFinishButton(selected.size() == choices.size());
|
||||
}
|
||||
|
||||
private boolean isFirstPage() {
|
||||
return page == 0;
|
||||
}
|
||||
|
||||
private boolean isLastPage() {
|
||||
return (choices.size() - 1) == page;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.ext.java.client.organizeimports;
|
||||
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
import org.eclipse.che.ide.api.mvp.View;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.ConflictImportDTO;
|
||||
|
||||
/**
|
||||
* The visual part of Organize Imports wizard that has an ability to resolve import conflicts.
|
||||
*
|
||||
* @author Valeriy Svydenko
|
||||
*/
|
||||
@ImplementedBy(OrganizeImportsViewImpl.class)
|
||||
interface OrganizeImportsView extends View<OrganizeImportsView.ActionDelegate> {
|
||||
|
||||
/** Show Organize Imports panel with the list of conflict imports. */
|
||||
void show(ConflictImportDTO match);
|
||||
|
||||
/** Hide Organize Imports panel. */
|
||||
void hide();
|
||||
|
||||
/** @return selected import for current view page. */
|
||||
String getSelectedImport();
|
||||
|
||||
/**
|
||||
* Selects an import into current view page.
|
||||
*
|
||||
* @param fqn
|
||||
* import which need to select
|
||||
*/
|
||||
void setSelectedImport(String fqn);
|
||||
|
||||
/**
|
||||
* Show new view page for choosing necessary import.
|
||||
*
|
||||
* @param match
|
||||
* conflict object with possible options to choose
|
||||
*/
|
||||
void changePage(ConflictImportDTO match);
|
||||
|
||||
/**
|
||||
* Setts enable scope of the Finish button.
|
||||
*
|
||||
* @param isEnable
|
||||
* enable state of scope property
|
||||
*/
|
||||
void setEnableFinishButton(boolean isEnable);
|
||||
|
||||
/**
|
||||
* Setts enable scope of the Next button.
|
||||
*
|
||||
* @param isEnable
|
||||
* enable state of scope property
|
||||
*/
|
||||
void setEnableNextButton(boolean isEnable);
|
||||
|
||||
/**
|
||||
* Setts enable scope of the Back button.
|
||||
*
|
||||
* @param isEnable
|
||||
* enable state of scope property
|
||||
*/
|
||||
void setEnableBackButton(boolean isEnable);
|
||||
|
||||
interface ActionDelegate {
|
||||
/** Performs some actions in response to user's clicking on the 'Next' button. */
|
||||
void onNextButtonClicked();
|
||||
|
||||
/** Performs some actions in response to user's clicking on the 'Back' button. */
|
||||
void onBackButtonClicked();
|
||||
|
||||
/** Performs some actions in response to user's clicking on the 'Finish' button. */
|
||||
void onFinishButtonClicked();
|
||||
|
||||
/** Performs some actions in response to user's clicking on the 'Cancel' button. */
|
||||
void onCancelButtonClicked();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.ext.java.client.organizeimports;
|
||||
|
||||
import com.google.gwt.core.client.GWT;
|
||||
import com.google.gwt.event.dom.client.ClickEvent;
|
||||
import com.google.gwt.event.dom.client.ClickHandler;
|
||||
import com.google.gwt.uibinder.client.UiBinder;
|
||||
import com.google.gwt.uibinder.client.UiField;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.che.ide.ext.java.client.JavaLocalizationConstant;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.ConflictImportDTO;
|
||||
import org.eclipse.che.ide.ui.window.Window;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.gwt.dom.client.Style.Cursor.POINTER;
|
||||
import static org.eclipse.che.ide.api.theme.Style.getEditorSelectionColor;
|
||||
import static org.eclipse.che.ide.api.theme.Style.getMainFontColor;
|
||||
|
||||
/**
|
||||
* Implements of {@link OrganizeImportsView}.
|
||||
*
|
||||
* @author Valeriy Svydenko
|
||||
*/
|
||||
@Singleton
|
||||
final class OrganizeImportsViewImpl extends Window implements OrganizeImportsView {
|
||||
interface OrganizeImportsViewImplUiBinder extends UiBinder<Widget, OrganizeImportsViewImpl> {
|
||||
}
|
||||
|
||||
private static OrganizeImportsViewImplUiBinder UI_BINDER = GWT.create(OrganizeImportsViewImplUiBinder.class);
|
||||
|
||||
@UiField
|
||||
VerticalPanel container;
|
||||
|
||||
@UiField(provided = true)
|
||||
final JavaLocalizationConstant locale;
|
||||
|
||||
private ActionDelegate delegate;
|
||||
private Button next;
|
||||
private Button back;
|
||||
private Button finish;
|
||||
|
||||
private String selectedImport;
|
||||
private Label selectedLabel;
|
||||
|
||||
@Inject
|
||||
public OrganizeImportsViewImpl(JavaLocalizationConstant locale) {
|
||||
this.locale = locale;
|
||||
setTitle(locale.organizeImportsName());
|
||||
setWidget(UI_BINDER.createAndBindUi(this));
|
||||
|
||||
createButtons(locale);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setDelegate(ActionDelegate delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void show(ConflictImportDTO match) {
|
||||
container.clear();
|
||||
List<String> matches = match.getTypeMatches();
|
||||
for (String fqn : matches) {
|
||||
final Label label = new Label(fqn);
|
||||
if (fqn.equals(selectedImport)) {
|
||||
selectedLabel = label;
|
||||
selectedLabel.getElement().getStyle().setBackgroundColor(getEditorSelectionColor());
|
||||
}
|
||||
label.getElement().getStyle().setColor(getMainFontColor());
|
||||
label.getElement().getStyle().setCursor(POINTER);
|
||||
label.addClickHandler(new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent clickEvent) {
|
||||
selectedLabel.getElement().getStyle().setBackgroundColor("initial");
|
||||
selectedLabel = label;
|
||||
label.getElement().getStyle().setBackgroundColor(getEditorSelectionColor());
|
||||
}
|
||||
});
|
||||
|
||||
container.add(label);
|
||||
}
|
||||
|
||||
super.show();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public String getSelectedImport() {
|
||||
return selectedLabel.getText();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setSelectedImport(String fqn) {
|
||||
this.selectedImport = fqn;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void changePage(ConflictImportDTO match) {
|
||||
show(match);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setEnableFinishButton(boolean isEnable) {
|
||||
finish.setEnabled(isEnable);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setEnableNextButton(boolean isEnable) {
|
||||
next.setEnabled(isEnable);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void setEnableBackButton(boolean isEnable) {
|
||||
back.setEnabled(isEnable);
|
||||
}
|
||||
|
||||
private void createButtons(JavaLocalizationConstant locale) {
|
||||
back = createButton(locale.organizeImportsButtonBack(), "imports-back-button", new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
delegate.onBackButtonClicked();
|
||||
}
|
||||
});
|
||||
|
||||
next = createButton(locale.organizeImportsButtonNext(), "imports-next-button", new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
delegate.onNextButtonClicked();
|
||||
}
|
||||
});
|
||||
|
||||
Button cancel = createButton(locale.organizeImportsButtonCancel(), "imports-cancel-button", new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
hide();
|
||||
delegate.onCancelButtonClicked();
|
||||
}
|
||||
});
|
||||
|
||||
finish = createPrimaryButton(locale.organizeImportsButtonFinish(), "imports-finish-button", new ClickHandler() {
|
||||
@Override
|
||||
public void onClick(ClickEvent event) {
|
||||
delegate.onFinishButtonClicked();
|
||||
}
|
||||
});
|
||||
|
||||
addButtonToFooter(finish);
|
||||
addButtonToFooter(cancel);
|
||||
addButtonToFooter(next);
|
||||
addButtonToFooter(back);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<!--
|
||||
|
||||
Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
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:
|
||||
Codenvy, S.A. - initial API and implementation
|
||||
|
||||
-->
|
||||
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
|
||||
xmlns:g="urn:import:com.google.gwt.user.client.ui">
|
||||
<ui:with field="locale" type="org.eclipse.che.ide.ext.java.client.JavaLocalizationConstant"/>
|
||||
|
||||
<ui:style>
|
||||
.main {
|
||||
width: 515px;
|
||||
float: left;
|
||||
height: 200px;
|
||||
}
|
||||
</ui:style>
|
||||
|
||||
<g:SimplePanel addStyleNames="{style.main}">
|
||||
<g:ScrollPanel width="100%" height="100%">
|
||||
|
||||
<g:VerticalPanel ui:field="container" width="100%" height="100%"/>
|
||||
|
||||
</g:ScrollPanel>
|
||||
</g:SimplePanel>
|
||||
|
||||
</ui:UiBinder>
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
.label {
|
||||
float: left;
|
||||
margin-left: 6px;
|
||||
margin-left: 3px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -125,6 +125,15 @@ file.structure.action.description = Open File Structure Window
|
|||
show.inherited.members.label = Press 'Ctrl+F12' to show inherited members
|
||||
hide.inherited.members.label = Press 'Ctrl+F12' to hide inherited members
|
||||
|
||||
##### Organize Imports #####
|
||||
organize.imports.name = Organize Imports
|
||||
organize.imports.description = Organize Imports action generates the import statements in a compilation unit
|
||||
organize.imports.failed.title = Failed to process organize imports
|
||||
organize.imports.button.finish=Finish
|
||||
organize.imports.button.cancel=Cancel
|
||||
organize.imports.button.back=< Back
|
||||
organize.imports.button.next=Next >
|
||||
|
||||
##### Open Implementation #####
|
||||
open.implementation.action.name = Implementation(s)
|
||||
open.implementation.action.description = Open Implementation(s)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.ext.java.client.action;
|
||||
|
||||
import com.google.gwtmockito.GwtMockitoTestRunner;
|
||||
|
||||
import org.eclipse.che.ide.api.action.ActionEvent;
|
||||
import org.eclipse.che.ide.api.editor.EditorAgent;
|
||||
import org.eclipse.che.ide.ext.java.client.JavaLocalizationConstant;
|
||||
import org.eclipse.che.ide.ext.java.client.organizeimports.OrganizeImportsPresenter;
|
||||
import org.eclipse.che.ide.jseditor.client.texteditor.EmbeddedTextEditorPresenter;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Tests for {@link OrganizeImportsAction}.
|
||||
*
|
||||
* @author Valeriy Svydenko
|
||||
*/
|
||||
@RunWith(GwtMockitoTestRunner.class)
|
||||
public class OrganizeImportsActionTest {
|
||||
@Mock
|
||||
private OrganizeImportsPresenter organizeImportsPresenter;
|
||||
@Mock
|
||||
private EditorAgent editorAgent;
|
||||
@Mock
|
||||
private ActionEvent actionEvent;
|
||||
|
||||
@Mock
|
||||
private EmbeddedTextEditorPresenter editor;
|
||||
|
||||
@Mock(answer = Answers.RETURNS_MOCKS)
|
||||
private JavaLocalizationConstant locale;
|
||||
|
||||
@InjectMocks
|
||||
OrganizeImportsAction action;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
when(editorAgent.getActiveEditor()).thenReturn(editor);
|
||||
}
|
||||
|
||||
public void prepareAction() throws Exception {
|
||||
verify(locale).organizeImportsName();
|
||||
verify(locale).organizeImportsDescription();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actionShouldBePerformed() {
|
||||
action.actionPerformed(actionEvent);
|
||||
|
||||
verify(organizeImportsPresenter).organizeImports(editor);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actionShouldBePerformedAsProposal() {
|
||||
action.performAsProposal();
|
||||
|
||||
verify(organizeImportsPresenter).organizeImports(editor);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,232 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.ext.java.client.organizeimports;
|
||||
|
||||
import com.google.gwtmockito.GwtMockitoTestRunner;
|
||||
|
||||
import org.eclipse.che.api.project.gwt.client.ProjectServiceClient;
|
||||
import org.eclipse.che.api.promises.client.Operation;
|
||||
import org.eclipse.che.api.promises.client.Promise;
|
||||
import org.eclipse.che.api.workspace.shared.dto.ProjectConfigDto;
|
||||
import org.eclipse.che.ide.api.app.AppContext;
|
||||
import org.eclipse.che.ide.api.editor.EditorInput;
|
||||
import org.eclipse.che.ide.api.notification.NotificationManager;
|
||||
import org.eclipse.che.ide.api.project.node.HasProjectConfig;
|
||||
import org.eclipse.che.ide.api.project.tree.VirtualFile;
|
||||
import org.eclipse.che.ide.dto.DtoFactory;
|
||||
import org.eclipse.che.ide.ext.java.client.JavaLocalizationConstant;
|
||||
import org.eclipse.che.ide.ext.java.client.editor.JavaCodeAssistClient;
|
||||
import org.eclipse.che.ide.ext.java.shared.dto.ConflictImportDTO;
|
||||
import org.eclipse.che.ide.jseditor.client.document.Document;
|
||||
import org.eclipse.che.ide.jseditor.client.texteditor.TextEditor;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Matchers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* @author Valeriy Svydenko
|
||||
*/
|
||||
@RunWith(GwtMockitoTestRunner.class)
|
||||
public class OrganizeImportsPresenterTest {
|
||||
private final static String PATH = "/project/a/b/A.java";
|
||||
private final static String WS_ID = "wsId";
|
||||
|
||||
@Mock
|
||||
private OrganizeImportsView view;
|
||||
@Mock
|
||||
private AppContext appContext;
|
||||
@Mock
|
||||
private ProjectServiceClient projectService;
|
||||
@Mock
|
||||
private JavaCodeAssistClient javaCodeAssistClient;
|
||||
@Mock
|
||||
private DtoFactory dtoFactory;
|
||||
@Mock
|
||||
private JavaLocalizationConstant locale;
|
||||
@Mock
|
||||
private NotificationManager notificationManager;
|
||||
|
||||
private OrganizeImportsPresenter presenter;
|
||||
|
||||
@Mock
|
||||
private VirtualFile file;
|
||||
@Mock
|
||||
private EditorInput editorInput;
|
||||
@Mock
|
||||
private HasProjectConfig hasProjectConfig;
|
||||
@Mock
|
||||
private ProjectConfigDto projectConfigDto;
|
||||
@Mock
|
||||
private TextEditor editor;
|
||||
@Mock
|
||||
private Document document;
|
||||
|
||||
@Mock
|
||||
private Promise<List<ConflictImportDTO>> importsPromise;
|
||||
@Mock
|
||||
private Promise<Void> resolveConflictsPromise;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<Operation<List<ConflictImportDTO>>> importsOperation;
|
||||
@Captor
|
||||
private ArgumentCaptor<Operation<Void>> resolveConflictsOperation;
|
||||
|
||||
private ConflictImportDTO conflict1;
|
||||
private ConflictImportDTO conflict2;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
when(editor.getEditorInput()).thenReturn(editorInput);
|
||||
when(editorInput.getFile()).thenReturn(file);
|
||||
when(file.getProject()).thenReturn(hasProjectConfig);
|
||||
when(hasProjectConfig.getProjectConfig()).thenReturn(projectConfigDto);
|
||||
when(projectConfigDto.getPath()).thenReturn(PATH);
|
||||
when(file.getName()).thenReturn("A.java");
|
||||
when(file.getPath()).thenReturn(PATH);
|
||||
|
||||
when(appContext.getWorkspaceId()).thenReturn(WS_ID);
|
||||
|
||||
when(javaCodeAssistClient.organizeImports(anyString(), anyString())).thenReturn(importsPromise);
|
||||
when(importsPromise.then(Matchers.<Operation<List<ConflictImportDTO>>>anyObject())).thenReturn(importsPromise);
|
||||
|
||||
presenter = new OrganizeImportsPresenter(view,
|
||||
appContext,
|
||||
projectService,
|
||||
javaCodeAssistClient,
|
||||
dtoFactory,
|
||||
locale,
|
||||
notificationManager);
|
||||
|
||||
prepareConflicts();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void organizeImportsShouldBeDoneWithoutConflicts() throws Exception {
|
||||
presenter.organizeImports(editor);
|
||||
|
||||
verify(javaCodeAssistClient).organizeImports(PATH, "A");
|
||||
verify(importsPromise).then(importsOperation.capture());
|
||||
importsOperation.getValue().apply(Collections.emptyList());
|
||||
}
|
||||
|
||||
private void prepareConflicts() {
|
||||
conflict1 = Mockito.mock(ConflictImportDTO.class);
|
||||
conflict2 = Mockito.mock(ConflictImportDTO.class);
|
||||
|
||||
List<String> imports1 = Arrays.asList("import1", "import2");
|
||||
List<String> imports2 = Arrays.asList("import3", "import4");
|
||||
|
||||
when(conflict1.getTypeMatches()).thenReturn(imports1);
|
||||
when(conflict2.getTypeMatches()).thenReturn(imports2);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void openWindowForResolvingConflicts() throws Exception {
|
||||
showOrganizeImportsWindow();
|
||||
|
||||
verify(view).setSelectedImport("import1");
|
||||
|
||||
verify(view).setEnableBackButton(false);
|
||||
verify(view).setEnableFinishButton(false);
|
||||
verify(view).setEnableNextButton(true);
|
||||
|
||||
verify(view).show(conflict1);
|
||||
}
|
||||
|
||||
private void showOrganizeImportsWindow() throws Exception {
|
||||
presenter.organizeImports(editor);
|
||||
|
||||
List<ConflictImportDTO> result = Arrays.asList(conflict1, conflict2);
|
||||
|
||||
verify(javaCodeAssistClient).organizeImports(PATH, "A");
|
||||
verify(importsPromise).then(importsOperation.capture());
|
||||
importsOperation.getValue().apply(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void showNextConflictPage() throws Exception {
|
||||
when(view.getSelectedImport()).thenReturn("import1");
|
||||
|
||||
showOrganizeImportsWindow();
|
||||
presenter.onNextButtonClicked();
|
||||
|
||||
verify(view).getSelectedImport();
|
||||
verify(view).setSelectedImport("import3");
|
||||
verify(view).changePage(conflict2);
|
||||
|
||||
verify(view).setEnableBackButton(true);
|
||||
verify(view).setEnableFinishButton(true);
|
||||
verify(view).setEnableNextButton(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void showPreviousConflictPage() throws Exception {
|
||||
when(view.getSelectedImport()).thenReturn("import4");
|
||||
|
||||
showOrganizeImportsWindow();
|
||||
presenter.onNextButtonClicked();
|
||||
reset(view);
|
||||
presenter.onBackButtonClicked();
|
||||
|
||||
verify(view).getSelectedImport();
|
||||
verify(view).setSelectedImport("import4");
|
||||
verify(view).changePage(conflict1);
|
||||
|
||||
verify(view).setEnableBackButton(false);
|
||||
verify(view).setEnableFinishButton(true);
|
||||
verify(view).setEnableNextButton(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void focusShouldBeSetAfterClosingWindow() throws Exception {
|
||||
showOrganizeImportsWindow();
|
||||
presenter.onCancelButtonClicked();
|
||||
|
||||
verify(editor).setFocus();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void focusShouldBeSetAfterApplyingConflicts() throws Exception {
|
||||
when(view.getSelectedImport()).thenReturn("import1");
|
||||
when(dtoFactory.createDto(ConflictImportDTO.class)).thenReturn(conflict1);
|
||||
when(conflict1.withTypeMatches(Matchers.<List<String>>anyObject())).thenReturn(conflict1);
|
||||
when(javaCodeAssistClient.applyChosenImports(anyString(), anyString(), any())).thenReturn(resolveConflictsPromise);
|
||||
when(resolveConflictsPromise.then(Matchers.<Operation<Void>>anyObject())).thenReturn(resolveConflictsPromise);
|
||||
|
||||
showOrganizeImportsWindow();
|
||||
presenter.onFinishButtonClicked();
|
||||
|
||||
verify(resolveConflictsPromise).then(resolveConflictsOperation.capture());
|
||||
resolveConflictsOperation.getValue().apply(null);
|
||||
|
||||
verify(editor).setFocus();
|
||||
verify(view).hide();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2012-2016 Codenvy, S.A.
|
||||
* 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:
|
||||
* Codenvy, S.A. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.che.ide.ext.java.shared.dto;
|
||||
|
||||
import org.eclipse.che.dto.shared.DTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* DTO represents the information about the imports for the organize imports process.
|
||||
*
|
||||
* @author Valeriy Svydenko
|
||||
*/
|
||||
@DTO
|
||||
public interface ConflictImportDTO {
|
||||
/** Returns list of the possible imports for the current conflict. */
|
||||
List<String> getTypeMatches();
|
||||
|
||||
void setTypeMatches(List<String> typeMatches);
|
||||
|
||||
ConflictImportDTO withTypeMatches(List<String> typeMatches);
|
||||
}
|
||||
Loading…
Reference in New Issue