-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce MoreUnit Code Mining - Fix #94
- Loading branch information
Showing
7 changed files
with
319 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
152 changes: 152 additions & 0 deletions
152
org.moreunit.plugin/src/org/moreunit/codemining/JumpCodeMining.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
package org.moreunit.codemining; | ||
|
||
import static org.moreunit.elements.CorrespondingMemberRequest.newCorrespondingMemberRequest; | ||
|
||
import java.util.concurrent.CompletableFuture; | ||
import java.util.function.Consumer; | ||
|
||
import org.eclipse.core.runtime.IProgressMonitor; | ||
import org.eclipse.jdt.core.IClasspathEntry; | ||
import org.eclipse.jdt.core.IJavaElement; | ||
import org.eclipse.jdt.core.IMember; | ||
import org.eclipse.jdt.core.IMethod; | ||
import org.eclipse.jdt.core.IPackageFragmentRoot; | ||
import org.eclipse.jdt.core.ISourceRange; | ||
import org.eclipse.jdt.core.ISourceReference; | ||
import org.eclipse.jdt.core.IType; | ||
import org.eclipse.jdt.core.JavaModelException; | ||
import org.eclipse.jface.text.BadLocationException; | ||
import org.eclipse.jface.text.IDocument; | ||
import org.eclipse.jface.text.ITextViewer; | ||
import org.eclipse.jface.text.codemining.ICodeMining; | ||
import org.eclipse.jface.text.codemining.ICodeMiningProvider; | ||
import org.eclipse.jface.text.codemining.LineEndCodeMining; | ||
import org.eclipse.swt.events.MouseEvent; | ||
import org.eclipse.ui.IEditorPart; | ||
import org.moreunit.elements.CorrespondingMemberRequest; | ||
import org.moreunit.elements.CorrespondingMemberRequest.MemberType; | ||
import org.moreunit.elements.TypeFacade; | ||
import org.moreunit.preferences.Preferences; | ||
import org.moreunit.preferences.Preferences.MethodSearchMode; | ||
import org.moreunit.ui.EditorUI; | ||
|
||
/** | ||
* {@link ICodeMining} to "jump" from tested class/method to test class/method | ||
* and from test class/method to tested class/method | ||
*/ | ||
public class JumpCodeMining extends LineEndCodeMining | ||
{ | ||
|
||
private final IJavaElement element; | ||
|
||
public JumpCodeMining(IJavaElement element, IDocument document, ICodeMiningProvider provider) throws JavaModelException, BadLocationException | ||
{ | ||
super(document, getLineNumber(element, document), provider); | ||
this.element = element; | ||
} | ||
|
||
private static int getLineNumber(IJavaElement element, IDocument document) throws JavaModelException, BadLocationException | ||
{ | ||
ISourceRange r = ((ISourceReference) element).getNameRange(); | ||
int offset = r.getOffset(); | ||
return document.getLineOfOffset(offset); | ||
} | ||
|
||
@Override | ||
protected CompletableFuture<Void> doResolve(ITextViewer viewer, IProgressMonitor monitor) | ||
{ | ||
String testOrTested = isTest() ? "tested" : "test"; | ||
return CompletableFuture.runAsync(() -> { | ||
if(element instanceof IType) | ||
{ | ||
MethodSearchMode searchMode = Preferences.getInstance().getMethodSearchMode(element.getJavaProject()); | ||
|
||
TypeFacade typeFacade = TypeFacade.createFacade(((IMember) element).getCompilationUnit()); | ||
|
||
CorrespondingMemberRequest request = newCorrespondingMemberRequest() // | ||
.withExpectedResultType(MemberType.TYPE_OR_METHOD) // | ||
.withCurrentMethod(element instanceof IMethod method ? method : null) // | ||
.methodSearchMode(searchMode) // | ||
.build(); | ||
|
||
IMember memberToJump = typeFacade.getOneCorrespondingMember(request); | ||
if(memberToJump != null) | ||
{ | ||
setLabel(" Jump to " + testOrTested + " class"); | ||
} | ||
} | ||
else if(element instanceof IMethod) | ||
{ | ||
MethodSearchMode searchMode = Preferences.getInstance().getMethodSearchMode(element.getJavaProject()); | ||
|
||
TypeFacade typeFacade = TypeFacade.createFacade(((IMember) element).getCompilationUnit()); | ||
|
||
CorrespondingMemberRequest request = newCorrespondingMemberRequest() // | ||
.withExpectedResultType(MemberType.TYPE_OR_METHOD) // | ||
.withCurrentMethod(element instanceof IMethod method ? method : null) // | ||
.methodSearchMode(searchMode) // | ||
.build(); | ||
|
||
IMember memberToJump = typeFacade.getOneCorrespondingMember(request); | ||
if(memberToJump instanceof IMethod) | ||
{ | ||
setLabel(" Jump to " + testOrTested + " method"); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
private boolean isTest() | ||
{ | ||
IPackageFragmentRoot packageFragmentRoot = (IPackageFragmentRoot) element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); | ||
if(packageFragmentRoot != null) | ||
{ | ||
try | ||
{ | ||
IClasspathEntry resolvedClasspathEntry = packageFragmentRoot.getResolvedClasspathEntry(); | ||
return resolvedClasspathEntry != null && resolvedClasspathEntry.isTest(); | ||
} | ||
catch (JavaModelException e) | ||
{ | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
@Override | ||
public Consumer<MouseEvent> getAction() | ||
{ | ||
return e -> { | ||
MethodSearchMode searchMode = Preferences.getInstance().getMethodSearchMode(element.getJavaProject()); | ||
|
||
TypeFacade typeFacade = TypeFacade.createFacade(((IMember) element).getCompilationUnit()); | ||
|
||
CorrespondingMemberRequest request = newCorrespondingMemberRequest() // | ||
.withExpectedResultType(MemberType.TYPE_OR_METHOD) // | ||
.withCurrentMethod(element instanceof IMethod method ? method : null) // | ||
.methodSearchMode(searchMode) // | ||
.build(); | ||
|
||
IMember memberToJump = typeFacade.getOneCorrespondingMember(request); | ||
if(memberToJump != null) | ||
{ | ||
jumpToMember(memberToJump); | ||
} | ||
}; | ||
} | ||
|
||
private void jumpToMember(IMember memberToJump) | ||
{ | ||
EditorUI editorUI = new EditorUI(); | ||
if(memberToJump instanceof IMethod) | ||
{ | ||
IMethod methodToJump = (IMethod) memberToJump; | ||
IEditorPart openedEditor = editorUI.open(methodToJump.getDeclaringType().getParent()); | ||
editorUI.reveal(openedEditor, methodToJump); | ||
} | ||
else | ||
{ | ||
editorUI.open(memberToJump.getParent()); | ||
} | ||
} | ||
} |
113 changes: 113 additions & 0 deletions
113
org.moreunit.plugin/src/org/moreunit/codemining/MoreUnitCodeMiningProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
package org.moreunit.codemining; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.concurrent.CompletableFuture; | ||
|
||
import org.eclipse.core.runtime.IProgressMonitor; | ||
import org.eclipse.jdt.core.IJavaElement; | ||
import org.eclipse.jdt.core.IMethod; | ||
import org.eclipse.jdt.core.IType; | ||
import org.eclipse.jdt.core.ITypeRoot; | ||
import org.eclipse.jdt.core.JavaModelException; | ||
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility; | ||
import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor; | ||
import org.eclipse.jface.text.BadLocationException; | ||
import org.eclipse.jface.text.ITextViewer; | ||
import org.eclipse.jface.text.codemining.AbstractCodeMiningProvider; | ||
import org.eclipse.jface.text.codemining.ICodeMining; | ||
import org.eclipse.jface.text.codemining.ICodeMiningProvider; | ||
import org.eclipse.ui.texteditor.ITextEditor; | ||
import org.moreunit.preferences.Preferences; | ||
|
||
/** | ||
* {@link ICodeMiningProvider} for MoreUnit. | ||
*/ | ||
public class MoreUnitCodeMiningProvider extends AbstractCodeMiningProvider | ||
{ | ||
|
||
private Preferences preferences; | ||
|
||
public MoreUnitCodeMiningProvider() | ||
{ | ||
this.preferences = Preferences.getInstance(); | ||
} | ||
|
||
@Override | ||
public CompletableFuture<List< ? extends ICodeMining>> provideCodeMinings(ITextViewer viewer, IProgressMonitor monitor) | ||
{ | ||
ITextEditor textEditor = super.getAdapter(ITextEditor.class); | ||
ITypeRoot unit = EditorUtility.getEditorInputJavaElement(textEditor, true); | ||
if(unit == null || ! preferences.shouldEnableMoreUnitCodeMining(unit.getJavaProject())) | ||
{ | ||
return CompletableFuture.completedFuture(Collections.emptyList()); | ||
} | ||
return CompletableFuture.supplyAsync(() -> { | ||
monitor.isCanceled(); | ||
try | ||
{ | ||
IJavaElement[] elements = unit.getChildren(); | ||
List<ICodeMining> minings = new ArrayList<>(elements.length); | ||
collectMinings(unit, textEditor, unit.getChildren(), minings, viewer, monitor); | ||
return minings; | ||
} | ||
catch (JavaModelException e) | ||
{ | ||
// Should never occur | ||
} | ||
return Collections.emptyList(); | ||
}); | ||
} | ||
|
||
private void collectMinings(ITypeRoot unit, ITextEditor textEditor, IJavaElement[] elements, List<ICodeMining> minings, ITextViewer viewer, IProgressMonitor monitor) throws JavaModelException | ||
{ | ||
|
||
if(! (textEditor instanceof JavaEditor)) | ||
{ | ||
return; | ||
} | ||
|
||
for (IJavaElement element : elements) | ||
{ | ||
if(monitor.isCanceled()) | ||
{ | ||
return; | ||
} | ||
if(element.getElementType() == IJavaElement.TYPE) | ||
{ | ||
collectMinings(unit, textEditor, ((IType) element).getChildren(), minings, viewer, monitor); | ||
} | ||
else if((element.getElementType() != IJavaElement.METHOD)) | ||
{ | ||
continue; | ||
} | ||
// support methods, classes | ||
boolean addMining = false; | ||
if(element instanceof IType) | ||
{ | ||
IType type = (IType) element; | ||
if(type.isClass()) | ||
{ | ||
addMining = true; | ||
} | ||
} | ||
else if(element instanceof IMethod) | ||
{ | ||
addMining = true; | ||
} | ||
if(addMining) | ||
{ | ||
try | ||
{ | ||
minings.add(new JumpCodeMining(element, viewer.getDocument(), this)); | ||
} | ||
catch (BadLocationException e) | ||
{ | ||
// Should never occur | ||
} | ||
} | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters