mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -480,7 +480,7 @@ public class CompileDriver {
|
||||
final Set<File> genSourceRoots = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
|
||||
final CompilerConfiguration config = CompilerConfiguration.getInstance(myProject);
|
||||
for (Module module : affectedModules) {
|
||||
if (config.getAnnotationProcessingConfiguration(module).isEnabled()) {
|
||||
if (!module.isDisposed() && config.getAnnotationProcessingConfiguration(module).isEnabled()) {
|
||||
final String path = CompilerPaths.getAnnotationProcessorsGenerationPath(module);
|
||||
if (path != null) {
|
||||
genSourceRoots.add(new File(path));
|
||||
|
||||
@@ -78,7 +78,7 @@ public class CompilerPathsEx extends CompilerPaths {
|
||||
public static String[] getOutputPaths(Module[] modules) {
|
||||
final Set<String> outputPaths = new OrderedSet<String>();
|
||||
for (Module module : modules) {
|
||||
final CompilerModuleExtension compilerModuleExtension = CompilerModuleExtension.getInstance(module);
|
||||
final CompilerModuleExtension compilerModuleExtension = !module.isDisposed()? CompilerModuleExtension.getInstance(module) : null;
|
||||
if (compilerModuleExtension == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -212,6 +212,7 @@ public class TargetElementUtil extends TargetElementUtilBase {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<PsiElement> getTargetCandidates(final PsiReference reference) {
|
||||
PsiElement parent = reference.getElement().getParent();
|
||||
|
||||
@@ -133,7 +133,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
@Nullable ASTNode originalTree,
|
||||
@Nullable MyTreeStructure parentLightTree) {
|
||||
this(project, containingFile, parserDefinition.getWhitespaceTokens(), parserDefinition.getCommentTokens(), lexer, charTable, text,
|
||||
originalTree, parentLightTree, 0);
|
||||
originalTree, parentLightTree, null);
|
||||
}
|
||||
|
||||
public PsiBuilderImpl(Project project,
|
||||
@@ -145,7 +145,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
@NotNull final CharSequence text,
|
||||
@Nullable ASTNode originalTree,
|
||||
@Nullable MyTreeStructure parentLightTree) {
|
||||
this(project, containingFile, whiteSpaces, comments, lexer, charTable, text, originalTree, parentLightTree, 0);
|
||||
this(project, containingFile, whiteSpaces, comments, lexer, charTable, text, originalTree, parentLightTree, null);
|
||||
}
|
||||
|
||||
private PsiBuilderImpl(Project project,
|
||||
@@ -157,7 +157,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
@NotNull final CharSequence text,
|
||||
@Nullable ASTNode originalTree,
|
||||
@Nullable MyTreeStructure parentLightTree,
|
||||
int offset) {
|
||||
LazyParseableToken parentToken) {
|
||||
myProject = project;
|
||||
myFile = containingFile;
|
||||
|
||||
@@ -170,9 +170,9 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
myCharTable = charTable;
|
||||
myOriginalTree = originalTree;
|
||||
myParentLightTree = parentLightTree;
|
||||
myOffset = offset;
|
||||
myOffset = parentToken != null ? parentToken.getStartOffset() : 0;
|
||||
|
||||
cacheLexemes();
|
||||
cacheLexemes(parentToken);
|
||||
}
|
||||
|
||||
public PsiBuilderImpl(@NotNull final Project project,
|
||||
@@ -190,10 +190,41 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
@NotNull final LighterLazyParseableNode chameleon,
|
||||
@NotNull final CharSequence text) {
|
||||
this(project, chameleon.getContainingFile(), parserDefinition.getWhitespaceTokens(), parserDefinition.getCommentTokens(), lexer,
|
||||
chameleon.getCharTable(), text, null, ((LazyParseableToken)chameleon).myParent, chameleon.getStartOffset());
|
||||
chameleon.getCharTable(), text, null, ((LazyParseableToken)chameleon).myParent, ((LazyParseableToken)chameleon)
|
||||
);
|
||||
}
|
||||
|
||||
private void cacheLexemes() {
|
||||
private void cacheLexemes(LazyParseableToken parentToken) {
|
||||
int[] lexStarts = null;
|
||||
IElementType[] lexTypes = null;
|
||||
int lexemeCount = -1;
|
||||
boolean doLexingOptimizationCorrectionCheck = false;
|
||||
|
||||
if (parentToken != null) {
|
||||
// there are two types of lazy parseable tokens out there: collapsed out of individual tokens or single token that needs to be expanded
|
||||
// in first case parent PsiBuilder has all our text lexed so no need to do it again
|
||||
int tokenCount = parentToken.myEndIndex - parentToken.myStartIndex;
|
||||
if (tokenCount != 1) { // not expand single lazy parseable token case
|
||||
lexStarts = new int[tokenCount + 1];
|
||||
System.arraycopy(parentToken.myBuilder.myLexStarts, parentToken.myStartIndex, lexStarts, 0, tokenCount);
|
||||
int diff = parentToken.myBuilder.myLexStarts[parentToken.myStartIndex];
|
||||
for(int i = 0; i < tokenCount; ++i) lexStarts[i] -= diff;
|
||||
lexStarts[tokenCount] = myText.length();
|
||||
|
||||
lexTypes = new IElementType[tokenCount];
|
||||
System.arraycopy(parentToken.myBuilder.myLexTypes, parentToken.myStartIndex, lexTypes, 0, tokenCount);
|
||||
lexemeCount = tokenCount;
|
||||
}
|
||||
ProgressIndicatorProvider.checkCanceled();
|
||||
|
||||
if (!doLexingOptimizationCorrectionCheck) {
|
||||
myLexStarts = lexStarts;
|
||||
myLexTypes = lexTypes;
|
||||
myLexemeCount = lexemeCount;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int approxLexCount = Math.max(10, myText.length() / 5);
|
||||
|
||||
myLexStarts = new int[approxLexCount];
|
||||
@@ -216,7 +247,8 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
final IElementType tokenType = myLexer.getTokenType();
|
||||
sb.append("Token sequence broken")
|
||||
.append("\n this: '").append(myLexer.getTokenText()).append("' (").append(tokenType).append(':')
|
||||
.append(tokenType != null ? tokenType.getLanguage() : null).append(") ").append(tokenStart).append(":").append(myLexer.getTokenEnd());
|
||||
.append(tokenType != null ? tokenType.getLanguage() : null).append(") ").append(tokenStart).append(":")
|
||||
.append(myLexer.getTokenEnd());
|
||||
if (i > 0) {
|
||||
final int prevStart = myLexStarts[i - 1];
|
||||
sb.append("\n prev: '").append(myText.subSequence(prevStart, offset)).append("' (").append(myLexTypes[i - 1]).append(':')
|
||||
@@ -238,6 +270,19 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
|
||||
myLexemeCount = i;
|
||||
clearCachedTokenType();
|
||||
|
||||
//noinspection ConstantConditions
|
||||
if (doLexingOptimizationCorrectionCheck) {
|
||||
if (lexemeCount != -1) {
|
||||
assert lexemeCount == myLexemeCount;
|
||||
for(int j = 0; j < lexemeCount; ++j) {
|
||||
if (myLexStarts[j] != lexStarts[j] || myLexTypes[j] != lexTypes[j]) {
|
||||
assert false;
|
||||
}
|
||||
}
|
||||
assert myLexStarts[lexemeCount] == lexStarts[lexemeCount];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1215,8 +1260,8 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder {
|
||||
CharSequence context =
|
||||
index < myLexStarts.length ? myText.subSequence(Math.max(0, myLexStarts[index] - 1000), myLexStarts[index]) : "<none>";
|
||||
String language = myFile != null ? myFile.getLanguage() + ", " : "";
|
||||
LOG.error(UNBALANCED_MESSAGE + "\n" +
|
||||
"language: " + language + "\n" +
|
||||
LOG.error(UNBALANCED_MESSAGE + "\n" +
|
||||
"language: " + language + "\n" +
|
||||
"context: '" + context + "'");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -336,10 +336,11 @@ public class TargetElementUtilBase {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<PsiElement> getTargetCandidates(PsiReference reference) {
|
||||
if (reference instanceof PsiPolyVariantReference) {
|
||||
final ResolveResult[] results = ((PsiPolyVariantReference)reference).multiResolve(false);
|
||||
final ArrayList<PsiElement> navigatableResults = new ArrayList<PsiElement>(results.length);
|
||||
List<PsiElement> navigatableResults = new ArrayList<PsiElement>(results.length);
|
||||
|
||||
for(ResolveResult r:results) {
|
||||
PsiElement element = r.getElement();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -558,7 +558,7 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
|
||||
}
|
||||
}
|
||||
|
||||
final PsiNameIdentifierOwner element = GotoDeclarationAction.findElementToShowUsagesOf(editor, file, offset);
|
||||
final PsiNameIdentifierOwner element = GotoDeclarationAction.findElementToShowUsagesOf(editor, offset);
|
||||
if (element != null) {
|
||||
PsiElement identifier = element.getNameIdentifier();
|
||||
return new Info(identifier){
|
||||
|
||||
+6
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -83,8 +83,8 @@ public class GotoDeclarationAction extends BaseCodeInsightAction implements Code
|
||||
FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.goto.declaration");
|
||||
|
||||
if (elements.length != 1) {
|
||||
if (elements.length == 0) {
|
||||
PsiElement element = findElementToShowUsagesOf(editor, file, editor.getCaretModel().getOffset());
|
||||
if (elements.length == 0 && suggestCandidates(TargetElementUtilBase.findReference(editor, offset)).isEmpty()) {
|
||||
PsiElement element = findElementToShowUsagesOf(editor, editor.getCaretModel().getOffset());
|
||||
if (element != null) {
|
||||
ShowUsagesAction showUsages = (ShowUsagesAction)ActionManager.getInstance().getAction(ShowUsagesAction.ID);
|
||||
RelativePoint popupPosition = JBPopupFactory.getInstance().guessBestPopupLocation(editor);
|
||||
@@ -111,7 +111,7 @@ public class GotoDeclarationAction extends BaseCodeInsightAction implements Code
|
||||
}
|
||||
}
|
||||
|
||||
public static PsiNameIdentifierOwner findElementToShowUsagesOf(@NotNull Editor editor, @NotNull PsiFile file, int offset) {
|
||||
public static PsiNameIdentifierOwner findElementToShowUsagesOf(@NotNull Editor editor, int offset) {
|
||||
PsiElement elementAt = TargetElementUtilBase.getInstance().findTargetElement(editor, TargetElementUtilBase.ELEMENT_NAME_ACCEPTED, offset);
|
||||
if (elementAt instanceof PsiNameIdentifierOwner) {
|
||||
return (PsiNameIdentifierOwner)elementAt;
|
||||
@@ -184,7 +184,8 @@ public class GotoDeclarationAction extends BaseCodeInsightAction implements Code
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Collection<PsiElement> suggestCandidates(final PsiReference reference) {
|
||||
@NotNull
|
||||
private static Collection<PsiElement> suggestCandidates(@Nullable PsiReference reference) {
|
||||
if (reference == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
+18
-16
@@ -325,12 +325,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
|
||||
appendPairedInspectionsForUnfairTools(globalTools, globalSimpleTools, localTools);
|
||||
|
||||
((RefManagerImpl)getRefManager()).initializeAnnotators();
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runGlobalTools(scope, inspectionManager, globalTools);
|
||||
}
|
||||
});
|
||||
runGlobalTools(scope, inspectionManager, globalTools);
|
||||
|
||||
if (runGlobalToolsOnly) return;
|
||||
|
||||
@@ -497,15 +492,16 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
|
||||
return PsiDocumentManager.getInstance(getProject()).getDocument(file);
|
||||
}
|
||||
|
||||
private void runGlobalTools(@NotNull AnalysisScope scope, @NotNull InspectionManager inspectionManager, @NotNull List<Tools> globalTools) {
|
||||
private void runGlobalTools(@NotNull final AnalysisScope scope, @NotNull final InspectionManager inspectionManager, @NotNull List<Tools> globalTools) {
|
||||
LOG.assertTrue(!ApplicationManager.getApplication().isReadAccessAllowed(), "Must not run under read action, too unresponsive");
|
||||
final List<InspectionToolWrapper> needRepeatSearchRequest = new ArrayList<InspectionToolWrapper>();
|
||||
|
||||
final boolean surelyNoExternalUsages = scope.getScopeType() == AnalysisScope.PROJECT;
|
||||
final boolean canBeExternalUsages = scope.getScopeType() != AnalysisScope.PROJECT;
|
||||
for (Tools tools : globalTools) {
|
||||
for (ScopeToolState state : tools.getTools()) {
|
||||
InspectionToolWrapper toolWrapper = state.getTool();
|
||||
GlobalInspectionTool tool = (GlobalInspectionTool)toolWrapper.getTool();
|
||||
InspectionToolPresentation toolPresentation = getPresentation(toolWrapper);
|
||||
final InspectionToolWrapper toolWrapper = state.getTool();
|
||||
final GlobalInspectionTool tool = (GlobalInspectionTool)toolWrapper.getTool();
|
||||
final InspectionToolPresentation toolPresentation = getPresentation(toolWrapper);
|
||||
try {
|
||||
if (tool.isGraphNeeded()) {
|
||||
try {
|
||||
@@ -516,11 +512,17 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
tool.runInspection(scope, inspectionManager, this, toolPresentation);
|
||||
//skip phase when we are sure that scope already contains everything
|
||||
if (!surelyNoExternalUsages && tool.queryExternalUsagesRequests(inspectionManager, this, toolPresentation)) {
|
||||
needRepeatSearchRequest.add(toolWrapper);
|
||||
}
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
tool.runInspection(scope, inspectionManager, GlobalInspectionContextImpl.this, toolPresentation);
|
||||
//skip phase when we are sure that scope already contains everything
|
||||
if (canBeExternalUsages &&
|
||||
tool.queryExternalUsagesRequests(inspectionManager, GlobalInspectionContextImpl.this, toolPresentation)) {
|
||||
needRepeatSearchRequest.add(toolWrapper);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
|
||||
@@ -157,6 +157,7 @@
|
||||
<projectService
|
||||
serviceInterface="git4idea.config.GitVcsSettings"
|
||||
serviceImplementation="git4idea.config.GitVcsSettings"/>
|
||||
<projectService serviceImplementation="git4idea.config.GitRebaseSettings"/>
|
||||
<projectService serviceImplementation="git4idea.config.GitSharedSettings" />
|
||||
<projectService
|
||||
serviceInterface="git4idea.config.GitExecutableValidator"
|
||||
|
||||
@@ -17,16 +17,17 @@ package git4idea.actions;
|
||||
|
||||
import com.intellij.dvcs.DvcsUtil;
|
||||
import com.intellij.openapi.application.AccessToken;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.VcsNotifier;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.commands.Git;
|
||||
import git4idea.commands.GitCommandResult;
|
||||
import git4idea.commands.GitLineHandler;
|
||||
import git4idea.commands.GitTask;
|
||||
import git4idea.commands.GitTaskResult;
|
||||
import git4idea.commands.GitTaskResultHandlerAdapter;
|
||||
import git4idea.i18n.GitBundle;
|
||||
import git4idea.rebase.GitInteractiveRebaseEditorHandler;
|
||||
import git4idea.rebase.GitRebaseEditorService;
|
||||
@@ -50,7 +51,7 @@ public abstract class GitRebaseActionBase extends GitRepositoryAction {
|
||||
@NotNull final VirtualFile defaultRoot,
|
||||
final Set<VirtualFile> affectedRoots,
|
||||
final List<VcsException> exceptions) throws VcsException {
|
||||
GitLineHandler h = createHandler(project, gitRoots, defaultRoot);
|
||||
final GitLineHandler h = createHandler(project, gitRoots, defaultRoot);
|
||||
if (h == null) {
|
||||
return;
|
||||
}
|
||||
@@ -63,34 +64,32 @@ public abstract class GitRebaseActionBase extends GitRepositoryAction {
|
||||
affectedRoots.add(root);
|
||||
|
||||
service.configureHandler(h, editor.getHandlerNo());
|
||||
GitTask task = new GitTask(project, h, GitBundle.getString("rebasing.title"));
|
||||
task.executeInBackground(false, new GitTaskResultHandlerAdapter() {
|
||||
new Task.Backgroundable(project, GitBundle.getString("rebasing.title"), false) {
|
||||
@Override
|
||||
protected void run(GitTaskResult taskResult) {
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
AccessToken token = DvcsUtil.workingTreeChangeStarted(project);
|
||||
try {
|
||||
GitCommandResult result = ServiceManager.getService(Git.class).runCommand(h);
|
||||
editor.close();
|
||||
GitRepositoryManager manager = GitUtil.getRepositoryManager(project);
|
||||
manager.updateRepository(root);
|
||||
root.refresh(false, true);
|
||||
notifyAboutResult(taskResult, resultListener, exceptions, project);
|
||||
notifyAboutResult(result, resultListener, exceptions, project);
|
||||
}
|
||||
finally {
|
||||
DvcsUtil.workingTreeChangeFinished(project, token);
|
||||
}
|
||||
}
|
||||
});
|
||||
}.queue();
|
||||
}
|
||||
|
||||
private static void notifyAboutResult(GitTaskResult taskResult,
|
||||
GitRebaseLineListener resultListener,
|
||||
List<VcsException> exceptions,
|
||||
Project project) {
|
||||
if (taskResult == GitTaskResult.CANCELLED) {
|
||||
return;
|
||||
}
|
||||
private static void notifyAboutResult(@NotNull GitCommandResult commandResult,
|
||||
@NotNull GitRebaseLineListener resultListener,
|
||||
@NotNull List<VcsException> exceptions,
|
||||
@NotNull Project project) {
|
||||
final GitRebaseLineListener.Result result = resultListener.getResult();
|
||||
String messageId;
|
||||
String message = null;
|
||||
boolean isError = true;
|
||||
switch (result.status) {
|
||||
case CONFLICT:
|
||||
@@ -98,6 +97,7 @@ public abstract class GitRebaseActionBase extends GitRepositoryAction {
|
||||
break;
|
||||
case ERROR:
|
||||
messageId = "rebase.result.error";
|
||||
message = commandResult.getErrorOutputAsHtmlString();
|
||||
break;
|
||||
case CANCELLED:
|
||||
// we do not need to show a message if editing was cancelled.
|
||||
@@ -115,15 +115,9 @@ public abstract class GitRebaseActionBase extends GitRepositoryAction {
|
||||
messageId = null;
|
||||
}
|
||||
|
||||
String message;
|
||||
String title;
|
||||
if (messageId != null) {
|
||||
String title = GitBundle.message(messageId + ".title");
|
||||
if (message == null) {
|
||||
message = GitBundle.message(messageId, result.current, result.total);
|
||||
title = GitBundle.message(messageId + ".title");
|
||||
}
|
||||
else {
|
||||
message = "Rebase finished: " + StringUtil.capitalize(StringUtil.toLowerCase(result.status.name()));
|
||||
title = "";
|
||||
}
|
||||
|
||||
if (isError) {
|
||||
|
||||
@@ -42,6 +42,14 @@ public interface Git {
|
||||
@NotNull
|
||||
GitCommandResult runCommand(@NotNull Computable<GitLineHandler> handlerConstructor);
|
||||
|
||||
/**
|
||||
* A generic method to run a Git command, when existing methods are not sufficient. <br/>
|
||||
* Can be used instead of {@link #runCommand(Computable)} if the operation will not need to be repeated for sure
|
||||
* (e.g. it is a completely local operation).
|
||||
*/
|
||||
@NotNull
|
||||
GitCommandResult runCommand(@NotNull GitLineHandler handler);
|
||||
|
||||
@NotNull
|
||||
GitCommandResult init(@NotNull Project project, @NotNull VirtualFile root, @NotNull GitLineHandlerListener... listeners);
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ import static java.util.Collections.singleton;
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
@SuppressWarnings("StringToUpperCaseOrToLowerCaseWithoutLocale")
|
||||
public class GitImpl implements Git {
|
||||
|
||||
private final Logger LOG = Logger.getInstance(Git.class);
|
||||
@@ -624,13 +625,24 @@ public class GitImpl implements Git {
|
||||
public GitCommandResult runCommand(@NotNull Computable<GitLineHandler> handlerConstructor) {
|
||||
return run(handlerConstructor);
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public GitCommandResult runCommand(@NotNull final GitLineHandler handler) {
|
||||
return runCommand(new Computable<GitLineHandler>() {
|
||||
@Override
|
||||
public GitLineHandler compute() {
|
||||
return handler;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the line looks line an error message
|
||||
*/
|
||||
private static boolean isError(String text) {
|
||||
for (String indicator : ERROR_INDICATORS) {
|
||||
if (text.startsWith(indicator.toLowerCase())) {
|
||||
if (text.trim().toLowerCase().startsWith(indicator.toLowerCase())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -640,7 +652,7 @@ public class GitImpl implements Git {
|
||||
// could be upper-cased, so should check case-insensitively
|
||||
public static final String[] ERROR_INDICATORS = {
|
||||
"error", "remote: error", "fatal",
|
||||
"Cannot apply", "Could not", "Interactive rebase already started", "refusing to pull", "cannot rebase:", "conflict",
|
||||
"Cannot", "Could not", "Interactive rebase already started", "refusing to pull", "cannot rebase:", "conflict",
|
||||
"unable"
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package git4idea.config;
|
||||
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.components.StoragePathMacros;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@State(name = "Git.Rebase.Settings", storages = {@Storage(file = StoragePathMacros.WORKSPACE_FILE)})
|
||||
public class GitRebaseSettings implements PersistentStateComponent<GitRebaseSettings.State> {
|
||||
|
||||
private State myState = new State();
|
||||
|
||||
public static class State {
|
||||
public boolean INTERACTIVE = true;
|
||||
public boolean PRESERVE_MERGES = false;
|
||||
public boolean SHOW_TAGS = false;
|
||||
public boolean SHOW_REMOTE_BRANCHES = false;
|
||||
public String ONTO = null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public State getState() {
|
||||
return myState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(State state) {
|
||||
myState = state;
|
||||
}
|
||||
|
||||
public boolean isInteractive() {
|
||||
return myState.INTERACTIVE;
|
||||
}
|
||||
|
||||
public void setInteractive(boolean interactive) {
|
||||
myState.INTERACTIVE = interactive;
|
||||
}
|
||||
|
||||
public boolean isPreserveMerges() {
|
||||
return myState.PRESERVE_MERGES;
|
||||
}
|
||||
|
||||
public void setPreserveMerges(boolean preserveMerges) {
|
||||
myState.PRESERVE_MERGES = preserveMerges;
|
||||
}
|
||||
|
||||
public boolean showTags() {
|
||||
return myState.SHOW_TAGS;
|
||||
}
|
||||
|
||||
public void setShowTags(boolean showTags) {
|
||||
myState.SHOW_TAGS = showTags;
|
||||
}
|
||||
|
||||
public boolean showRemoteBranches() {
|
||||
return myState.SHOW_REMOTE_BRANCHES;
|
||||
}
|
||||
|
||||
public void setShowRemoteBranches(boolean showRemoteBranches) {
|
||||
myState.SHOW_REMOTE_BRANCHES = showRemoteBranches;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getOnto() {
|
||||
return myState.ONTO;
|
||||
}
|
||||
|
||||
public void setOnto(@Nullable String onto) {
|
||||
myState.ONTO = onto;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -290,7 +290,6 @@ rebase.result.cancelled=The rebase process was cancelled.
|
||||
rebase.result.conflict.title=Rebase Suspended
|
||||
rebase.result.conflict=Stopped rebasing because of conflict ({0}/{1}).\nResolve conflicts and continue the rebase process.
|
||||
rebase.result.error.title=Rebase Error
|
||||
rebase.result.error=Stopped rebasing because of error while rebasing ({0}/{1}).\nCheck vcs console for details.
|
||||
rebase.show.remote.branches.tooltip=If selected, remote branches are shown in drop down as well.
|
||||
rebase.show.remote.branches=Show Re&mote Branches
|
||||
rebase.show.tags.tooltip=Show tags in \"from\" and \"onto\" comboboxes.
|
||||
|
||||
@@ -15,10 +15,12 @@
|
||||
*/
|
||||
package git4idea.rebase;
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.DocumentAdapter;
|
||||
@@ -27,12 +29,15 @@ import git4idea.branch.GitBranchUtil;
|
||||
import git4idea.commands.GitCommand;
|
||||
import git4idea.commands.GitLineHandler;
|
||||
import git4idea.config.GitConfigUtil;
|
||||
import git4idea.config.GitRebaseSettings;
|
||||
import git4idea.i18n.GitBundle;
|
||||
import git4idea.merge.GitMergeUtil;
|
||||
import git4idea.repo.GitRemote;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.ui.GitReferenceValidator;
|
||||
import git4idea.util.GitUIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
@@ -115,7 +120,7 @@ public class GitRebaseDialog extends DialogWrapper {
|
||||
/**
|
||||
* The current branch
|
||||
*/
|
||||
protected GitBranch myCurrentBranch;
|
||||
@Nullable protected GitBranch myCurrentBranch;
|
||||
/**
|
||||
* The tags
|
||||
*/
|
||||
@@ -128,6 +133,9 @@ public class GitRebaseDialog extends DialogWrapper {
|
||||
* The validator for from field
|
||||
*/
|
||||
private final GitReferenceValidator myFromValidator;
|
||||
@NotNull private final GitRebaseSettings mySettings;
|
||||
|
||||
@Nullable private final String myOriginalOntoBranch;
|
||||
|
||||
/**
|
||||
* A constructor
|
||||
@@ -142,6 +150,7 @@ public class GitRebaseDialog extends DialogWrapper {
|
||||
setOKButtonText(GitBundle.getString("rebase.button"));
|
||||
init();
|
||||
myProject = project;
|
||||
mySettings = ServiceManager.getService(myProject, GitRebaseSettings.class);
|
||||
final Runnable validateRunnable = new Runnable() {
|
||||
public void run() {
|
||||
validateFields();
|
||||
@@ -157,11 +166,50 @@ public class GitRebaseDialog extends DialogWrapper {
|
||||
validateFields();
|
||||
}
|
||||
});
|
||||
|
||||
setupBranches();
|
||||
setupStrategy();
|
||||
|
||||
myInteractiveCheckBox.setSelected(mySettings.isInteractive());
|
||||
myPreserveMergesCheckBox.setSelected(mySettings.isPreserveMerges());
|
||||
myShowTagsCheckBox.setSelected(mySettings.showTags());
|
||||
myShowRemoteBranchesCheckBox.setSelected(mySettings.showRemoteBranches());
|
||||
overwriteOntoForCurrentBranch(mySettings);
|
||||
|
||||
myOriginalOntoBranch = GitUIUtil.getTextField(myOntoComboBox).getText();
|
||||
|
||||
validateFields();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JComponent getPreferredFocusedComponent() {
|
||||
return myOntoComboBox;
|
||||
}
|
||||
|
||||
private void overwriteOntoForCurrentBranch(@NotNull GitRebaseSettings settings) {
|
||||
String onto = settings.getOnto();
|
||||
if (onto != null && !onto.equals(myBranchComboBox.getSelectedItem())) {
|
||||
if (!isValidRevision(onto)) {
|
||||
mySettings.setOnto(null);
|
||||
}
|
||||
else {
|
||||
myOntoComboBox.setSelectedItem(onto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValidRevision(@NotNull String revisionExpression) {
|
||||
try {
|
||||
GitRevisionNumber.resolve(myProject, gitRoot(), revisionExpression);
|
||||
return true;
|
||||
}
|
||||
catch (VcsException e) {
|
||||
LOG.debug(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public GitLineHandler handler() {
|
||||
GitLineHandler h = new GitLineHandler(myProject, gitRoot(), GitCommand.REBASE);
|
||||
h.setStdoutSuppressed(false);
|
||||
@@ -195,6 +243,27 @@ public class GitRebaseDialog extends DialogWrapper {
|
||||
return h;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doOKAction() {
|
||||
try {
|
||||
rememberFields();
|
||||
}
|
||||
finally {
|
||||
super.doOKAction();
|
||||
}
|
||||
}
|
||||
|
||||
private void rememberFields() {
|
||||
mySettings.setInteractive(myInteractiveCheckBox.isSelected());
|
||||
mySettings.setPreserveMerges(myPreserveMergesCheckBox.isSelected());
|
||||
mySettings.setShowTags(myShowTagsCheckBox.isSelected());
|
||||
mySettings.setShowRemoteBranches(myShowRemoteBranchesCheckBox.isSelected());
|
||||
String onto = StringUtil.nullize(GitUIUtil.getTextField(myOntoComboBox).getText(), true);
|
||||
if (onto != null && !onto.equals(myOriginalOntoBranch)) {
|
||||
mySettings.setOnto(onto);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup strategy
|
||||
*/
|
||||
|
||||
@@ -22,7 +22,9 @@ import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.Cell;
|
||||
import com.intellij.ui.ColoredTableCellRenderer;
|
||||
import com.intellij.ui.TableSpeedSearch;
|
||||
import com.intellij.ui.speedSearch.SpeedSearchUtil;
|
||||
import com.intellij.ui.table.JBTable;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ListWithSelection;
|
||||
@@ -132,6 +134,14 @@ public class GitRebaseEditor extends DialogWrapper {
|
||||
actionColumn.setCellEditor(new DefaultCellEditor(editorComboBox));
|
||||
actionColumn.setCellRenderer(ComboBoxTableCellRenderer.INSTANCE);
|
||||
|
||||
myCommitsTable.setDefaultRenderer(String.class, new ColoredTableCellRenderer() {
|
||||
@Override
|
||||
protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) {
|
||||
append(value.toString());
|
||||
SpeedSearchUtil.applySpeedSearchHighlighting(myCommitsTable, this, true, selected);
|
||||
}
|
||||
});
|
||||
|
||||
myCommitsTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||
public void valueChanged(final ListSelectionEvent e) {
|
||||
myViewButton.setEnabled(myCommitsTable.getSelectedRowCount() == 1);
|
||||
|
||||
+6
-336
@@ -20,40 +20,31 @@
|
||||
*/
|
||||
package com.theoryinpractice.testng.configuration;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.execution.CantRunException;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.testframework.SearchForTestsTask;
|
||||
import com.intellij.execution.testframework.TestSearchScope;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PackageScope;
|
||||
import com.intellij.psi.search.searches.AnnotatedMembersSearch;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.util.ClassUtil;
|
||||
import com.theoryinpractice.testng.model.IDEARemoteTestRunnerClient;
|
||||
import com.theoryinpractice.testng.model.TestClassFilter;
|
||||
import com.theoryinpractice.testng.model.TestData;
|
||||
import com.theoryinpractice.testng.model.TestNGTestObject;
|
||||
import com.theoryinpractice.testng.model.TestType;
|
||||
import com.theoryinpractice.testng.util.TestNGUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.testng.xml.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.ServerSocket;
|
||||
import java.util.*;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
public class SearchingForTestsTask extends SearchForTestsTask {
|
||||
private static final Logger LOG = Logger.getInstance("#" + SearchingForTestsTask.class.getName());
|
||||
@@ -280,182 +271,9 @@ public class SearchingForTestsTask extends SearchForTestsTask {
|
||||
|
||||
protected void fillTestObjects(final Map<PsiClass, Map<PsiMethod, List<String>>> classes)
|
||||
throws CantRunException {
|
||||
final TestData data = myConfig.getPersistantData();
|
||||
final PsiManager psiManager = PsiManager.getInstance(myProject);
|
||||
if (data.TEST_OBJECT.equals(TestType.PACKAGE.getType())) {
|
||||
final String packageName = data.getPackageName();
|
||||
PsiPackage psiPackage = ApplicationManager.getApplication().runReadAction(
|
||||
new Computable<PsiPackage>() {
|
||||
@Nullable
|
||||
public PsiPackage compute() {
|
||||
return JavaPsiFacade.getInstance(psiManager.getProject()).findPackage(packageName);
|
||||
}
|
||||
}
|
||||
);
|
||||
if (psiPackage == null) {
|
||||
throw CantRunException.packageNotFound(packageName);
|
||||
}
|
||||
else {
|
||||
TestSearchScope scope = myConfig.getPersistantData().getScope();
|
||||
//TODO we should narrow this down by module really, if that's what's specified
|
||||
TestClassFilter projectFilter =
|
||||
new TestClassFilter(scope.getSourceScope(myConfig).getGlobalSearchScope(), myProject, true, true);
|
||||
TestClassFilter filter = projectFilter.intersectionWith(PackageScope.packageScope(psiPackage, true));
|
||||
calculateDependencies(null, classes, TestNGUtil.getAllTestClasses(filter, false));
|
||||
if (classes.size() == 0) {
|
||||
throw new CantRunException("No tests found in the package \"" + packageName + '\"');
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (data.TEST_OBJECT.equals(TestType.CLASS.getType())) {
|
||||
//it's a class
|
||||
final PsiClass psiClass = ApplicationManager.getApplication().runReadAction(
|
||||
new Computable<PsiClass>() {
|
||||
@Nullable
|
||||
public PsiClass compute() {
|
||||
return ClassUtil.findPsiClass(psiManager, data.getMainClassName().replace('/', '.'), null, true, getSearchScope());
|
||||
}
|
||||
}
|
||||
);
|
||||
if (psiClass == null) {
|
||||
throw new CantRunException("No tests found in the class \"" + data.getMainClassName() + '\"');
|
||||
}
|
||||
if (null == ApplicationManager.getApplication().runReadAction(new Computable<String>() {
|
||||
@Nullable
|
||||
public String compute() {
|
||||
return psiClass.getQualifiedName();
|
||||
}
|
||||
})) {
|
||||
throw new CantRunException("Cannot test anonymous or local class \"" + data.getMainClassName() + '\"');
|
||||
}
|
||||
calculateDependencies(null, classes, psiClass);
|
||||
}
|
||||
else if (data.TEST_OBJECT.equals(TestType.METHOD.getType())) {
|
||||
//it's a method
|
||||
final PsiClass psiClass = ApplicationManager.getApplication().runReadAction(
|
||||
new Computable<PsiClass>() {
|
||||
@Nullable
|
||||
public PsiClass compute() {
|
||||
return ClassUtil.findPsiClass(psiManager, data.getMainClassName().replace('/', '.'), null, true, getSearchScope());
|
||||
}
|
||||
}
|
||||
);
|
||||
if (psiClass == null) {
|
||||
throw new CantRunException("No tests found in the class \"" + data.getMainClassName() + '\"');
|
||||
}
|
||||
if (null == ApplicationManager.getApplication().runReadAction(
|
||||
new Computable<String>() {
|
||||
@Nullable
|
||||
public String compute() {
|
||||
return psiClass.getQualifiedName();
|
||||
}
|
||||
}
|
||||
)) {
|
||||
throw new CantRunException("Cannot test anonymous or local class \"" + data.getMainClassName() + '\"');
|
||||
}
|
||||
collectTestMethods(classes, psiClass, data.getMethodName());
|
||||
}
|
||||
else if (data.TEST_OBJECT.equals(TestType.GROUP.getType())) {
|
||||
//for a group, we include all classes
|
||||
PsiClass[] testClasses = TestNGUtil
|
||||
.getAllTestClasses(new TestClassFilter(data.getScope().getSourceScope(myConfig).getGlobalSearchScope(), myProject, true, true), false);
|
||||
if (testClasses != null) {
|
||||
for (PsiClass c : testClasses) {
|
||||
classes.put(c, new LinkedHashMap<PsiMethod, List<String>>());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (data.TEST_OBJECT.equals(TestType.PATTERN.getType())) {
|
||||
for (final String pattern : data.getPatterns()) {
|
||||
final String className;
|
||||
final String methodName;
|
||||
if (pattern.contains(",")) {
|
||||
methodName = StringUtil.getShortName(pattern, ',');
|
||||
className = StringUtil.getPackageName(pattern, ',');
|
||||
} else {
|
||||
className = pattern;
|
||||
methodName = null;
|
||||
}
|
||||
|
||||
final PsiClass psiClass = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiClass compute() {
|
||||
return ClassUtil.findPsiClass(psiManager, className.replace('/', '.'), null, true, getSearchScope());
|
||||
}
|
||||
});
|
||||
if (psiClass != null) {
|
||||
final Boolean hasTest = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return TestNGUtil.hasTest(psiClass);
|
||||
}
|
||||
});
|
||||
if (hasTest) {
|
||||
if (StringUtil.isEmpty(methodName)) {
|
||||
calculateDependencies(null, classes, psiClass);
|
||||
}
|
||||
else {
|
||||
collectTestMethods(classes, psiClass, methodName);
|
||||
}
|
||||
} else {
|
||||
throw new CantRunException("No tests found in class " + className);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (classes.size() != data.getPatterns().size()) {
|
||||
TestSearchScope scope = myConfig.getPersistantData().getScope();
|
||||
final List<Pattern> compilePatterns = new ArrayList<Pattern>();
|
||||
for (String p : data.getPatterns()) {
|
||||
final Pattern compilePattern;
|
||||
try {
|
||||
compilePattern = Pattern.compile(p);
|
||||
}
|
||||
catch (PatternSyntaxException e) {
|
||||
continue;
|
||||
}
|
||||
if (compilePattern != null) {
|
||||
compilePatterns.add(compilePattern);
|
||||
}
|
||||
}
|
||||
TestClassFilter projectFilter =
|
||||
new TestClassFilter(scope.getSourceScope(myConfig).getGlobalSearchScope(), myProject, true, true){
|
||||
@Override
|
||||
public boolean isAccepted(PsiClass psiClass) {
|
||||
if (super.isAccepted(psiClass)) {
|
||||
final String qualifiedName = psiClass.getQualifiedName();
|
||||
LOG.assertTrue(qualifiedName != null);
|
||||
for (Pattern pattern : compilePatterns) {
|
||||
if (pattern.matcher(qualifiedName).matches()) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
calculateDependencies(null, classes, TestNGUtil.getAllTestClasses(projectFilter, false));
|
||||
if (classes.size() == 0) {
|
||||
throw new CantRunException("No tests found in for patterns \"" + StringUtil.join(data.getPatterns(), " || ") + '\"');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void collectTestMethods(Map<PsiClass, Map<PsiMethod, List<String>>> classes, final PsiClass psiClass, final String methodName) {
|
||||
final PsiMethod[] methods = ApplicationManager.getApplication().runReadAction(
|
||||
new Computable<PsiMethod[]>() {
|
||||
public PsiMethod[] compute() {
|
||||
return psiClass.findMethodsByName(methodName, true);
|
||||
}
|
||||
}
|
||||
);
|
||||
calculateDependencies(methods, classes, psiClass);
|
||||
Map<PsiMethod, List<String>> psiMethods = classes.get(psiClass);
|
||||
if (psiMethods == null) {
|
||||
psiMethods = new LinkedHashMap<PsiMethod, List<String>>();
|
||||
classes.put(psiClass, psiMethods);
|
||||
}
|
||||
for (PsiMethod method : methods) {
|
||||
psiMethods.put(method, Collections.<String>emptyList());
|
||||
final TestNGTestObject testObject = TestNGTestObject.fromConfig(myConfig);
|
||||
if (testObject != null) {
|
||||
testObject.fillTestObjects(classes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -492,152 +310,4 @@ public class SearchingForTestsTask extends SearchForTestsTask {
|
||||
return params;
|
||||
}
|
||||
|
||||
private void calculateDependencies(PsiMethod[] methods,
|
||||
final Map<PsiClass, Map<PsiMethod, List<String>>> results,
|
||||
@Nullable final PsiClass... classes) {
|
||||
calculateDependencies(methods, results, new LinkedHashSet<PsiMember>(), classes);
|
||||
}
|
||||
|
||||
private void calculateDependencies(final PsiMethod[] methods,
|
||||
final Map<PsiClass, Map<PsiMethod, List<String>>> results,
|
||||
final Set<PsiMember> alreadyMarkedToBeChecked,
|
||||
@Nullable final PsiClass... classes) {
|
||||
if (classes != null && classes.length > 0) {
|
||||
final Set<String> groupDependencies = new LinkedHashSet<String>();
|
||||
TestNGUtil.collectAnnotationValues(groupDependencies, "dependsOnGroups", methods, classes);
|
||||
final Set<PsiMember> membersToCheckNow = new LinkedHashSet<PsiMember>();
|
||||
if (!groupDependencies.isEmpty()) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
final Project project = classes[0].getProject();
|
||||
final PsiClass testAnnotation =
|
||||
JavaPsiFacade.getInstance(project).findClass(TestNGUtil.TEST_ANNOTATION_FQN, GlobalSearchScope.allScope(project));
|
||||
LOG.assertTrue(testAnnotation != null);
|
||||
for (PsiMember psiMember : AnnotatedMembersSearch.search(testAnnotation, getSearchScope())) {
|
||||
final PsiAnnotation annotation = AnnotationUtil.findAnnotation(psiMember, TestNGUtil.TEST_ANNOTATION_FQN);
|
||||
if (TestNGUtil.isAnnotatedWithParameter(annotation, "groups", groupDependencies)) {
|
||||
if (appendMember(psiMember, alreadyMarkedToBeChecked, results)) {
|
||||
membersToCheckNow.add(psiMember);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
collectDependsOnMethods(results, alreadyMarkedToBeChecked, membersToCheckNow, methods, classes);
|
||||
|
||||
if (methods == null) {
|
||||
for (PsiClass c : classes) {
|
||||
results.put(c, new LinkedHashMap<PsiMethod, List<String>>());
|
||||
}
|
||||
} else {
|
||||
for (PsiMember psiMember : membersToCheckNow) {
|
||||
PsiClass psiClass;
|
||||
PsiMethod[] meths = null;
|
||||
if (psiMember instanceof PsiMethod) {
|
||||
psiClass = psiMember.getContainingClass();
|
||||
meths = new PsiMethod[] {(PsiMethod)psiMember};
|
||||
} else {
|
||||
psiClass = (PsiClass)psiMember;
|
||||
}
|
||||
calculateDependencies(meths, results, alreadyMarkedToBeChecked, psiClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void collectDependsOnMethods(final Map<PsiClass, Map<PsiMethod, List<String>>> results,
|
||||
final Set<PsiMember> alreadyMarkedToBeChecked,
|
||||
final Set<PsiMember> membersToCheckNow,
|
||||
final PsiMethod[] methods,
|
||||
final PsiClass... classes) {
|
||||
final PsiClass[] psiClasses;
|
||||
if (methods != null && methods.length > 0) {
|
||||
final Set<PsiClass> containingClasses = new LinkedHashSet<PsiClass>();
|
||||
for (final PsiMethod method : methods) {
|
||||
containingClasses.add(ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
|
||||
@Override
|
||||
public PsiClass compute() {
|
||||
return method.getContainingClass();
|
||||
}
|
||||
}));
|
||||
}
|
||||
psiClasses = containingClasses.toArray(new PsiClass[containingClasses.size()]);
|
||||
} else {
|
||||
psiClasses = classes;
|
||||
}
|
||||
for (final PsiClass containingClass : psiClasses) {
|
||||
final Set<String> testMethodDependencies = new LinkedHashSet<String>();
|
||||
TestNGUtil.collectAnnotationValues(testMethodDependencies, "dependsOnMethods", methods, containingClass);
|
||||
if (!testMethodDependencies.isEmpty()) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
final Project project = containingClass.getProject();
|
||||
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
|
||||
for (String dependency : testMethodDependencies) {
|
||||
final String className = StringUtil.getPackageName(dependency);
|
||||
final String methodName = StringUtil.getShortName(dependency);
|
||||
if (StringUtil.isEmpty(className)) {
|
||||
checkClassMethods(methodName, containingClass, alreadyMarkedToBeChecked, membersToCheckNow, results);
|
||||
}
|
||||
else {
|
||||
final PsiClass aClass = psiFacade.findClass(className, containingClass.getResolveScope());
|
||||
if (aClass != null) {
|
||||
checkClassMethods(methodName, aClass, alreadyMarkedToBeChecked, membersToCheckNow, results);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkClassMethods(String methodName,
|
||||
PsiClass containingClass,
|
||||
Set<PsiMember> alreadyMarkedToBeChecked,
|
||||
Set<PsiMember> membersToCheckNow,
|
||||
Map<PsiClass, Map<PsiMethod, List<String>>> results) {
|
||||
final PsiMethod[] psiMethods = containingClass.findMethodsByName(methodName, true);
|
||||
for (PsiMethod method : psiMethods) {
|
||||
if (AnnotationUtil.isAnnotated(method, TestNGUtil.TEST_ANNOTATION_FQN, false) &&
|
||||
appendMember(method, alreadyMarkedToBeChecked, results)) {
|
||||
membersToCheckNow.add(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean appendMember(final PsiMember psiMember,
|
||||
final Set<PsiMember> underConsideration,
|
||||
final Map<PsiClass, Map<PsiMethod, List<String>>> results) {
|
||||
boolean result = false;
|
||||
final PsiClass psiClass = psiMember instanceof PsiClass ? ((PsiClass)psiMember) : psiMember.getContainingClass();
|
||||
Map<PsiMethod, List<String>> psiMethods = results.get(psiClass);
|
||||
if (psiMethods == null) {
|
||||
psiMethods = new LinkedHashMap<PsiMethod, List<String>>();
|
||||
results.put(psiClass, psiMethods);
|
||||
if (psiMember instanceof PsiClass) {
|
||||
result = underConsideration.add(psiMember);
|
||||
}
|
||||
}
|
||||
if (psiMember instanceof PsiMethod) {
|
||||
final boolean add = psiMethods.put((PsiMethod)psiMember, Collections.<String>emptyList()) != null;
|
||||
if (add) {
|
||||
return underConsideration.add(psiMember);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private GlobalSearchScope getSearchScope() {
|
||||
final TestData data = myConfig.getPersistantData();
|
||||
final Module module = myConfig.getConfigurationModule().getModule();
|
||||
return data.TEST_OBJECT.equals(TestType.PACKAGE.getType())
|
||||
? myConfig.getPersistantData().getScope().getSourceScope(myConfig).getGlobalSearchScope()
|
||||
: module != null ? GlobalSearchScope.moduleWithDependenciesScope(module) : GlobalSearchScope.projectScope(myConfig.getProject());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+9
-64
@@ -29,7 +29,6 @@ import com.intellij.execution.configuration.EnvironmentVariablesComponent;
|
||||
import com.intellij.execution.configurations.*;
|
||||
import com.intellij.execution.junit.RefactoringListeners;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.execution.testframework.SourceScope;
|
||||
import com.intellij.execution.testframework.TestSearchScope;
|
||||
import com.intellij.execution.util.JavaParametersUtil;
|
||||
import com.intellij.execution.util.ProgramParametersUtil;
|
||||
@@ -47,12 +46,12 @@ import com.intellij.refactoring.listeners.RefactoringElementAdapter;
|
||||
import com.intellij.refactoring.listeners.RefactoringElementListener;
|
||||
import com.intellij.refactoring.listeners.UndoRefactoringElementListener;
|
||||
import com.theoryinpractice.testng.model.TestData;
|
||||
import com.theoryinpractice.testng.model.TestNGTestObject;
|
||||
import com.theoryinpractice.testng.model.TestType;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.testng.xml.Parser;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -68,7 +67,7 @@ public class TestNGConfiguration extends ModuleBasedConfiguration<JavaRunConfigu
|
||||
public boolean ALTERNATIVE_JRE_PATH_ENABLED;
|
||||
public String ALTERNATIVE_JRE_PATH;
|
||||
|
||||
private static final Object PARSE_LOCK = new Object();
|
||||
|
||||
|
||||
public static final String DEFAULT_PACKAGE_NAME = ExecutionBundle.message("default.package.presentable.name");
|
||||
public static final String DEFAULT_PACKAGE_CONFIGURATION_NAME = ExecutionBundle.message("default.package.configuration.name");
|
||||
@@ -149,32 +148,14 @@ public class TestNGConfiguration extends ModuleBasedConfiguration<JavaRunConfigu
|
||||
|
||||
@Override
|
||||
public String suggestedName() {
|
||||
return data.getGeneratedName(getConfigurationModule());
|
||||
final TestNGTestObject testObject = TestNGTestObject.fromConfig(this);
|
||||
return testObject != null ? testObject.getGeneratedName() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActionName() {
|
||||
if (TestType.CLASS.getType().equals(data.TEST_OBJECT)) {
|
||||
String shortName = JavaExecutionUtil.getShortClassName(data.MAIN_CLASS_NAME);
|
||||
return ProgramRunnerUtil.shortenName(shortName, 0);
|
||||
}
|
||||
if (TestType.PACKAGE.getType().equals(data.TEST_OBJECT)) {
|
||||
String s = getName();
|
||||
if (!isGeneratedName()) return '\"' + s + '\"';
|
||||
if (data.getPackageName().trim().length() > 0) {
|
||||
return "Tests in \"" + data.getPackageName() + '\"';
|
||||
}
|
||||
else {
|
||||
return "All Tests";
|
||||
}
|
||||
}
|
||||
if (TestType.METHOD.getType().equals(data.TEST_OBJECT)) {
|
||||
return data.getMethodName() + "()";
|
||||
}
|
||||
if (TestType.SUITE.getType().equals(data.TEST_OBJECT)) {
|
||||
return data.getSuiteName();
|
||||
}
|
||||
return data.getGroupName();
|
||||
final TestNGTestObject testObject = TestNGTestObject.fromConfig(this);
|
||||
return testObject != null ? ProgramRunnerUtil.shortenName(testObject.getActionName(), 0) : null;
|
||||
}
|
||||
|
||||
public void setVMParameters(String value) {
|
||||
@@ -299,45 +280,9 @@ public class TestNGConfiguration extends ModuleBasedConfiguration<JavaRunConfigu
|
||||
|
||||
@Override
|
||||
public void checkConfiguration() throws RuntimeConfigurationException {
|
||||
if (data.TEST_OBJECT.equals(TestType.CLASS.getType()) || data.TEST_OBJECT.equals(TestType.METHOD.getType())) {
|
||||
final SourceScope scope = data.getScope().getSourceScope(this);
|
||||
if (scope == null) {
|
||||
throw new RuntimeConfigurationException("Invalid scope specified");
|
||||
}
|
||||
PsiClass psiClass = JavaPsiFacade.getInstance(project).findClass(data.getMainClassName(), scope.getGlobalSearchScope());
|
||||
if (psiClass == null) throw new RuntimeConfigurationException("Class '" + data.getMainClassName() + "' not found");
|
||||
if (data.TEST_OBJECT.equals(TestType.METHOD.getType())) {
|
||||
PsiMethod[] methods = psiClass.findMethodsByName(data.getMethodName(), true);
|
||||
if (methods.length == 0) {
|
||||
throw new RuntimeConfigurationException("Method '" + data.getMethodName() + "' not found");
|
||||
}
|
||||
for (PsiMethod method : methods) {
|
||||
if (!method.hasModifierProperty(PsiModifier.PUBLIC)) {
|
||||
throw new RuntimeConfigurationException("Non public method '" + data.getMethodName() + "'specified");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (data.TEST_OBJECT.equals(TestType.PACKAGE.getType())) {
|
||||
PsiPackage psiPackage = JavaPsiFacade.getInstance(project).findPackage(data.getPackageName());
|
||||
if (psiPackage == null) throw new RuntimeConfigurationException("Package '" + data.getPackageName() + "' not found");
|
||||
}
|
||||
else if (data.TEST_OBJECT.equals(TestType.SUITE.getType())) {
|
||||
try {
|
||||
final Parser parser = new Parser(data.getSuiteName());
|
||||
parser.setLoadClasses(false);
|
||||
synchronized (PARSE_LOCK) {
|
||||
parser.parse();//try to parse suite.xml
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeConfigurationException("Unable to parse '" + data.getSuiteName() + "' specified");
|
||||
}
|
||||
} else if (data.TEST_OBJECT.equals(TestType.PATTERN.getType())) {
|
||||
final Set<String> patterns = data.getPatterns();
|
||||
if (patterns.isEmpty()) {
|
||||
throw new RuntimeConfigurationWarning("No pattern selected");
|
||||
}
|
||||
final TestNGTestObject testObject = TestNGTestObject.fromConfig(this);
|
||||
if (testObject != null) {
|
||||
testObject.checkConfiguration();
|
||||
}
|
||||
JavaRunConfigurationExtensionManager.checkConfigurationIsValid(this);
|
||||
ProgramParametersUtil.checkWorkingDirectoryExist(this, getProject(), getConfigurationModule().getModule());
|
||||
|
||||
+2
-1
@@ -33,6 +33,7 @@ import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.theoryinpractice.testng.model.TestData;
|
||||
import com.theoryinpractice.testng.model.TestNGTestObject;
|
||||
import org.testng.IDEATestNGRemoteListener;
|
||||
|
||||
public abstract class TestNGConfigurationProducer extends JavaRunConfigurationProducerBase<TestNGConfiguration> implements Cloneable {
|
||||
@@ -58,7 +59,7 @@ public abstract class TestNGConfigurationProducer extends JavaRunConfigurationPr
|
||||
String paramSetName = contextLocation instanceof PsiMemberParameterizedLocation
|
||||
? getInvocationNumber(((PsiMemberParameterizedLocation)contextLocation).getParamSetName()) : null;
|
||||
if (paramSetName != null && !Comparing.strEqual(paramSetName, testNGConfiguration.getProgramParameters())) return false;
|
||||
TestData testobject = testNGConfiguration.getPersistantData();
|
||||
TestNGTestObject testobject = TestNGTestObject.fromConfig(testNGConfiguration);
|
||||
if (testobject != null) {
|
||||
if (testobject.isConfiguredByElement(element)) {
|
||||
final Module configurationModule = testNGConfiguration.getConfigurationModule().getModule();
|
||||
|
||||
+3
-1
@@ -33,6 +33,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.theoryinpractice.testng.model.TestData;
|
||||
import com.theoryinpractice.testng.model.TestNGTestObject;
|
||||
import icons.TestngIcons;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -72,7 +73,8 @@ public class TestNGConfigurationType implements ConfigurationType
|
||||
return false;
|
||||
else {
|
||||
final PsiElement element = location.getPsiElement();
|
||||
if (testobject.isConfiguredByElement(element)) {
|
||||
final TestNGTestObject testNGTestObject = TestNGTestObject.fromConfig(config);
|
||||
if (testNGTestObject != null && testNGTestObject.isConfiguredByElement(element)) {
|
||||
final Module configurationModule = config.getConfigurationModule().getModule();
|
||||
if (Comparing.equal(location.getModule(), configurationModule)) return true;
|
||||
|
||||
|
||||
@@ -18,16 +18,15 @@ package com.theoryinpractice.testng.model;
|
||||
import com.intellij.execution.ExternalizablePath;
|
||||
import com.intellij.execution.JavaExecutionUtil;
|
||||
import com.intellij.execution.Location;
|
||||
import com.intellij.execution.configurations.JavaRunConfigurationModule;
|
||||
import com.intellij.execution.junit.JUnitUtil;
|
||||
import com.intellij.execution.junit2.info.MethodLocation;
|
||||
import com.intellij.execution.testframework.TestSearchScope;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiPackage;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -174,26 +173,6 @@ public class TestData implements Cloneable
|
||||
return data;
|
||||
}
|
||||
|
||||
public String getGeneratedName(JavaRunConfigurationModule runconfigurationmodule) {
|
||||
if (TestType.PACKAGE.getType().equals(TEST_OBJECT)) if (getPackageName().length() == 0) return "<default>";
|
||||
else return getPackageName();
|
||||
String name = JavaExecutionUtil.getPresentableClassName(getMainClassName());
|
||||
if (TestType.METHOD.getType().equals(TEST_OBJECT)) {
|
||||
return name + '.' + getMethodName();
|
||||
}
|
||||
else if (TestType.SUITE.getType().equals(TEST_OBJECT)) {
|
||||
return getSuiteName();
|
||||
}
|
||||
else {
|
||||
if (TestType.PATTERN.getType().equals(TEST_OBJECT)) {
|
||||
final int size = myPatterns.size();
|
||||
if (size == 0) return "Temp suite";
|
||||
return StringUtil.getShortName(myPatterns.iterator().next()) + (size > 1 ? " and " + (size - 1) + " more" : "");
|
||||
}
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public String getMainClassName() {
|
||||
return MAIN_CLASS_NAME == null ? "" : MAIN_CLASS_NAME;
|
||||
}
|
||||
@@ -217,28 +196,6 @@ public class TestData implements Cloneable
|
||||
return JavaExecutionUtil.findModule(psiclass);
|
||||
}
|
||||
|
||||
public boolean isConfiguredByElement(PsiElement element) {
|
||||
if (TEST_OBJECT.equals(TestType.PACKAGE.getType())) {
|
||||
if (element instanceof PsiPackage) {
|
||||
return Comparing.strEqual(PACKAGE_NAME, ((PsiPackage) element).getQualifiedName());
|
||||
} else if (element instanceof PsiDirectory) {
|
||||
final PsiPackage psiPackage = JavaDirectoryService.getInstance().getPackage(((PsiDirectory)element));
|
||||
return psiPackage != null && Comparing.strEqual(PACKAGE_NAME, psiPackage.getQualifiedName());
|
||||
}
|
||||
}
|
||||
|
||||
element = PsiTreeUtil.getParentOfType(element, PsiModifierListOwner.class, false);
|
||||
if (element instanceof PsiMethod && TEST_OBJECT.equals(TestType.METHOD.getType())) {
|
||||
final PsiClass aClass = ((PsiMethod) element).getContainingClass();
|
||||
return aClass != null &&
|
||||
Comparing.strEqual(MAIN_CLASS_NAME, JavaExecutionUtil.getRuntimeQualifiedName(aClass)) &&
|
||||
Comparing.strEqual(METHOD_NAME, ((PsiMethod) element).getName());
|
||||
} else if (element instanceof PsiClass && TEST_OBJECT.equals(TestType.CLASS.getType())) {
|
||||
return Comparing.strEqual(MAIN_CLASS_NAME, JavaExecutionUtil.getRuntimeQualifiedName((PsiClass) element));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Map<String, String> getEnvs() {
|
||||
return ENVS;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.theoryinpractice.testng.model;
|
||||
|
||||
import com.intellij.execution.CantRunException;
|
||||
import com.intellij.execution.JavaExecutionUtil;
|
||||
import com.intellij.execution.configurations.RuntimeConfigurationException;
|
||||
import com.intellij.execution.testframework.SourceScope;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.ClassUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.theoryinpractice.testng.configuration.TestNGConfiguration;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class TestNGTestClass extends TestNGTestObject {
|
||||
public TestNGTestClass(TestNGConfiguration config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillTestObjects(Map<PsiClass, Map<PsiMethod, List<String>>> classes)
|
||||
throws CantRunException {
|
||||
final TestData data = myConfig.getPersistantData();
|
||||
//it's a class
|
||||
final PsiClass psiClass = ApplicationManager.getApplication().runReadAction(
|
||||
new Computable<PsiClass>() {
|
||||
@Nullable
|
||||
public PsiClass compute() {
|
||||
return ClassUtil.findPsiClass(PsiManager.getInstance(myConfig.getProject()), data.getMainClassName().replace('/', '.'), null, true, getSearchScope());
|
||||
}
|
||||
}
|
||||
);
|
||||
if (psiClass == null) {
|
||||
throw new CantRunException("No tests found in the class \"" + data.getMainClassName() + '\"');
|
||||
}
|
||||
if (null == ApplicationManager.getApplication().runReadAction(new Computable<String>() {
|
||||
@Nullable
|
||||
public String compute() {
|
||||
return psiClass.getQualifiedName();
|
||||
}
|
||||
})) {
|
||||
throw new CantRunException("Cannot test anonymous or local class \"" + data.getMainClassName() + '\"');
|
||||
}
|
||||
calculateDependencies(null, classes, psiClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGeneratedName() {
|
||||
return JavaExecutionUtil.getPresentableClassName(myConfig.getPersistantData().getMainClassName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActionName() {
|
||||
return JavaExecutionUtil.getShortClassName(myConfig.getPersistantData().MAIN_CLASS_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkConfiguration() throws RuntimeConfigurationException {
|
||||
final TestData data = myConfig.getPersistantData();
|
||||
final SourceScope scope = data.getScope().getSourceScope(myConfig);
|
||||
if (scope == null) {
|
||||
throw new RuntimeConfigurationException("Invalid scope specified");
|
||||
}
|
||||
PsiClass psiClass = JavaPsiFacade.getInstance(myConfig.getProject()).findClass(data.getMainClassName(), scope.getGlobalSearchScope());
|
||||
if (psiClass == null) throw new RuntimeConfigurationException("Class '" + data.getMainClassName() + "' not found");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConfiguredByElement(PsiElement element) {
|
||||
element = PsiTreeUtil.getParentOfType(element, PsiModifierListOwner.class, false);
|
||||
if (element instanceof PsiClass) {
|
||||
return Comparing.strEqual(myConfig.getPersistantData().getMethodName(), JavaExecutionUtil.getRuntimeQualifiedName((PsiClass) element));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.theoryinpractice.testng.model;
|
||||
|
||||
import com.intellij.execution.CantRunException;
|
||||
import com.intellij.execution.configurations.RuntimeConfigurationException;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.theoryinpractice.testng.configuration.TestNGConfiguration;
|
||||
import com.theoryinpractice.testng.util.TestNGUtil;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class TestNGTestGroup extends TestNGTestObject {
|
||||
public TestNGTestGroup(TestNGConfiguration config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillTestObjects(Map<PsiClass, Map<PsiMethod, List<String>>> classes)
|
||||
throws CantRunException {
|
||||
final TestData data = myConfig.getPersistantData();
|
||||
//for a group, we include all classes
|
||||
final TestClassFilter classFilter =
|
||||
new TestClassFilter(data.getScope().getSourceScope(myConfig).getGlobalSearchScope(), myConfig.getProject(), true, true);
|
||||
PsiClass[] testClasses = TestNGUtil.getAllTestClasses(classFilter, false);
|
||||
if (testClasses != null) {
|
||||
for (PsiClass c : testClasses) {
|
||||
classes.put(c, new LinkedHashMap<PsiMethod, List<String>>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGeneratedName() {
|
||||
return myConfig.getPersistantData().getGroupName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActionName() {
|
||||
return myConfig.getPersistantData().getGroupName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkConfiguration() throws RuntimeConfigurationException {
|
||||
//check group exist?
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.theoryinpractice.testng.model;
|
||||
|
||||
import com.intellij.execution.CantRunException;
|
||||
import com.intellij.execution.JavaExecutionUtil;
|
||||
import com.intellij.execution.configurations.RuntimeConfigurationException;
|
||||
import com.intellij.execution.testframework.SourceScope;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.ClassUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.theoryinpractice.testng.configuration.TestNGConfiguration;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class TestNGTestMethod extends TestNGTestObject {
|
||||
public TestNGTestMethod(TestNGConfiguration config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillTestObjects(Map<PsiClass, Map<PsiMethod, List<String>>> classes)
|
||||
throws CantRunException {
|
||||
final TestData data = myConfig.getPersistantData();
|
||||
final PsiClass psiClass = ApplicationManager.getApplication().runReadAction(
|
||||
new Computable<PsiClass>() {
|
||||
@Nullable
|
||||
public PsiClass compute() {
|
||||
return ClassUtil.findPsiClass(PsiManager.getInstance(myConfig.getProject()), data.getMainClassName().replace('/', '.'), null, true, getSearchScope());
|
||||
}
|
||||
}
|
||||
);
|
||||
if (psiClass == null) {
|
||||
throw new CantRunException("No tests found in the class \"" + data.getMainClassName() + '\"');
|
||||
}
|
||||
if (null == ApplicationManager.getApplication().runReadAction(
|
||||
new Computable<String>() {
|
||||
@Nullable
|
||||
public String compute() {
|
||||
return psiClass.getQualifiedName();
|
||||
}
|
||||
}
|
||||
)) {
|
||||
throw new CantRunException("Cannot test anonymous or local class \"" + data.getMainClassName() + '\"');
|
||||
}
|
||||
collectTestMethods(classes, psiClass, data.getMethodName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGeneratedName() {
|
||||
final TestData data = myConfig.getPersistantData();
|
||||
return JavaExecutionUtil.getPresentableClassName(data.getMainClassName()) + '.' + data.getMethodName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActionName() {
|
||||
return myConfig.getPersistantData().getMethodName() + "()";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkConfiguration() throws RuntimeConfigurationException {
|
||||
final TestData data = myConfig.getPersistantData();
|
||||
final SourceScope scope = data.getScope().getSourceScope(myConfig);
|
||||
if (scope == null) {
|
||||
throw new RuntimeConfigurationException("Invalid scope specified");
|
||||
}
|
||||
PsiClass psiClass = JavaPsiFacade.getInstance(myConfig.getProject()).findClass(data.getMainClassName(), scope.getGlobalSearchScope());
|
||||
if (psiClass == null) throw new RuntimeConfigurationException("Class '" + data.getMainClassName() + "' not found");
|
||||
PsiMethod[] methods = psiClass.findMethodsByName(data.getMethodName(), true);
|
||||
if (methods.length == 0) {
|
||||
throw new RuntimeConfigurationException("Method '" + data.getMethodName() + "' not found");
|
||||
}
|
||||
for (PsiMethod method : methods) {
|
||||
if (!method.hasModifierProperty(PsiModifier.PUBLIC)) {
|
||||
throw new RuntimeConfigurationException("Non public method '" + data.getMethodName() + "'specified");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConfiguredByElement(PsiElement element) {
|
||||
element = PsiTreeUtil.getParentOfType(element, PsiModifierListOwner.class, false);
|
||||
if (element instanceof PsiMethod) {
|
||||
final PsiClass aClass = ((PsiMethod) element).getContainingClass();
|
||||
final TestData data = myConfig.getPersistantData();
|
||||
return aClass != null &&
|
||||
Comparing.strEqual(data.MAIN_CLASS_NAME, JavaExecutionUtil.getRuntimeQualifiedName(aClass)) &&
|
||||
Comparing.strEqual(data.METHOD_NAME, ((PsiMethod) element).getName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.theoryinpractice.testng.model;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.execution.CantRunException;
|
||||
import com.intellij.execution.configurations.RuntimeConfigurationException;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.searches.AnnotatedMembersSearch;
|
||||
import com.theoryinpractice.testng.configuration.TestNGConfiguration;
|
||||
import com.theoryinpractice.testng.util.TestNGUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public abstract class TestNGTestObject {
|
||||
private static final Logger LOG = Logger.getInstance("#" + TestNGTestObject.class.getName());
|
||||
protected final TestNGConfiguration myConfig;
|
||||
|
||||
public TestNGTestObject(TestNGConfiguration config) {
|
||||
myConfig = config;
|
||||
}
|
||||
|
||||
public static TestNGTestObject fromConfig(TestNGConfiguration config) {
|
||||
final TestData data = config.getPersistantData();
|
||||
if (data.TEST_OBJECT.equals(TestType.PACKAGE.getType())) {
|
||||
return new TestNGTestPackage(config);
|
||||
}
|
||||
if (data.TEST_OBJECT.equals(TestType.CLASS.getType())) {
|
||||
return new TestNGTestClass(config);
|
||||
}
|
||||
if (data.TEST_OBJECT.equals(TestType.METHOD.getType())) {
|
||||
return new TestNGTestMethod(config);
|
||||
}
|
||||
|
||||
if (data.TEST_OBJECT.equals(TestType.GROUP.getType())) {
|
||||
return new TestNGTestGroup(config);
|
||||
}
|
||||
|
||||
if (data.TEST_OBJECT.equals(TestType.PATTERN.getType())) {
|
||||
return new TestNGTestPattern(config);
|
||||
}
|
||||
|
||||
if (data.TEST_OBJECT.equals(TestType.SUITE.getType())){
|
||||
return new TestNGTestSuite(config);
|
||||
}
|
||||
assert false : data.TEST_OBJECT;
|
||||
return null;
|
||||
}
|
||||
|
||||
public abstract void fillTestObjects(final Map<PsiClass, Map<PsiMethod, List<String>>> classes) throws CantRunException;
|
||||
public abstract String getGeneratedName();
|
||||
public abstract String getActionName();
|
||||
public abstract void checkConfiguration() throws RuntimeConfigurationException;
|
||||
|
||||
public boolean isConfiguredByElement(PsiElement element) {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void calculateDependencies(PsiMethod[] methods,
|
||||
final Map<PsiClass, Map<PsiMethod, List<String>>> results,
|
||||
@Nullable final PsiClass... classes) {
|
||||
calculateDependencies(methods, results, new LinkedHashSet<PsiMember>(), classes);
|
||||
}
|
||||
|
||||
private void calculateDependencies(final PsiMethod[] methods,
|
||||
final Map<PsiClass, Map<PsiMethod, List<String>>> results,
|
||||
final Set<PsiMember> alreadyMarkedToBeChecked,
|
||||
@Nullable final PsiClass... classes) {
|
||||
if (classes != null && classes.length > 0) {
|
||||
final Set<String> groupDependencies = new LinkedHashSet<String>();
|
||||
TestNGUtil.collectAnnotationValues(groupDependencies, "dependsOnGroups", methods, classes);
|
||||
final Set<PsiMember> membersToCheckNow = new LinkedHashSet<PsiMember>();
|
||||
if (!groupDependencies.isEmpty()) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
final Project project = classes[0].getProject();
|
||||
final PsiClass testAnnotation =
|
||||
JavaPsiFacade.getInstance(project).findClass(TestNGUtil.TEST_ANNOTATION_FQN, GlobalSearchScope.allScope(project));
|
||||
LOG.assertTrue(testAnnotation != null);
|
||||
for (PsiMember psiMember : AnnotatedMembersSearch.search(testAnnotation, getSearchScope())) {
|
||||
final PsiAnnotation annotation = AnnotationUtil.findAnnotation(psiMember, TestNGUtil.TEST_ANNOTATION_FQN);
|
||||
if (TestNGUtil.isAnnotatedWithParameter(annotation, "groups", groupDependencies)) {
|
||||
if (appendMember(psiMember, alreadyMarkedToBeChecked, results)) {
|
||||
membersToCheckNow.add(psiMember);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
collectDependsOnMethods(results, alreadyMarkedToBeChecked, membersToCheckNow, methods, classes);
|
||||
|
||||
if (methods == null) {
|
||||
for (PsiClass c : classes) {
|
||||
results.put(c, new LinkedHashMap<PsiMethod, List<String>>());
|
||||
}
|
||||
} else {
|
||||
for (PsiMember psiMember : membersToCheckNow) {
|
||||
PsiClass psiClass;
|
||||
PsiMethod[] meths = null;
|
||||
if (psiMember instanceof PsiMethod) {
|
||||
psiClass = psiMember.getContainingClass();
|
||||
meths = new PsiMethod[] {(PsiMethod)psiMember};
|
||||
} else {
|
||||
psiClass = (PsiClass)psiMember;
|
||||
}
|
||||
calculateDependencies(meths, results, alreadyMarkedToBeChecked, psiClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void collectDependsOnMethods(final Map<PsiClass, Map<PsiMethod, List<String>>> results,
|
||||
final Set<PsiMember> alreadyMarkedToBeChecked,
|
||||
final Set<PsiMember> membersToCheckNow,
|
||||
final PsiMethod[] methods,
|
||||
final PsiClass... classes) {
|
||||
final PsiClass[] psiClasses;
|
||||
if (methods != null && methods.length > 0) {
|
||||
final Set<PsiClass> containingClasses = new LinkedHashSet<PsiClass>();
|
||||
for (final PsiMethod method : methods) {
|
||||
containingClasses.add(ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
|
||||
@Override
|
||||
public PsiClass compute() {
|
||||
return method.getContainingClass();
|
||||
}
|
||||
}));
|
||||
}
|
||||
psiClasses = containingClasses.toArray(new PsiClass[containingClasses.size()]);
|
||||
} else {
|
||||
psiClasses = classes;
|
||||
}
|
||||
for (final PsiClass containingClass : psiClasses) {
|
||||
final Set<String> testMethodDependencies = new LinkedHashSet<String>();
|
||||
TestNGUtil.collectAnnotationValues(testMethodDependencies, "dependsOnMethods", methods, containingClass);
|
||||
if (!testMethodDependencies.isEmpty()) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
public void run() {
|
||||
final Project project = containingClass.getProject();
|
||||
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
|
||||
for (String dependency : testMethodDependencies) {
|
||||
final String className = StringUtil.getPackageName(dependency);
|
||||
final String methodName = StringUtil.getShortName(dependency);
|
||||
if (StringUtil.isEmpty(className)) {
|
||||
checkClassMethods(methodName, containingClass, alreadyMarkedToBeChecked, membersToCheckNow, results);
|
||||
}
|
||||
else {
|
||||
final PsiClass aClass = psiFacade.findClass(className, containingClass.getResolveScope());
|
||||
if (aClass != null) {
|
||||
checkClassMethods(methodName, aClass, alreadyMarkedToBeChecked, membersToCheckNow, results);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkClassMethods(String methodName,
|
||||
PsiClass containingClass,
|
||||
Set<PsiMember> alreadyMarkedToBeChecked,
|
||||
Set<PsiMember> membersToCheckNow,
|
||||
Map<PsiClass, Map<PsiMethod, List<String>>> results) {
|
||||
final PsiMethod[] psiMethods = containingClass.findMethodsByName(methodName, true);
|
||||
for (PsiMethod method : psiMethods) {
|
||||
if (AnnotationUtil.isAnnotated(method, TestNGUtil.TEST_ANNOTATION_FQN, false) &&
|
||||
appendMember(method, alreadyMarkedToBeChecked, results)) {
|
||||
membersToCheckNow.add(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean appendMember(final PsiMember psiMember,
|
||||
final Set<PsiMember> underConsideration,
|
||||
final Map<PsiClass, Map<PsiMethod, List<String>>> results) {
|
||||
boolean result = false;
|
||||
final PsiClass psiClass = psiMember instanceof PsiClass ? ((PsiClass)psiMember) : psiMember.getContainingClass();
|
||||
Map<PsiMethod, List<String>> psiMethods = results.get(psiClass);
|
||||
if (psiMethods == null) {
|
||||
psiMethods = new LinkedHashMap<PsiMethod, List<String>>();
|
||||
results.put(psiClass, psiMethods);
|
||||
if (psiMember instanceof PsiClass) {
|
||||
result = underConsideration.add(psiMember);
|
||||
}
|
||||
}
|
||||
if (psiMember instanceof PsiMethod) {
|
||||
final boolean add = psiMethods.put((PsiMethod)psiMember, Collections.<String>emptyList()) != null;
|
||||
if (add) {
|
||||
return underConsideration.add(psiMember);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected GlobalSearchScope getSearchScope() {
|
||||
final TestData data = myConfig.getPersistantData();
|
||||
final Module module = myConfig.getConfigurationModule().getModule();
|
||||
return data.TEST_OBJECT.equals(TestType.PACKAGE.getType())
|
||||
? myConfig.getPersistantData().getScope().getSourceScope(myConfig).getGlobalSearchScope()
|
||||
: module != null ? GlobalSearchScope.moduleWithDependenciesScope(module) : GlobalSearchScope.projectScope(myConfig.getProject());
|
||||
}
|
||||
|
||||
protected void collectTestMethods(Map<PsiClass, Map<PsiMethod, List<String>>> classes, final PsiClass psiClass, final String methodName) {
|
||||
final PsiMethod[] methods = ApplicationManager.getApplication().runReadAction(
|
||||
new Computable<PsiMethod[]>() {
|
||||
public PsiMethod[] compute() {
|
||||
return psiClass.findMethodsByName(methodName, true);
|
||||
}
|
||||
}
|
||||
);
|
||||
calculateDependencies(methods, classes, psiClass);
|
||||
Map<PsiMethod, List<String>> psiMethods = classes.get(psiClass);
|
||||
if (psiMethods == null) {
|
||||
psiMethods = new LinkedHashMap<PsiMethod, List<String>>();
|
||||
classes.put(psiClass, psiMethods);
|
||||
}
|
||||
for (PsiMethod method : methods) {
|
||||
psiMethods.put(method, Collections.<String>emptyList());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.theoryinpractice.testng.model;
|
||||
|
||||
import com.intellij.execution.CantRunException;
|
||||
import com.intellij.execution.JavaExecutionUtil;
|
||||
import com.intellij.execution.configurations.RuntimeConfigurationException;
|
||||
import com.intellij.execution.testframework.TestSearchScope;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.PackageScope;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.theoryinpractice.testng.configuration.TestNGConfiguration;
|
||||
import com.theoryinpractice.testng.util.TestNGUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class TestNGTestPackage extends TestNGTestObject {
|
||||
public TestNGTestPackage(TestNGConfiguration configuration) {
|
||||
super(configuration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillTestObjects(Map<PsiClass, Map<PsiMethod, List<String>>> classes) throws CantRunException {
|
||||
final String packageName = myConfig.getPersistantData().getPackageName();
|
||||
PsiPackage psiPackage = ApplicationManager.getApplication().runReadAction(
|
||||
new Computable<PsiPackage>() {
|
||||
@Nullable
|
||||
public PsiPackage compute() {
|
||||
return JavaPsiFacade.getInstance(myConfig.getProject()).findPackage(packageName);
|
||||
}
|
||||
}
|
||||
);
|
||||
if (psiPackage == null) {
|
||||
throw CantRunException.packageNotFound(packageName);
|
||||
}
|
||||
else {
|
||||
TestSearchScope scope = myConfig.getPersistantData().getScope();
|
||||
//TODO we should narrow this down by module really, if that's what's specified
|
||||
TestClassFilter projectFilter =
|
||||
new TestClassFilter(scope.getSourceScope(myConfig).getGlobalSearchScope(), myConfig.getProject(), true, true);
|
||||
TestClassFilter filter = projectFilter.intersectionWith(PackageScope.packageScope(psiPackage, true));
|
||||
calculateDependencies(null, classes, TestNGUtil.getAllTestClasses(filter, false));
|
||||
if (classes.size() == 0) {
|
||||
throw new CantRunException("No tests found in the package \"" + packageName + '\"');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGeneratedName() {
|
||||
final String packageName = myConfig.getPersistantData().getPackageName();
|
||||
return packageName.length() == 0 ? "<default>" : packageName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActionName() {
|
||||
String s = myConfig.getName();
|
||||
if (!myConfig.isGeneratedName()) return '\"' + s + '\"';
|
||||
if (myConfig.getPersistantData().getPackageName().trim().length() > 0) {
|
||||
return "Tests in \"" + myConfig.getPersistantData().getPackageName() + '\"';
|
||||
}
|
||||
else {
|
||||
return "All Tests";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkConfiguration() throws RuntimeConfigurationException {
|
||||
final TestData data = myConfig.getPersistantData();
|
||||
PsiPackage psiPackage = JavaPsiFacade.getInstance(myConfig.getProject()).findPackage(data.getPackageName());
|
||||
if (psiPackage == null) throw new RuntimeConfigurationException("Package '" + data.getPackageName() + "' not found");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConfiguredByElement(PsiElement element) {
|
||||
final String packageName = myConfig.getPersistantData().getPackageName();
|
||||
if (element instanceof PsiPackage) {
|
||||
return Comparing.strEqual(packageName, ((PsiPackage)element).getQualifiedName());
|
||||
} else if (element instanceof PsiDirectory) {
|
||||
final PsiPackage psiPackage = JavaDirectoryService.getInstance().getPackage(((PsiDirectory)element));
|
||||
return psiPackage != null && Comparing.strEqual(packageName, psiPackage.getQualifiedName());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.theoryinpractice.testng.model;
|
||||
|
||||
import com.intellij.execution.CantRunException;
|
||||
import com.intellij.execution.configurations.RuntimeConfigurationException;
|
||||
import com.intellij.execution.configurations.RuntimeConfigurationWarning;
|
||||
import com.intellij.execution.testframework.TestSearchScope;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.util.ClassUtil;
|
||||
import com.theoryinpractice.testng.configuration.TestNGConfiguration;
|
||||
import com.theoryinpractice.testng.util.TestNGUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
public class TestNGTestPattern extends TestNGTestObject {
|
||||
private static final Logger LOG = Logger.getInstance("#" + TestNGTestPattern.class.getName());
|
||||
|
||||
public TestNGTestPattern(TestNGConfiguration config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillTestObjects(Map<PsiClass, Map<PsiMethod, List<String>>> classes)
|
||||
throws CantRunException {
|
||||
final TestData data = myConfig.getPersistantData();
|
||||
for (final String pattern : data.getPatterns()) {
|
||||
final String className;
|
||||
final String methodName;
|
||||
if (pattern.contains(",")) {
|
||||
methodName = StringUtil.getShortName(pattern, ',');
|
||||
className = StringUtil.getPackageName(pattern, ',');
|
||||
} else {
|
||||
className = pattern;
|
||||
methodName = null;
|
||||
}
|
||||
|
||||
final PsiClass psiClass = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiClass compute() {
|
||||
return ClassUtil.findPsiClass(PsiManager.getInstance(myConfig.getProject()), className.replace('/', '.'), null, true, getSearchScope());
|
||||
}
|
||||
});
|
||||
if (psiClass != null) {
|
||||
final Boolean hasTest = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return TestNGUtil.hasTest(psiClass);
|
||||
}
|
||||
});
|
||||
if (hasTest) {
|
||||
if (StringUtil.isEmpty(methodName)) {
|
||||
calculateDependencies(null, classes, psiClass);
|
||||
}
|
||||
else {
|
||||
collectTestMethods(classes, psiClass, methodName);
|
||||
}
|
||||
} else {
|
||||
throw new CantRunException("No tests found in class " + className);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (classes.size() != data.getPatterns().size()) {
|
||||
TestSearchScope scope = myConfig.getPersistantData().getScope();
|
||||
final List<Pattern> compilePatterns = new ArrayList<Pattern>();
|
||||
for (String p : data.getPatterns()) {
|
||||
final Pattern compilePattern;
|
||||
try {
|
||||
compilePattern = Pattern.compile(p);
|
||||
}
|
||||
catch (PatternSyntaxException e) {
|
||||
continue;
|
||||
}
|
||||
if (compilePattern != null) {
|
||||
compilePatterns.add(compilePattern);
|
||||
}
|
||||
}
|
||||
TestClassFilter projectFilter =
|
||||
new TestClassFilter(scope.getSourceScope(myConfig).getGlobalSearchScope(), myConfig.getProject(), true, true){
|
||||
@Override
|
||||
public boolean isAccepted(PsiClass psiClass) {
|
||||
if (super.isAccepted(psiClass)) {
|
||||
final String qualifiedName = psiClass.getQualifiedName();
|
||||
LOG.assertTrue(qualifiedName != null);
|
||||
for (Pattern pattern : compilePatterns) {
|
||||
if (pattern.matcher(qualifiedName).matches()) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
calculateDependencies(null, classes, TestNGUtil.getAllTestClasses(projectFilter, false));
|
||||
if (classes.size() == 0) {
|
||||
throw new CantRunException("No tests found in for patterns \"" + StringUtil.join(data.getPatterns(), " || ") + '\"');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGeneratedName() {
|
||||
final Set<String> patterns = myConfig.getPersistantData().getPatterns();
|
||||
final int size = patterns.size();
|
||||
if (size == 0) return "Temp suite";
|
||||
return StringUtil.getShortName(patterns.iterator().next()) + (size > 1 ? " and " + (size - 1) + " more" : "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActionName() {
|
||||
return getGeneratedName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkConfiguration() throws RuntimeConfigurationException {
|
||||
final Set<String> patterns = myConfig.getPersistantData().getPatterns();
|
||||
if (patterns.isEmpty()) {
|
||||
throw new RuntimeConfigurationWarning("No pattern selected");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.theoryinpractice.testng.model;
|
||||
|
||||
import com.intellij.execution.CantRunException;
|
||||
import com.intellij.execution.configurations.RuntimeConfigurationException;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.theoryinpractice.testng.configuration.TestNGConfiguration;
|
||||
import org.testng.xml.Parser;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class TestNGTestSuite extends TestNGTestObject {
|
||||
private static final Object PARSE_LOCK = new Object();
|
||||
public TestNGTestSuite(TestNGConfiguration config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillTestObjects(Map<PsiClass, Map<PsiMethod, List<String>>> classes) throws CantRunException {}
|
||||
|
||||
@Override
|
||||
public String getGeneratedName() {
|
||||
return myConfig.getPersistantData().getSuiteName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getActionName() {
|
||||
return myConfig.getPersistantData().getSuiteName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkConfiguration() throws RuntimeConfigurationException {
|
||||
final TestData data = myConfig.getPersistantData();
|
||||
try {
|
||||
final Parser parser = new Parser(data.getSuiteName());
|
||||
parser.setLoadClasses(false);
|
||||
synchronized (PARSE_LOCK) {
|
||||
parser.parse();//try to parse suite.xml
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeConfigurationException("Unable to parse '" + data.getSuiteName() + "' specified");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -436,7 +436,7 @@ public class TestNGUtil {
|
||||
public void run() {
|
||||
final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
|
||||
|
||||
final Collection<PsiClass> set = new HashSet<PsiClass>();
|
||||
final Collection<PsiClass> set = new LinkedHashSet<PsiClass>();
|
||||
PsiManager manager = PsiManager.getInstance(filter.getProject());
|
||||
GlobalSearchScope scope = filter.getScope();
|
||||
GlobalSearchScope projectScope = GlobalSearchScope.projectScope(manager.getProject());
|
||||
|
||||
Reference in New Issue
Block a user