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:
@@ -254,9 +254,6 @@ public class BuildManager implements ApplicationComponent{
|
||||
if (!eventFile.isValid()) {
|
||||
return true; // should be deleted
|
||||
}
|
||||
if (ProjectCoreUtil.isProjectOrWorkspaceFile(eventFile)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (project == null) {
|
||||
// lazy init
|
||||
@@ -268,6 +265,10 @@ public class BuildManager implements ApplicationComponent{
|
||||
}
|
||||
|
||||
if (fileIndex.isInContent(eventFile)) {
|
||||
if (ProjectCoreUtil.isProjectOrWorkspaceFile(eventFile)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -387,9 +388,9 @@ public class BuildManager implements ApplicationComponent{
|
||||
|
||||
public void clearState(Project project) {
|
||||
final String projectPath = getProjectPath(project);
|
||||
|
||||
|
||||
cancelPreloadedBuilds(projectPath);
|
||||
|
||||
|
||||
synchronized (myProjectDataMap) {
|
||||
final ProjectData data = myProjectDataMap.get(projectPath);
|
||||
if (data != null) {
|
||||
@@ -823,7 +824,7 @@ public class BuildManager implements ApplicationComponent{
|
||||
|
||||
private Future<Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler>> launchPreloadedBuildProcess(final Project project, SequentialTaskExecutor projectTaskQueue) throws Exception {
|
||||
ensureListening();
|
||||
|
||||
|
||||
// launching build process from projectTaskQueue ensures that no other build process for this project is currently running
|
||||
return projectTaskQueue.submit(new Callable<Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler>>() {
|
||||
public Pair<RequestFuture<PreloadedProcessMessageHandler>, OSProcessHandler> call() throws Exception {
|
||||
@@ -845,7 +846,7 @@ public class BuildManager implements ApplicationComponent{
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private OSProcessHandler launchBuildProcess(Project project, final int port, final UUID sessionId, boolean requestProjectPreload) throws ExecutionException {
|
||||
final String compilerPath;
|
||||
final String vmExecutablePath;
|
||||
@@ -951,7 +952,7 @@ public class BuildManager implements ApplicationComponent{
|
||||
cmdLine.addParameter("-Dpreload.project.path=" + FileUtil.toCanonicalPath(getProjectPath(project)));
|
||||
cmdLine.addParameter("-Dpreload.config.path=" + FileUtil.toCanonicalPath(PathManager.getOptionsPath()));
|
||||
}
|
||||
|
||||
|
||||
final String shouldGenerateIndex = System.getProperty(GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION);
|
||||
if (shouldGenerateIndex != null) {
|
||||
cmdLine.addParameter("-D"+ GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION +"=" + shouldGenerateIndex);
|
||||
@@ -975,11 +976,11 @@ public class BuildManager implements ApplicationComponent{
|
||||
cmdLine.addParameter(option);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isProfilingMode) {
|
||||
cmdLine.addParameter("-agentlib:yjpagent=disablej2ee,disablealloc,delay=10000,sessionname=ExternalBuild");
|
||||
}
|
||||
|
||||
|
||||
// debugging
|
||||
final int debugPort = Registry.intValue("compiler.process.debug.port");
|
||||
if (debugPort > 0) {
|
||||
@@ -1016,10 +1017,10 @@ public class BuildManager implements ApplicationComponent{
|
||||
final List<String> args = provider.getVMArguments();
|
||||
cmdLine.addParameters(args);
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnnecessaryFullyQualifiedName")
|
||||
|
||||
@SuppressWarnings("UnnecessaryFullyQualifiedName")
|
||||
final Class<?> launcherClass = org.jetbrains.jps.cmdline.Launcher.class;
|
||||
|
||||
|
||||
final List<String> launcherCp = new ArrayList<String>();
|
||||
launcherCp.add(ClasspathBootstrap.getResourcePath(launcherClass));
|
||||
launcherCp.add(compilerPath);
|
||||
@@ -1027,7 +1028,7 @@ public class BuildManager implements ApplicationComponent{
|
||||
launcherCp.addAll(BuildProcessClasspathManager.getLauncherClasspath(project));
|
||||
cmdLine.addParameter("-classpath");
|
||||
cmdLine.addParameter(classpathToString(launcherCp));
|
||||
|
||||
|
||||
cmdLine.addParameter(launcherClass.getName());
|
||||
|
||||
final List<String> cp = ClasspathBootstrap.getBuildProcessApplicationClasspath(true);
|
||||
@@ -1064,7 +1065,7 @@ public class BuildManager implements ApplicationComponent{
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return processHandler;
|
||||
}
|
||||
|
||||
@@ -1239,7 +1240,7 @@ public class BuildManager implements ApplicationComponent{
|
||||
@Override
|
||||
public void onTextAvailable(ProcessEvent event, Key outputType) {
|
||||
String text;
|
||||
|
||||
|
||||
synchronized (this) {
|
||||
if (myStoredLength > 2048) {
|
||||
return;
|
||||
@@ -1250,7 +1251,7 @@ public class BuildManager implements ApplicationComponent{
|
||||
}
|
||||
myStoredLength += text.length();
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
myOutput.append(text);
|
||||
}
|
||||
@@ -1454,7 +1455,7 @@ public class BuildManager implements ApplicationComponent{
|
||||
}
|
||||
myPath = list.toArray();
|
||||
}
|
||||
|
||||
|
||||
public abstract String getValue();
|
||||
|
||||
@Override
|
||||
@@ -1473,12 +1474,12 @@ public class BuildManager implements ApplicationComponent{
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(myPath);
|
||||
}
|
||||
|
||||
|
||||
public static InternedPath create(String path) {
|
||||
return path.startsWith("/")? new XInternedPath(path) : new WinInternedPath(path);
|
||||
return path.startsWith("/")? new XInternedPath(path) : new WinInternedPath(path);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class WinInternedPath extends InternedPath {
|
||||
private WinInternedPath(String path) {
|
||||
super(path);
|
||||
@@ -1491,7 +1492,7 @@ public class BuildManager implements ApplicationComponent{
|
||||
// handle case of windows drive letter
|
||||
return name.length() == 2 && name.endsWith(":")? name + "/" : name;
|
||||
}
|
||||
|
||||
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
for (int element : myPath) {
|
||||
if (buf.length() > 0) {
|
||||
|
||||
+9
-8
@@ -29,7 +29,6 @@ import com.intellij.openapi.options.TabbedConfigurable;
|
||||
import com.intellij.openapi.options.ex.SingleConfigurableEditor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.xdebugger.XDebugProcess;
|
||||
import com.intellij.xdebugger.XDebugSession;
|
||||
import com.intellij.xdebugger.XDebuggerManager;
|
||||
import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase;
|
||||
@@ -88,13 +87,15 @@ public class CustomizeContextViewAction extends XDebuggerTreeActionBase {
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
final XDebuggerManager debuggerManager = XDebuggerManager.getInstance(getEventProject(e));
|
||||
final XDebugSession currentSession = debuggerManager.getCurrentSession();
|
||||
if (currentSession != null) {
|
||||
final XDebugProcess process = currentSession.getDebugProcess();
|
||||
e.getPresentation().setVisible(process instanceof JavaDebugProcess);
|
||||
e.getPresentation().setEnabled(process instanceof JavaDebugProcess);
|
||||
e.getPresentation().setText(ActionsBundle.actionText(DebuggerActions.CUSTOMIZE_VIEWS));
|
||||
e.getPresentation().setText(ActionsBundle.actionText(DebuggerActions.CUSTOMIZE_VIEWS));
|
||||
Project project = getEventProject(e);
|
||||
if (project != null) {
|
||||
final XDebugSession currentSession = XDebuggerManager.getInstance(project).getCurrentSession();
|
||||
if (currentSession != null) {
|
||||
e.getPresentation().setEnabledAndVisible(currentSession.getDebugProcess() instanceof JavaDebugProcess);
|
||||
return;
|
||||
}
|
||||
}
|
||||
e.getPresentation().setEnabledAndVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
+21
-3
@@ -97,7 +97,18 @@ public class DuplicatesFinder {
|
||||
}
|
||||
|
||||
|
||||
public InputVariables getParameters() {
|
||||
return myParameters;
|
||||
}
|
||||
|
||||
public PsiElement[] getPattern() {
|
||||
return myPattern;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ReturnValue getReturnValue() {
|
||||
return myReturnValue;
|
||||
}
|
||||
|
||||
public List<Match> findDuplicates(PsiElement scope) {
|
||||
annotatePattern();
|
||||
@@ -164,9 +175,7 @@ public class DuplicatesFinder {
|
||||
|
||||
@Nullable
|
||||
private Match isDuplicateFragment(PsiElement candidate, boolean ignoreParameterTypesAndPostVariableUsages) {
|
||||
for (PsiElement pattern : myPattern) {
|
||||
if (PsiTreeUtil.isAncestor(pattern, candidate, false)) return null;
|
||||
}
|
||||
if (isSelf(candidate)) return null;
|
||||
PsiElement sibling = candidate;
|
||||
ArrayList<PsiElement> candidates = new ArrayList<PsiElement>();
|
||||
for (final PsiElement element : myPattern) {
|
||||
@@ -206,6 +215,15 @@ public class DuplicatesFinder {
|
||||
return match;
|
||||
}
|
||||
|
||||
protected boolean isSelf(PsiElement candidate) {
|
||||
for (PsiElement pattern : myPattern) {
|
||||
if (PsiTreeUtil.isAncestor(pattern, candidate, false)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean checkPostVariableUsages(final ArrayList<PsiElement> candidates, final Match match) {
|
||||
final PsiElement codeFragment = ControlFlowUtil.findCodeFragment(candidates.get(0));
|
||||
try {
|
||||
|
||||
+21
-17
@@ -16,37 +16,41 @@
|
||||
package com.intellij.codeInsight.template.postfix.templates;
|
||||
|
||||
import com.intellij.codeInsight.generation.surroundWith.JavaWithTryCatchSurrounder;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils.selectorTopmost;
|
||||
import static com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils.JAVA_PSI_INFO;
|
||||
|
||||
public class TryStatementPostfixTemplate extends PostfixTemplateWithExpressionSelector {
|
||||
|
||||
public static Condition<PsiElement> HAS_TYPE = new Condition<PsiElement>() {
|
||||
@Override
|
||||
public boolean value(@Nullable PsiElement element) {
|
||||
return element instanceof PsiExpression && ((PsiExpression)element).getType() != null;
|
||||
}
|
||||
};
|
||||
public class TryStatementPostfixTemplate extends PostfixTemplate {
|
||||
|
||||
protected TryStatementPostfixTemplate() {
|
||||
super("try", "try { exp } catch(Exception e)", JAVA_PSI_INFO, selectorTopmost(HAS_TYPE));
|
||||
super("try", "try { exp } catch(Exception e)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
|
||||
PsiStatement statementParent = PsiTreeUtil.getNonStrictParentOfType(context, PsiStatement.class);
|
||||
if (statementParent == null ||
|
||||
newOffset != statementParent.getTextRange().getEndOffset()) return false;
|
||||
|
||||
if (statementParent instanceof PsiDeclarationStatement) return true;
|
||||
|
||||
if (statementParent instanceof PsiExpressionStatement) {
|
||||
PsiExpression expression = ((PsiExpressionStatement)statementParent).getExpression();
|
||||
return null != expression.getType();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void expandForChooseExpression(@NotNull PsiElement context, @NotNull Editor editor) {
|
||||
PsiExpression expr = (PsiExpression)context;
|
||||
PsiStatement statement = PsiTreeUtil.getParentOfType(expr, PsiStatement.class, false);
|
||||
public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
|
||||
PsiStatement statement = PsiTreeUtil.getNonStrictParentOfType(context, PsiStatement.class);
|
||||
assert statement != null;
|
||||
|
||||
PsiFile file = statement.getContainingFile();
|
||||
|
||||
@@ -41,8 +41,6 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings {
|
||||
public static final int FULLY_QUALIFY_NAMES_ALWAYS = 2;
|
||||
public static final int SHORTEN_NAMES_ALWAYS_AND_ADD_IMPORT = 3;
|
||||
|
||||
public boolean LEGACY_SETTING_USE_FQ_CLASS_NAMES_IN_JAVADOC_IMPORTED = false;
|
||||
|
||||
public int CLASS_NAMES_IN_JAVADOC = FULLY_QUALIFY_NAMES_IF_NOT_IMPORTED;
|
||||
|
||||
public boolean useFqNamesInJavadocAlways() {
|
||||
@@ -51,12 +49,15 @@ public class JavaCodeStyleSettings extends CustomCodeStyleSettings {
|
||||
|
||||
@Override
|
||||
public void importLegacySettings() {
|
||||
if (!LEGACY_SETTING_USE_FQ_CLASS_NAMES_IN_JAVADOC_IMPORTED) {
|
||||
CodeStyleSettings settings = getContainer();
|
||||
if (!settings.USE_FQ_CLASS_NAMES_IN_JAVADOC) {
|
||||
CLASS_NAMES_IN_JAVADOC = SHORTEN_NAMES_ALWAYS_AND_ADD_IMPORT;
|
||||
}
|
||||
LEGACY_SETTING_USE_FQ_CLASS_NAMES_IN_JAVADOC_IMPORTED = true;
|
||||
importLegacyUseFqClassNamesInJavadocSetting();
|
||||
}
|
||||
|
||||
private void importLegacyUseFqClassNamesInJavadocSetting() {
|
||||
CodeStyleSettings settings = getContainer();
|
||||
boolean isDefaultValue = settings.USE_FQ_CLASS_NAMES_IN_JAVADOC;
|
||||
if (!isDefaultValue) {
|
||||
CLASS_NAMES_IN_JAVADOC = SHORTEN_NAMES_ALWAYS_AND_ADD_IMPORT;
|
||||
settings.USE_FQ_CLASS_NAMES_IN_JAVADOC = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+36
-9
@@ -47,7 +47,10 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.controlFlow.ControlFlowUtil;
|
||||
import com.intellij.psi.impl.source.codeStyle.JavaCodeStyleManagerImpl;
|
||||
import com.intellij.psi.scope.processor.VariablesProcessor;
|
||||
@@ -725,6 +728,11 @@ public class ExtractMethodProcessor implements MatchProvider {
|
||||
myVariableDatum[i].passAsParameter = false;
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public void changeParamName(int i, String param) {
|
||||
myVariableDatum[i].name = param;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked in command and in atomic action
|
||||
*/
|
||||
@@ -783,6 +791,7 @@ public class ExtractMethodProcessor implements MatchProvider {
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private DuplicatesFinder initDuplicates() {
|
||||
List<PsiElement> elements = new ArrayList<PsiElement>();
|
||||
for (PsiElement element : myElements) {
|
||||
@@ -1239,7 +1248,10 @@ public class ExtractMethodProcessor implements MatchProvider {
|
||||
}
|
||||
|
||||
private void renameInputVariables() throws IncorrectOperationException {
|
||||
for (VariableData data : myVariableDatum) {
|
||||
//when multiple input variables should have the same name, unique names are generated
|
||||
//without reverse, the second rename would rename variable without a prefix into second one though it was already renamed
|
||||
for (int i = myVariableDatum.length - 1; i >= 0; i--) {
|
||||
VariableData data = myVariableDatum[i];
|
||||
PsiVariable variable = data.variable;
|
||||
if (!data.name.equals(variable.getName())) {
|
||||
for (PsiElement element : myElements) {
|
||||
@@ -1659,18 +1671,33 @@ public class ExtractMethodProcessor implements MatchProvider {
|
||||
return myExtractedMethod;
|
||||
}
|
||||
|
||||
public boolean hasDuplicates() {
|
||||
final List<Match> duplicates = getDuplicates();
|
||||
return duplicates != null && !duplicates.isEmpty();
|
||||
public Boolean hasDuplicates() {
|
||||
List<Match> duplicates = getDuplicates();
|
||||
if (duplicates != null && !duplicates.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
final ExtractMethodSignatureSuggester suggester = new ExtractMethodSignatureSuggester(myProject, myExtractedMethod, myMethodCall, myVariableDatum);
|
||||
duplicates = suggester.getDuplicates(myExtractedMethod, myMethodCall);
|
||||
if (duplicates != null && !duplicates.isEmpty()) {
|
||||
myDuplicates = duplicates;
|
||||
myExtractedMethod = suggester.getExtractedMethod();
|
||||
myMethodCall = suggester.getMethodCall();
|
||||
myVariableDatum = suggester.getVariableData();
|
||||
return null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasDuplicates(Set<VirtualFile> files) {
|
||||
final DuplicatesFinder finder = initDuplicates();
|
||||
|
||||
if (hasDuplicates()) return true;
|
||||
final PsiManager psiManager = PsiManager.getInstance(myProject);
|
||||
for (VirtualFile file : files) {
|
||||
if (!finder.findDuplicates(psiManager.findFile(file)).isEmpty()) return true;
|
||||
final Boolean hasDuplicates = hasDuplicates();
|
||||
if (hasDuplicates == null || hasDuplicates) return true;
|
||||
if (finder != null) {
|
||||
final PsiManager psiManager = PsiManager.getInstance(myProject);
|
||||
for (VirtualFile file : files) {
|
||||
if (!finder.findDuplicates(psiManager.findFile(file)).isEmpty()) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
+328
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.intellij.refactoring.extractMethod;
|
||||
|
||||
import com.intellij.codeInsight.JavaPsiEquivalenceUtil;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.SuggestedNameInfo;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.refactoring.util.VariableData;
|
||||
import com.intellij.refactoring.util.duplicates.DuplicatesFinder;
|
||||
import com.intellij.refactoring.util.duplicates.Match;
|
||||
import com.intellij.refactoring.util.duplicates.MethodDuplicatesHandler;
|
||||
import com.intellij.util.text.UniqueNameGenerator;
|
||||
import gnu.trove.THashMap;
|
||||
import gnu.trove.THashSet;
|
||||
import gnu.trove.TObjectHashingStrategy;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ExtractMethodSignatureSuggester {
|
||||
private static final Logger LOG = Logger.getInstance("#" + ExtractMethodSignatureSuggester.class.getName());
|
||||
private static final TObjectHashingStrategy<PsiExpression> ourEquivalenceStrategy = new TObjectHashingStrategy<PsiExpression>() {
|
||||
@Override
|
||||
public int computeHashCode(PsiExpression object) {
|
||||
return RefactoringUtil.unparenthesizeExpression(object).getClass().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(PsiExpression o1, PsiExpression o2) {
|
||||
return JavaPsiEquivalenceUtil
|
||||
.areExpressionsEquivalent(RefactoringUtil.unparenthesizeExpression(o1), RefactoringUtil.unparenthesizeExpression(o2));
|
||||
}
|
||||
};
|
||||
|
||||
private Project myProject;
|
||||
private PsiElementFactory myElementFactory;
|
||||
|
||||
private PsiMethod myExtractedMethod;
|
||||
private PsiMethodCallExpression myMethodCall;
|
||||
private VariableData[] myVariableData;
|
||||
|
||||
public ExtractMethodSignatureSuggester(Project project,
|
||||
PsiMethod extractedMethod,
|
||||
PsiMethodCallExpression methodCall,
|
||||
VariableData[] variableDatum) {
|
||||
myProject = project;
|
||||
myElementFactory = JavaPsiFacade.getElementFactory(project);
|
||||
|
||||
myExtractedMethod = (PsiMethod)extractedMethod.copy();
|
||||
myMethodCall = methodCall;
|
||||
myVariableData = variableDatum;
|
||||
}
|
||||
|
||||
public List<Match> getDuplicates(final PsiMethod method, final PsiMethodCallExpression methodCall) {
|
||||
final List<Match> duplicates = findDuplicatesSignature(method);
|
||||
if (duplicates != null && !duplicates.isEmpty()) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode() ||
|
||||
Messages.showYesNoDialog(myProject, "No exact duplicates found.\nWould you like to apply suggested changes to replace " + duplicates.size() + " duplicates?", "Extract Parameters to Replace Duplicates",
|
||||
Messages.getQuestionIcon()) == Messages.YES) {
|
||||
WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
myMethodCall = (PsiMethodCallExpression)methodCall.replace(myMethodCall);
|
||||
myExtractedMethod = (PsiMethod)method.replace(myExtractedMethod);
|
||||
}
|
||||
});
|
||||
|
||||
final DuplicatesFinder finder = MethodDuplicatesHandler.createDuplicatesFinder(myExtractedMethod);
|
||||
if (finder != null) {
|
||||
final List<VariableData> datas = finder.getParameters().getInputVariables();
|
||||
myVariableData = datas.toArray(new VariableData[datas.size()]);
|
||||
return finder.findDuplicates(myExtractedMethod.getContainingClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public PsiMethod getExtractedMethod() {
|
||||
return myExtractedMethod;
|
||||
}
|
||||
|
||||
public PsiMethodCallExpression getMethodCall() {
|
||||
return myMethodCall;
|
||||
}
|
||||
|
||||
public VariableData[] getVariableData() {
|
||||
return myVariableData;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<Match> findDuplicatesSignature(final PsiMethod method) {
|
||||
final List<PsiExpression> copies = new ArrayList<PsiExpression>();
|
||||
final InputVariables variables = detectTopLevelExpressionsToReplaceWithParameters(copies);
|
||||
if (variables == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final DuplicatesFinder defaultFinder = MethodDuplicatesHandler.createDuplicatesFinder(myExtractedMethod);
|
||||
if (defaultFinder == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final DuplicatesFinder finder = new DuplicatesFinder(defaultFinder.getPattern(), variables, defaultFinder.getReturnValue(), new ArrayList<PsiVariable>()) {
|
||||
@Override
|
||||
protected boolean isSelf(PsiElement candidate) {
|
||||
return PsiTreeUtil.isAncestor(method, candidate, true);
|
||||
}
|
||||
};
|
||||
List<Match> duplicates = finder.findDuplicates(method.getContainingClass());
|
||||
|
||||
if (duplicates != null && !duplicates.isEmpty()) {
|
||||
restoreRenamedParams(copies);
|
||||
inlineSameArguments(method, copies, variables, duplicates);
|
||||
myMethodCall = (PsiMethodCallExpression)myMethodCall.copy();
|
||||
for (PsiExpression expression : copies) {
|
||||
myMethodCall.getArgumentList().add(expression);
|
||||
}
|
||||
return duplicates;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void inlineSameArguments(PsiMethod method, List<PsiExpression> copies, InputVariables variables, List<Match> duplicates) {
|
||||
final List<VariableData> variableDatum = variables.getInputVariables();
|
||||
final Map<PsiVariable, PsiExpression> toInline = new HashMap<PsiVariable, PsiExpression>();
|
||||
final int strongParamsCound = method.getParameterList().getParametersCount();
|
||||
for (int i = strongParamsCound; i < variableDatum.size(); i++) {
|
||||
VariableData variableData = variableDatum.get(i);
|
||||
final THashSet<PsiExpression> map = new THashSet<PsiExpression>(ourEquivalenceStrategy);
|
||||
if (!collectParamValues(duplicates, variableData, map)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final PsiExpression currentExpression = copies.get(i - strongParamsCound);
|
||||
map.add(currentExpression);
|
||||
|
||||
if (map.size() == 1) {
|
||||
toInline.put(variableData.variable, currentExpression);
|
||||
}
|
||||
}
|
||||
|
||||
if (!toInline.isEmpty()) {
|
||||
copies.removeAll(toInline.values());
|
||||
inlineArgumentsInMethodBody(toInline);
|
||||
removeRedundantParametersFromMethodSignature(toInline);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeRedundantParametersFromMethodSignature(Map<PsiVariable, PsiExpression> param2ExprMap) {
|
||||
for (PsiParameter parameter : myExtractedMethod.getParameterList().getParameters()) {
|
||||
if (param2ExprMap.containsKey(parameter)) {
|
||||
parameter.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void inlineArgumentsInMethodBody(final Map<PsiVariable, PsiExpression> param2ExprMap) {
|
||||
final Map<PsiExpression, PsiExpression> replacement = new HashMap<PsiExpression, PsiExpression>();
|
||||
myExtractedMethod.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
super.visitReferenceExpression(expression);
|
||||
final PsiElement resolve = expression.resolve();
|
||||
if (resolve instanceof PsiVariable) {
|
||||
final PsiExpression toInlineExpr = param2ExprMap.get((PsiVariable)resolve);
|
||||
if (toInlineExpr != null) {
|
||||
replacement.put(expression, toInlineExpr);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
for (PsiExpression expression : replacement.keySet()) {
|
||||
expression.replace(replacement.get(expression));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean collectParamValues(List<Match> duplicates, VariableData variableData, THashSet<PsiExpression> map) {
|
||||
for (Match duplicate : duplicates) {
|
||||
final List<PsiElement> values = duplicate.getParameterValues(variableData.variable);
|
||||
if (values == null || values.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
boolean found = false;
|
||||
for (PsiElement value : values) {
|
||||
if (value instanceof PsiExpression) {
|
||||
map.add((PsiExpression)value);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void restoreRenamedParams(List<PsiExpression> copies) {
|
||||
final Map<String, PsiVariable> renameMap = new HashMap<String, PsiVariable>();
|
||||
for (VariableData data : myVariableData) {
|
||||
if (!data.name.equals(data.variable.getName())) {
|
||||
renameMap.put(data.name, data.variable);
|
||||
}
|
||||
}
|
||||
|
||||
if (!renameMap.isEmpty()) {
|
||||
for (PsiExpression currentExpression : copies) {
|
||||
final Map<PsiReferenceExpression, PsiVariable> params = new HashMap<PsiReferenceExpression, PsiVariable>();
|
||||
currentExpression.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
super.visitReferenceExpression(expression);
|
||||
final PsiElement resolve = expression.resolve();
|
||||
if (resolve instanceof PsiParameter && myExtractedMethod.equals(((PsiParameter)resolve).getDeclarationScope())) {
|
||||
final String name = ((PsiParameter)resolve).getName();
|
||||
final PsiVariable variable = renameMap.get(name);
|
||||
if (renameMap.containsKey(name)) {
|
||||
params.put(expression, variable);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
for (PsiReferenceExpression expression : params.keySet()) {
|
||||
final PsiVariable var = params.get(expression);
|
||||
expression.replace(myElementFactory.createExpressionFromText(var.getName(), expression));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private InputVariables detectTopLevelExpressionsToReplaceWithParameters(List<PsiExpression> copies) {
|
||||
final PsiParameter[] parameters = myExtractedMethod.getParameterList().getParameters();
|
||||
final List<PsiVariable> inputVariables = new ArrayList<PsiVariable>(Arrays.asList(parameters));
|
||||
final PsiCodeBlock body = myExtractedMethod.getBody();
|
||||
LOG.assertTrue(body != null);
|
||||
final PsiStatement[] pattern = body.getStatements();
|
||||
final List<PsiExpression> exprs = new ArrayList<PsiExpression>();
|
||||
for (PsiStatement statement : pattern) {
|
||||
if (statement instanceof PsiExpressionStatement) {
|
||||
final PsiExpression expression = ((PsiExpressionStatement)statement).getExpression();
|
||||
if (expression instanceof PsiIfStatement || expression instanceof PsiLoopStatement) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
statement.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitCallExpression(PsiCallExpression callExpression) {
|
||||
final PsiExpressionList list = callExpression.getArgumentList();
|
||||
if (list != null) {
|
||||
for (PsiExpression expression : list.getExpressions()) {
|
||||
if (expression instanceof PsiReferenceExpression) {
|
||||
final PsiElement resolve = ((PsiReferenceExpression)expression).resolve();
|
||||
if (resolve instanceof PsiField) {
|
||||
exprs.add(expression);
|
||||
}
|
||||
} else {
|
||||
exprs.add(expression);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (exprs.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final UniqueNameGenerator uniqueNameGenerator = new UniqueNameGenerator();
|
||||
for (PsiParameter parameter : parameters) {
|
||||
uniqueNameGenerator.addExistingName(parameter.getName());
|
||||
}
|
||||
final THashMap<PsiExpression, String> unique = new THashMap<PsiExpression, String>(ourEquivalenceStrategy);
|
||||
final Map<PsiExpression, String> replacement = new HashMap<PsiExpression, String>();
|
||||
for (PsiExpression expr : exprs) {
|
||||
String name = unique.get(expr);
|
||||
if (name == null) {
|
||||
|
||||
final PsiType type = GenericsUtil.getVariableTypeByExpressionType(expr.getType());
|
||||
if (type == null || type == PsiType.NULL || PsiUtil.resolveClassInType(type) instanceof PsiAnonymousClass) return null;
|
||||
|
||||
copies.add(myElementFactory.createExpressionFromText(expr.getText(), body));
|
||||
|
||||
final SuggestedNameInfo info = JavaCodeStyleManager.getInstance(myProject).suggestVariableName(VariableKind.PARAMETER, null, expr, null);
|
||||
name = uniqueNameGenerator.generateUniqueName(info.names[0]);
|
||||
|
||||
final PsiParameter parameter = (PsiParameter)myExtractedMethod.getParameterList().add(myElementFactory.createParameter(name, type));
|
||||
inputVariables.add(parameter);
|
||||
unique.put(expr, name);
|
||||
}
|
||||
replacement.put(expr, name);
|
||||
}
|
||||
|
||||
for (PsiExpression expression : replacement.keySet()) {
|
||||
expression.replace(myElementFactory.createExpressionFromText(replacement.get(expression), null));
|
||||
}
|
||||
|
||||
return new InputVariables(inputVariables, myExtractedMethod.getProject(), new LocalSearchScope(myExtractedMethod), false);
|
||||
}
|
||||
}
|
||||
+2
@@ -28,6 +28,7 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
@@ -61,6 +62,7 @@ import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.VisibilityUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.*;
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ class ConstantMatchProvider implements MatchProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDuplicates() {
|
||||
public Boolean hasDuplicates() {
|
||||
return !myMatches.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
@@ -59,13 +59,17 @@ public class DuplicatesImpl {
|
||||
private DuplicatesImpl() {}
|
||||
|
||||
public static void invoke(@NotNull final Project project, @NotNull Editor editor, @NotNull MatchProvider provider) {
|
||||
invoke(project, editor, provider, true);
|
||||
}
|
||||
|
||||
public static void invoke(@NotNull final Project project, @NotNull Editor editor, @NotNull MatchProvider provider, boolean skipPromptWhenOne) {
|
||||
final List<Match> duplicates = provider.getDuplicates();
|
||||
int idx = 0;
|
||||
final Ref<Boolean> showAll = new Ref<Boolean>();
|
||||
final String confirmDuplicatePrompt = getConfirmationPrompt(provider, duplicates);
|
||||
for (final Match match : duplicates) {
|
||||
if (!match.getMatchStart().isValid() || !match.getMatchEnd().isValid()) continue;
|
||||
if (replaceMatch(project, provider, match, editor, ++idx, duplicates.size(), showAll, confirmDuplicatePrompt, true)) return;
|
||||
if (replaceMatch(project, provider, match, editor, ++idx, duplicates.size(), showAll, confirmDuplicatePrompt, skipPromptWhenOne)) return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,18 +190,18 @@ public class DuplicatesImpl {
|
||||
}
|
||||
|
||||
public static void processDuplicates(@NotNull MatchProvider provider, @NotNull Project project, @NotNull Editor editor) {
|
||||
boolean hasDuplicates = provider.hasDuplicates();
|
||||
if (hasDuplicates) {
|
||||
Boolean hasDuplicates = provider.hasDuplicates();
|
||||
if (hasDuplicates == null || hasDuplicates.booleanValue()) {
|
||||
List<Match> duplicates = provider.getDuplicates();
|
||||
if (duplicates.size() == 1) {
|
||||
previewMatch(project, duplicates.get(0), editor);
|
||||
}
|
||||
final int answer = ApplicationManager.getApplication().isUnitTestMode() ? Messages.YES : Messages.showYesNoDialog(project,
|
||||
final int answer = ApplicationManager.getApplication().isUnitTestMode() || hasDuplicates == null ? Messages.YES : Messages.showYesNoDialog(project,
|
||||
RefactoringBundle.message("0.has.detected.1.code.fragments.in.this.file.that.can.be.replaced.with.a.call.to.extracted.method",
|
||||
ApplicationNamesInfo.getInstance().getProductName(), duplicates.size()),
|
||||
"Process Duplicates", Messages.getQuestionIcon());
|
||||
if (answer == Messages.YES) {
|
||||
invoke(project, editor, provider);
|
||||
invoke(project, editor, provider, hasDuplicates != null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,10 @@ public interface MatchProvider {
|
||||
|
||||
List<Match> getDuplicates();
|
||||
|
||||
boolean hasDuplicates();
|
||||
/**
|
||||
* @return null if no confirmation prompt is expected
|
||||
*/
|
||||
@Nullable Boolean hasDuplicates();
|
||||
|
||||
@Nullable String getConfirmDuplicatePrompt(Match match);
|
||||
|
||||
|
||||
+15
-8
@@ -257,6 +257,16 @@ public class MethodDuplicatesHandler implements RefactoringActionHandler {
|
||||
}
|
||||
|
||||
public static List<Match> hasDuplicates(final PsiFile file, final PsiMember member) {
|
||||
final DuplicatesFinder duplicatesFinder = createDuplicatesFinder(member);
|
||||
if (duplicatesFinder == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return duplicatesFinder.findDuplicates(file);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static DuplicatesFinder createDuplicatesFinder(PsiMember member) {
|
||||
PsiElement[] pattern;
|
||||
ReturnValue matchedReturnValue = null;
|
||||
if (member instanceof PsiMethod) {
|
||||
@@ -288,17 +298,14 @@ public class MethodDuplicatesHandler implements RefactoringActionHandler {
|
||||
pattern = new PsiElement[]{((PsiField)member).getInitializer()};
|
||||
}
|
||||
if (pattern.length == 0) {
|
||||
return Collections.emptyList();
|
||||
return null;
|
||||
}
|
||||
final List<? extends PsiVariable> inputVariables =
|
||||
member instanceof PsiMethod ? Arrays.asList(((PsiMethod)member).getParameterList().getParameters()) : new ArrayList<PsiVariable>();
|
||||
final DuplicatesFinder duplicatesFinder =
|
||||
new DuplicatesFinder(pattern,
|
||||
new InputVariables(inputVariables, member.getProject(), new LocalSearchScope(pattern), false),
|
||||
matchedReturnValue,
|
||||
new ArrayList<PsiVariable>());
|
||||
|
||||
return duplicatesFinder.findDuplicates(file);
|
||||
return new DuplicatesFinder(pattern,
|
||||
new InputVariables(inputVariables, member.getProject(), new LocalSearchScope(pattern), false),
|
||||
matchedReturnValue,
|
||||
new ArrayList<PsiVariable>());
|
||||
}
|
||||
|
||||
static String getStatusMessage(final int duplicatesNo) {
|
||||
|
||||
+1
-1
@@ -149,7 +149,7 @@ class MethodDuplicatesMatchProvider implements MatchProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDuplicates() {
|
||||
public Boolean hasDuplicates() {
|
||||
return myDuplicates.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
public class Foo {
|
||||
void m() {
|
||||
new Object().try<caret>
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class Foo {
|
||||
void m() {
|
||||
try {
|
||||
new Object()
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
public class Foo {
|
||||
void m() {
|
||||
Object obj = new Object().try<caret>
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class Foo {
|
||||
void m() {
|
||||
try {
|
||||
Object obj = new Object()<caret>
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
public class Foo {
|
||||
void m() {
|
||||
doAct() + "aaa".try<caret>
|
||||
}
|
||||
|
||||
String doAct() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
public class Foo {
|
||||
void m() {
|
||||
try {
|
||||
doAct() + "aaa"
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
String doAct() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import java.lang.Exception;
|
||||
|
||||
public class Foo {
|
||||
void m() {
|
||||
methodCall(.try<caret>
|
||||
}
|
||||
|
||||
void methodCall(String s) {
|
||||
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import java.lang.Exception;
|
||||
|
||||
public class Foo {
|
||||
void m() {
|
||||
methodCall(.try <caret>
|
||||
}
|
||||
|
||||
void methodCall(String s) {
|
||||
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
import java.io.IOException;
|
||||
|
||||
public class Foo {
|
||||
void m() {
|
||||
doAct().try<caret>
|
||||
}
|
||||
|
||||
void doAct() throws IOException {}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import java.io.IOException;
|
||||
|
||||
public class Foo {
|
||||
void m() {
|
||||
try {
|
||||
doAct()<caret>
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
void doAct() throws IOException {}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class X {
|
||||
public static void main(String[] args) {
|
||||
boolean _user = true;
|
||||
String user = "foo";
|
||||
<selection>System.out.println(_user + " " + user);</selection>
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class X {
|
||||
public static void main(String[] args) {
|
||||
boolean _user = true;
|
||||
String user = "foo";
|
||||
newMethod(_user, user);
|
||||
}
|
||||
|
||||
private static void newMethod(boolean user, String user2) {
|
||||
System.out.println(user + " " + user2);
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
public class Test {
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
<selection>System.out.println("foo");
|
||||
System.out.println("bazz");
|
||||
System.out.println(x);</selection>
|
||||
|
||||
System.out.println("bar");
|
||||
System.out.println("bazz");
|
||||
System.out.println(x);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
public class Test {
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
newMethod(x, "foo");
|
||||
|
||||
newMethod(x, "bar");
|
||||
}
|
||||
|
||||
private void newMethod(int x, String foo) {
|
||||
System.out.println(foo);
|
||||
System.out.println("bazz");
|
||||
System.out.println(x);
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
public class Test {
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
<selection>System.out.println("foo");
|
||||
System.out.println(x);</selection>
|
||||
|
||||
System.out.println("bar");
|
||||
System.out.println(x);
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
public class Test {
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
<selection>System.out.println("foo");
|
||||
System.out.println("foo");
|
||||
System.out.println(x);</selection>
|
||||
|
||||
System.out.println("bar");
|
||||
System.out.println("bar");
|
||||
System.out.println(x);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
public class Test {
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
newMethod(x, "foo");
|
||||
|
||||
newMethod(x, "bar");
|
||||
}
|
||||
|
||||
private void newMethod(int x, String foo) {
|
||||
System.out.println(foo);
|
||||
System.out.println(foo);
|
||||
System.out.println(x);
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
public class Test {
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
newMethod(x, "foo");
|
||||
|
||||
newMethod(x, "bar");
|
||||
}
|
||||
|
||||
private void newMethod(int x, String foo) {
|
||||
System.out.println(foo);
|
||||
System.out.println(x);
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
public class Test {
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
<selection>System.out.println(1);
|
||||
System.out.println(2);
|
||||
System.out.println(x);</selection>
|
||||
|
||||
System.out.println(3);
|
||||
System.out.println(4);
|
||||
System.out.println(x);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
public class Test {
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
newMethod(x, 1, 2);
|
||||
|
||||
newMethod(x, 3, 4);
|
||||
}
|
||||
|
||||
private void newMethod(int x, int x2, int x3) {
|
||||
System.out.println(x2);
|
||||
System.out.println(x3);
|
||||
System.out.println(x);
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
public class Test {
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
<selection>
|
||||
System.out.println(x);
|
||||
System.out.println(x + 1);
|
||||
</selection>
|
||||
|
||||
System.out.println(x);
|
||||
System.out.println(x + 2);
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
public class Test {
|
||||
{
|
||||
int x = 0;
|
||||
|
||||
|
||||
newMethod(x, x + 1);
|
||||
|
||||
|
||||
newMethod(x, x + 2);
|
||||
}
|
||||
|
||||
private void newMethod(int p, int x) {
|
||||
System.out.println(p);
|
||||
System.out.println(x);
|
||||
}
|
||||
}
|
||||
+20
@@ -39,4 +39,24 @@ public class TryPostfixTemplateTest extends PostfixTemplateTestCase {
|
||||
public void testNotResolvedExpression() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testDeclarationStatement() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testExpressionInMethodBody() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testSimpleWithThrowsCheckedException() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIncompleteStatement() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testConstructorStatement() {
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.CodeInsightUtil;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
@@ -33,6 +34,7 @@ import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ExtractMethodTest extends LightCodeInsightTestCase {
|
||||
@@ -609,6 +611,29 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
|
||||
doDuplicatesTest();
|
||||
}
|
||||
|
||||
public void testSuggestChangeSignatureOneParam() throws Exception {
|
||||
doDuplicatesTest();
|
||||
}
|
||||
|
||||
public void testSuggestChangeSignatureOneParamMultipleTimesInside() throws Exception {
|
||||
doDuplicatesTest();
|
||||
}
|
||||
|
||||
public void testSuggestChangeSignatureLeaveSameExpressionsUntouched() throws Exception {
|
||||
doDuplicatesTest();
|
||||
}
|
||||
|
||||
public void testSuggestChangeSignatureSameParamNames() throws Exception {
|
||||
doDuplicatesTest();
|
||||
}
|
||||
|
||||
public void testSuggestChangeSignatureWithChangedParameterName() throws Exception {
|
||||
configureByFile(BASE_PATH + getTestName(false) + ".java");
|
||||
boolean success = performExtractMethod(true, true, getEditor(), getFile(), getProject(), false, null, false, "p");
|
||||
assertTrue(success);
|
||||
checkResultByFile(BASE_PATH + getTestName(false) + "_after.java");
|
||||
}
|
||||
|
||||
public void testTargetAnonymous() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
@@ -646,6 +671,18 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
|
||||
doTestPassFieldsAsParams();
|
||||
}
|
||||
|
||||
public void testDefaultNamesConflictResolution() throws Exception {
|
||||
final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
|
||||
final String oldPrefix = settings.LOCAL_VARIABLE_NAME_PREFIX;
|
||||
try {
|
||||
settings.LOCAL_VARIABLE_NAME_PREFIX = "_";
|
||||
doTest();
|
||||
}
|
||||
finally {
|
||||
settings.LOCAL_VARIABLE_NAME_PREFIX = oldPrefix;
|
||||
}
|
||||
}
|
||||
|
||||
public void testCantPassFieldAsParameter() throws Exception {
|
||||
try {
|
||||
doTestPassFieldsAsParams();
|
||||
@@ -670,7 +707,7 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
|
||||
settings.ELSE_ON_NEW_LINE = true;
|
||||
settings.CATCH_ON_NEW_LINE = myCatchOnNewLine;
|
||||
configureByFile(BASE_PATH + getTestName(false) + ".java");
|
||||
boolean success = performExtractMethod(true, true, getEditor(), getFile(), getProject(), false, type, false);
|
||||
boolean success = performExtractMethod(true, true, getEditor(), getFile(), getProject(), false, type, false, null);
|
||||
assertTrue(success);
|
||||
checkResultByFile(BASE_PATH + getTestName(false) + "_after.java");
|
||||
}
|
||||
@@ -680,7 +717,7 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
|
||||
settings.ELSE_ON_NEW_LINE = true;
|
||||
settings.CATCH_ON_NEW_LINE = myCatchOnNewLine;
|
||||
configureByFile(BASE_PATH + getTestName(false) + ".java");
|
||||
boolean success = performExtractMethod(true, true, getEditor(), getFile(), getProject(), false, null, true);
|
||||
boolean success = performExtractMethod(true, true, getEditor(), getFile(), getProject(), false, null, true, null);
|
||||
assertTrue(success);
|
||||
checkResultByFile(BASE_PATH + getTestName(false) + "_after.java");
|
||||
}
|
||||
@@ -740,7 +777,7 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
|
||||
final boolean extractChainedConstructor,
|
||||
int... disabledParams)
|
||||
throws PrepareFailedException, IncorrectOperationException {
|
||||
return performExtractMethod(doRefactor, replaceAllDuplicates, editor, file, project, extractChainedConstructor, null, false, disabledParams);
|
||||
return performExtractMethod(doRefactor, replaceAllDuplicates, editor, file, project, extractChainedConstructor, null, false, null, disabledParams);
|
||||
}
|
||||
|
||||
public static boolean performExtractMethod(boolean doRefactor,
|
||||
@@ -751,6 +788,7 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
|
||||
final boolean extractChainedConstructor,
|
||||
PsiType returnType,
|
||||
boolean makeStatic,
|
||||
String newNameOfFirstParam,
|
||||
int... disabledParams)
|
||||
throws PrepareFailedException, IncorrectOperationException {
|
||||
int startOffset = editor.getSelectionModel().getSelectionStart();
|
||||
@@ -789,15 +827,21 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
|
||||
processor.doNotPassParameter(param);
|
||||
}
|
||||
}
|
||||
if (newNameOfFirstParam != null) {
|
||||
processor.changeParamName(0, newNameOfFirstParam);
|
||||
}
|
||||
ExtractMethodHandler.run(project, editor, processor);
|
||||
}
|
||||
|
||||
if (replaceAllDuplicates) {
|
||||
final List<Match> duplicates = processor.getDuplicates();
|
||||
for (final Match match : duplicates) {
|
||||
if (!match.getMatchStart().isValid() || !match.getMatchEnd().isValid()) continue;
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
processor.processMatch(match);
|
||||
final Boolean hasDuplicates = processor.hasDuplicates();
|
||||
if (hasDuplicates == null || hasDuplicates.booleanValue()) {
|
||||
final List<Match> duplicates = processor.getDuplicates();
|
||||
for (final Match match : duplicates) {
|
||||
if (!match.getMatchStart().isValid() || !match.getMatchEnd().isValid()) continue;
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
processor.processMatch(match);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2272,6 +2272,45 @@ public class Mappings {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// some classes may be associated with multiple sources.
|
||||
// In case some of these sources was not compiled, but the class was changed, we need to update
|
||||
// sourceToClasses mapping for such sources to include the updated ClassRepr version of the changed class
|
||||
final THashSet<File> unchangedSources = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
|
||||
delta.mySourceFileToClasses.forEachEntry(new TObjectObjectProcedure<File, Collection<ClassRepr>>() {
|
||||
@Override
|
||||
public boolean execute(File source, Collection<ClassRepr> b) {
|
||||
unchangedSources.add(source);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
unchangedSources.removeAll(delta.getChangedFiles());
|
||||
if (!unchangedSources.isEmpty()) {
|
||||
unchangedSources.forEach(new TObjectProcedure<File>() {
|
||||
@Override
|
||||
public boolean execute(File file) {
|
||||
final Collection<ClassRepr> updatedClasses = delta.mySourceFileToClasses.get(file);
|
||||
if (updatedClasses != null && !updatedClasses.isEmpty()) {
|
||||
final List<ClassRepr> classesToAdd = new ArrayList<ClassRepr>();
|
||||
classesToAdd.addAll(updatedClasses);
|
||||
Collection<ClassRepr> currentClasses = mySourceFileToClasses.get(file);
|
||||
if (currentClasses != null) {
|
||||
final TIntHashSet updatedClassNames = new TIntHashSet();
|
||||
for (ClassRepr aClass : updatedClasses) {
|
||||
updatedClassNames.add(aClass.name);
|
||||
}
|
||||
for (ClassRepr aClass : currentClasses) {
|
||||
if (!updatedClassNames.contains(aClass.name)) {
|
||||
classesToAdd.add(aClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
mySourceFileToClasses.replace(file, classesToAdd);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
myClassToSubclasses.putAll(delta.myClassToSubclasses);
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.intellij.openapi.project;
|
||||
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.InternalFileType;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.SystemInfoRt;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
|
||||
/**
|
||||
@@ -17,9 +19,9 @@ public class ProjectCoreUtil {
|
||||
public static boolean isProjectOrWorkspaceFile(final VirtualFile file,
|
||||
final FileType fileType) {
|
||||
if (fileType instanceof InternalFileType) return true;
|
||||
VirtualFile parent = file.getParent();
|
||||
while(parent != null) {
|
||||
if (DIRECTORY_BASED_PROJECT_DIR.equals(parent.getName())) return true;
|
||||
VirtualFile parent = file.isDirectory() ? file: file.getParent();
|
||||
while (parent != null) {
|
||||
if (Comparing.equal(parent.getNameSequence(), DIRECTORY_BASED_PROJECT_DIR, SystemInfoRt.isFileSystemCaseSensitive)) return true;
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -20,7 +20,7 @@ import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.fileEditor.UniqueVFilePathBuilder;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.fileTypes.InternalFileType;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -107,11 +107,12 @@ public class ProjectUtil {
|
||||
}
|
||||
|
||||
public static boolean isProjectOrWorkspaceFile(final VirtualFile file) {
|
||||
return isProjectOrWorkspaceFile(file, file.getFileType());
|
||||
// do not use file.getFileType() to avoid autodetection by content loading for arbitrary files
|
||||
return isProjectOrWorkspaceFile(file, FileTypeManager.getInstance().getFileTypeByFileName(file.getName()));
|
||||
}
|
||||
|
||||
public static boolean isProjectOrWorkspaceFile(@NotNull VirtualFile file, @NotNull FileType fileType) {
|
||||
return fileType instanceof InternalFileType || file.getPath().contains('/' + ProjectCoreUtil.DIRECTORY_BASED_PROJECT_DIR + '/');
|
||||
public static boolean isProjectOrWorkspaceFile(@NotNull VirtualFile file, @Nullable FileType fileType) {
|
||||
return ProjectCoreUtil.isProjectOrWorkspaceFile(file, fileType);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.intellij.psi.tree.IStubFileElementType;
|
||||
import com.intellij.util.ExceptionUtil;
|
||||
import com.intellij.util.indexing.*;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.DataInputOutputUtil;
|
||||
import com.intellij.util.io.IntInlineKeyDescriptor;
|
||||
import com.intellij.util.io.KeyDescriptor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -45,7 +46,7 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.stubs.StubUpdatingIndex");
|
||||
|
||||
// todo remove once we don't need this for stub-ast mismatch debug info
|
||||
private static final FileAttribute INDEXED_STAMP = new FileAttribute("stubIndexStamp", 0, false);
|
||||
private static final FileAttribute INDEXED_STAMP = new FileAttribute("stubIndexStamp", 1, false);
|
||||
|
||||
public static final ID<Integer, SerializedStubTree> INDEX_ID = ID.create("Stubs");
|
||||
|
||||
@@ -145,8 +146,8 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi
|
||||
private static void rememberIndexingStamp(final VirtualFile file, long contentLength) {
|
||||
try {
|
||||
DataOutputStream stream = INDEXED_STAMP.writeAttribute(file);
|
||||
stream.writeLong(file.getTimeStamp());
|
||||
stream.writeLong(contentLength);
|
||||
DataInputOutputUtil.writeTIME(stream, file.getTimeStamp());
|
||||
DataInputOutputUtil.writeLONG(stream, contentLength);
|
||||
stream.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
@@ -161,8 +162,8 @@ public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtensi
|
||||
return "no data";
|
||||
}
|
||||
|
||||
long stamp = stream.readLong();
|
||||
long size = stream.readLong();
|
||||
long stamp = DataInputOutputUtil.readTIME(stream);
|
||||
long size = DataInputOutputUtil.readLONG(stream);
|
||||
stream.close();
|
||||
return "indexed at " + stamp + " with size " + size;
|
||||
}
|
||||
|
||||
@@ -254,13 +254,7 @@ public class FileBasedIndexImpl extends FileBasedIndex {
|
||||
}
|
||||
|
||||
public static boolean isProjectOrWorkspaceFile(@NotNull VirtualFile file, @Nullable FileType fileType) {
|
||||
if (fileType instanceof InternalFileType) return true;
|
||||
VirtualFile parent = file.isDirectory() ? file: file.getParent();
|
||||
while (parent != null) {
|
||||
if (Comparing.equal(parent.getNameSequence(), ProjectCoreUtil.DIRECTORY_BASED_PROJECT_DIR, SystemInfoRt.isFileSystemCaseSensitive)) return true;
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return false;
|
||||
return ProjectCoreUtil.isProjectOrWorkspaceFile(file, fileType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,9 +26,13 @@ import org.jetbrains.annotations.NotNull;
|
||||
import javax.swing.*;
|
||||
|
||||
public class WorkspaceFileType implements InternalFileType {
|
||||
public static final WorkspaceFileType INSTANCE = new WorkspaceFileType();
|
||||
|
||||
@NonNls public static final String DEFAULT_EXTENSION = "iws";
|
||||
@NonNls public static final String DOT_DEFAULT_EXTENSION = "." + DEFAULT_EXTENSION;
|
||||
|
||||
private WorkspaceFileType() {}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getName() {
|
||||
|
||||
+18
-27
@@ -38,7 +38,6 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.colors.ColorKey;
|
||||
import com.intellij.openapi.editor.colors.EditorColors;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.colors.EditorFontType;
|
||||
import com.intellij.openapi.editor.event.EditorMouseEventArea;
|
||||
import com.intellij.openapi.editor.ex.*;
|
||||
@@ -96,7 +95,6 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
private ArrayList<TextAnnotationGutterProvider> myTextAnnotationGutters = new ArrayList<TextAnnotationGutterProvider>();
|
||||
private final Map<TextAnnotationGutterProvider, EditorGutterAction> myProviderToListener = new HashMap<TextAnnotationGutterProvider, EditorGutterAction>();
|
||||
private static final int GAP_BETWEEN_ANNOTATIONS = 5;
|
||||
private Color myBackgroundColor = null;
|
||||
private String myLastGutterToolTip = null;
|
||||
@NotNull private TIntFunction myLineNumberConvertor;
|
||||
private boolean myShowDefaultGutterPopup = true;
|
||||
@@ -174,7 +172,6 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
}
|
||||
|
||||
public void reinitSettings() {
|
||||
myBackgroundColor = null;
|
||||
revalidateMarkup();
|
||||
repaint();
|
||||
}
|
||||
@@ -197,8 +194,9 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
}
|
||||
|
||||
UISettings.setupAntialiasing(g);
|
||||
paintLineNumbersBackground(g, clip);
|
||||
paintAnnotationsBackground(g, clip);
|
||||
Color backgroundColor = getBackground();
|
||||
paintLineNumbersBackground(g, clip, backgroundColor);
|
||||
paintAnnotationsBackground(g, clip, backgroundColor);
|
||||
|
||||
Object hint = g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
|
||||
if (!UIUtil.isRetina()) g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF);
|
||||
@@ -206,9 +204,9 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
try {
|
||||
int firstVisibleOffset = myEditor.logicalPositionToOffset(myEditor.xyToLogicalPosition(new Point(0, clip.y - myEditor.getLineHeight())));
|
||||
int lastVisibleOffset = myEditor.logicalPositionToOffset(myEditor.xyToLogicalPosition(new Point(0, clip.y + clip.height + myEditor.getLineHeight())));
|
||||
paintFoldingBackground(g, clip);
|
||||
paintLineMarkersBackground(g, clip);
|
||||
paintBackground(g, clip, getLineMarkerAreaOffset(), getLineMarkerAreaWidth());
|
||||
paintFoldingBackground(g, clip, backgroundColor);
|
||||
paintLineMarkersBackground(g, clip, backgroundColor);
|
||||
paintBackground(g, clip, getLineMarkerAreaOffset(), getLineMarkerAreaWidth(), backgroundColor);
|
||||
paintEditorBackgrounds(g, firstVisibleOffset, lastVisibleOffset);
|
||||
paintAnnotations(g, clip);
|
||||
paintLineMarkers(g, firstVisibleOffset, lastVisibleOffset);
|
||||
@@ -298,11 +296,10 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
}
|
||||
}
|
||||
|
||||
private void paintAnnotationsBackground(Graphics g, Rectangle clip) {
|
||||
private void paintAnnotationsBackground(Graphics g, Rectangle clip, Color backgroundColor) {
|
||||
int w = getAnnotationsAreaWidthEx();
|
||||
if (w == 0) return;
|
||||
final Color background = myEditor.isInDistractionFreeMode() ? myEditor.getBackgroundColor() : getBackground();
|
||||
paintBackground(g, clip, getAnnotationsAreaOffset(), w, background);
|
||||
paintBackground(g, clip, getAnnotationsAreaOffset(), w, backgroundColor);
|
||||
}
|
||||
|
||||
private void paintAnnotations(Graphics g, Rectangle clip) {
|
||||
@@ -356,9 +353,9 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
}
|
||||
}
|
||||
|
||||
private void paintLineMarkersBackground(Graphics g, Rectangle clip) {
|
||||
private void paintLineMarkersBackground(Graphics g, Rectangle clip, Color bgColor) {
|
||||
if (isLineMarkersShown()) {
|
||||
paintBackground(g, clip, getLineMarkerAreaOffset(), getLineMarkerAreaWidth());
|
||||
paintBackground(g, clip, getLineMarkerAreaOffset(), getLineMarkerAreaWidth(), bgColor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,10 +365,6 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
}
|
||||
}
|
||||
|
||||
private void paintBackground(final Graphics g, final Rectangle clip, final int x, final int width) {
|
||||
paintBackground(g, clip, x, width, getBackground());
|
||||
}
|
||||
|
||||
private void paintBackground(final Graphics g,
|
||||
final Rectangle clip,
|
||||
final int x,
|
||||
@@ -399,21 +392,19 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
}
|
||||
}
|
||||
|
||||
private void paintLineNumbersBackground(Graphics g, Rectangle clip) {
|
||||
private void paintLineNumbersBackground(Graphics g, Rectangle clip, Color bgColor) {
|
||||
if (isLineNumbersShown()) {
|
||||
paintBackground(g, clip, getLineNumberAreaOffset(), getLineNumberAreaWidth());
|
||||
paintBackground(g, clip, getLineNumberAreaOffset(), getLineNumberAreaWidth(), bgColor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getBackground() {
|
||||
if (myBackgroundColor == null) {
|
||||
EditorColorsScheme colorsScheme = myEditor.getColorsScheme();
|
||||
boolean distractionMode = myEditor.isInDistractionFreeMode();
|
||||
Color color = distractionMode ? colorsScheme.getDefaultBackground() : colorsScheme.getColor(EditorColors.GUTTER_BACKGROUND);
|
||||
myBackgroundColor = color == null ? EditorColors.GUTTER_BACKGROUND.getDefaultColor() : color;
|
||||
if (myEditor.isInDistractionFreeMode()) {
|
||||
return myEditor.getBackgroundColor();
|
||||
}
|
||||
return myBackgroundColor;
|
||||
Color color = myEditor.getColorsScheme().getColor(EditorColors.GUTTER_BACKGROUND);
|
||||
return color != null ? color : EditorColors.GUTTER_BACKGROUND.getDefaultColor();
|
||||
}
|
||||
|
||||
private void doPaintLineNumbers(Graphics g, Rectangle clip) {
|
||||
@@ -850,9 +841,9 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
}
|
||||
}
|
||||
|
||||
private void paintFoldingBackground(Graphics g, Rectangle clip) {
|
||||
private void paintFoldingBackground(Graphics g, Rectangle clip, Color bgColor) {
|
||||
int lineX = getWhitespaceSeparatorOffset();
|
||||
paintBackground(g, clip, getFoldingAreaOffset(), getFoldingAreaWidth());
|
||||
paintBackground(g, clip, getFoldingAreaOffset(), getFoldingAreaWidth(), bgColor);
|
||||
|
||||
g.setColor(myEditor.getBackgroundColor());
|
||||
g.fillRect(lineX, clip.y, getFoldingAreaWidth(), clip.height);
|
||||
|
||||
+3
-3
@@ -27,8 +27,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
*/
|
||||
public class InternalFileTypeFactory extends FileTypeFactory {
|
||||
public void createFileTypes(@NotNull final FileTypeConsumer consumer) {
|
||||
consumer.consume(new WorkspaceFileType(), WorkspaceFileType.DEFAULT_EXTENSION);
|
||||
consumer.consume(new ModuleFileType(), ModuleFileType.DEFAULT_EXTENSION);
|
||||
consumer.consume(new ProjectFileType(), ProjectFileType.DEFAULT_EXTENSION);
|
||||
consumer.consume(WorkspaceFileType.INSTANCE, WorkspaceFileType.DEFAULT_EXTENSION);
|
||||
consumer.consume(ModuleFileType.INSTANCE, ModuleFileType.DEFAULT_EXTENSION);
|
||||
consumer.consume(ProjectFileType.INSTANCE, ProjectFileType.DEFAULT_EXTENSION);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -719,6 +719,7 @@
|
||||
</group>
|
||||
|
||||
<group id="XDebugger.ToolWindow.LeftToolbar">
|
||||
<separator/>
|
||||
<reference ref="Resume"/>
|
||||
<reference ref="Pause"/>
|
||||
<reference ref="Stop"/>
|
||||
|
||||
@@ -26,9 +26,13 @@ import org.jetbrains.annotations.NotNull;
|
||||
import javax.swing.*;
|
||||
|
||||
public class ModuleFileType implements InternalFileType {
|
||||
public static final ModuleFileType INSTANCE = new ModuleFileType();
|
||||
|
||||
@NonNls public static final String DEFAULT_EXTENSION = "iml";
|
||||
@NonNls public static final String DOT_DEFAULT_EXTENSION = ".iml";
|
||||
|
||||
private ModuleFileType() {}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getName() {
|
||||
|
||||
@@ -26,9 +26,13 @@ import org.jetbrains.annotations.NotNull;
|
||||
import javax.swing.*;
|
||||
|
||||
public class ProjectFileType implements InternalFileType {
|
||||
public static final ProjectFileType INSTANCE = new ProjectFileType();
|
||||
|
||||
@NonNls public static final String DEFAULT_EXTENSION = "ipr";
|
||||
@NonNls public static final String DOT_DEFAULT_EXTENSION = ".ipr";
|
||||
|
||||
private ProjectFileType() {}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getName() {
|
||||
|
||||
@@ -178,6 +178,9 @@ public class VcsRootDetectorTest extends VcsRootPlatformTest {
|
||||
@NotNull String... expectedPaths)
|
||||
throws IOException {
|
||||
initProject(vcsRootConfiguration);
|
||||
if (startDir != null) {
|
||||
startDir.refresh(false, true);
|
||||
}
|
||||
Collection<VcsRoot> vcsRoots = detect(startDir);
|
||||
assertRoots(Arrays.asList(expectedPaths), getPaths(
|
||||
ContainerUtil.filter(vcsRoots, new Condition<VcsRoot>() {
|
||||
|
||||
@@ -178,6 +178,7 @@ public class VcsRootErrorsFinderTest extends VcsRootPlatformTest {
|
||||
Collection<VcsRootError> expected = new ArrayList<VcsRootError>();
|
||||
expected.addAll(unregAll(vcsRootConfiguration.getUnregErrors()));
|
||||
expected.addAll(extraAll(vcsRootConfiguration.getExtraErrors()));
|
||||
myProjectRoot.refresh(false, true);
|
||||
Collection<VcsRootError> actual = ContainerUtil.filter(new VcsRootErrorsFinder(myProject).find(), new Condition<VcsRootError>() {
|
||||
@Override
|
||||
public boolean value(VcsRootError error) {
|
||||
|
||||
@@ -86,6 +86,7 @@ public abstract class VcsRootPlatformTest extends UsefulTestCase {
|
||||
.getInstance());
|
||||
myRootModel = ((ModuleRootManagerImpl)ModuleRootManager.getInstance(module)).getRootModel();
|
||||
mkdir(myRepositoryFolderName);
|
||||
myProjectRoot.refresh(false, true);
|
||||
myRepository = myProjectRoot.findChild(myRepositoryFolderName);
|
||||
myVcs = new MockAbstractVcs(myProject);
|
||||
myVcsManager = (ProjectLevelVcsManagerImpl)ProjectLevelVcsManager.getInstance(myProject);
|
||||
@@ -109,6 +110,7 @@ public abstract class VcsRootPlatformTest extends UsefulTestCase {
|
||||
point.registerExtension(myExtension);
|
||||
myVcsManager.registerVcs(myVcs);
|
||||
myVcsName = myVcs.getName();
|
||||
myRepository.refresh(false, true);
|
||||
}
|
||||
|
||||
private static ExtensionPoint<VcsRootChecker> getExtensionPoint() {
|
||||
@@ -146,6 +148,7 @@ public abstract class VcsRootPlatformTest extends UsefulTestCase {
|
||||
createProjectStructure(myProject, contentRoots);
|
||||
if (!contentRoots.isEmpty()) {
|
||||
for (String root : contentRoots) {
|
||||
myProjectRoot.refresh(false, true);
|
||||
VirtualFile f = myProjectRoot.findFileByRelativePath(root);
|
||||
if (f != null) {
|
||||
myRootModel.addContentEntry(f);
|
||||
|
||||
@@ -27,4 +27,6 @@ public interface VcsUserRegistry {
|
||||
@NotNull
|
||||
Set<VcsUser> getUsers();
|
||||
|
||||
@NotNull
|
||||
VcsUser createUser(@NotNull String name, @NotNull String email);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.ThrowableComputable;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.Interner;
|
||||
import com.intellij.util.io.*;
|
||||
import com.intellij.vcs.log.VcsUser;
|
||||
import com.intellij.vcs.log.VcsUserRegistry;
|
||||
@@ -52,15 +53,17 @@ public class VcsUserRegistryImpl implements Disposable, VcsUserRegistry {
|
||||
};
|
||||
|
||||
@Nullable private final PersistentEnumerator<VcsUser> myPersistentEnumerator;
|
||||
@NotNull private final Interner<VcsUser> myInterner;
|
||||
|
||||
VcsUserRegistryImpl(@NotNull Project project) {
|
||||
final File mapFile = new File(USER_CACHE_APP_DIR, project.getName() + "." + project.getLocationHash());
|
||||
Disposer.register(project, this);
|
||||
myPersistentEnumerator = initEnumerator(mapFile);
|
||||
myInterner = new Interner<VcsUser>();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PersistentEnumerator<VcsUser> initEnumerator(@NotNull final File mapFile) {
|
||||
private PersistentEnumerator<VcsUser> initEnumerator(@NotNull final File mapFile) {
|
||||
try {
|
||||
return IOUtil.openCleanOrResetBroken(new ThrowableComputable<PersistentEnumerator<VcsUser>, IOException>() {
|
||||
@Override
|
||||
@@ -75,6 +78,12 @@ public class VcsUserRegistryImpl implements Disposable, VcsUserRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public VcsUser createUser(@NotNull String name, @NotNull String email) {
|
||||
return myInterner.intern(new VcsUserImpl(name, email));
|
||||
}
|
||||
|
||||
public void addUser(@NotNull VcsUser user) {
|
||||
try {
|
||||
if (myPersistentEnumerator != null) {
|
||||
@@ -125,7 +134,7 @@ public class VcsUserRegistryImpl implements Disposable, VcsUserRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
private static class MyDescriptor implements KeyDescriptor<VcsUser> {
|
||||
private class MyDescriptor implements KeyDescriptor<VcsUser> {
|
||||
@Override
|
||||
public void save(@NotNull DataOutput out, VcsUser value) throws IOException {
|
||||
IOUtil.writeUTF(out, value.getName());
|
||||
@@ -136,7 +145,7 @@ public class VcsUserRegistryImpl implements Disposable, VcsUserRegistry {
|
||||
public VcsUser read(@NotNull DataInput in) throws IOException {
|
||||
String name = IOUtil.readUTF(in);
|
||||
String email = IOUtil.readUTF(in);
|
||||
return new VcsUserImpl(name, email);
|
||||
return createUser(name, email);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -11,6 +11,14 @@ import java.util.List;
|
||||
|
||||
public class VcsLogObjectsFactoryImpl implements VcsLogObjectsFactory {
|
||||
|
||||
@NotNull private final VcsUserRegistry myUserRegistry;
|
||||
|
||||
// created as application service
|
||||
@SuppressWarnings("unused")
|
||||
private VcsLogObjectsFactoryImpl(@NotNull VcsUserRegistry userRegistry) {
|
||||
myUserRegistry = userRegistry;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Hash createHash(@NotNull String stringHash) {
|
||||
@@ -60,7 +68,7 @@ public class VcsLogObjectsFactoryImpl implements VcsLogObjectsFactory {
|
||||
@NotNull
|
||||
@Override
|
||||
public VcsUser createUser(@NotNull String name, @NotNull String email) {
|
||||
return new VcsUserImpl(name, email);
|
||||
return myUserRegistry.createUser(name, email);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -24,7 +24,6 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.ListCellRendererWrapper;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.GitRemoteBranch;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.commands.GitCommand;
|
||||
@@ -175,7 +174,7 @@ public class GitPullDialog extends DialogWrapper {
|
||||
myBranchChooser.setElements(ContainerUtil.mapNotNull(remoteBranches, new Function<GitRemoteBranch, String>() {
|
||||
@Override
|
||||
public String fun(GitRemoteBranch branch) {
|
||||
return branch.getRemote().getName().equals(selectedRemote) ? branch.getName() : null;
|
||||
return branch.getRemote().getName().equals(selectedRemote) ? branch.getNameForLocalOperations() : null;
|
||||
}
|
||||
}), false);
|
||||
if (currentRemoteBranch != null && currentRemoteBranch.getRemote().getName().equals(selectedRemote)) {
|
||||
|
||||
@@ -61,7 +61,6 @@ public class HgRepositoryImpl extends RepositoryImpl implements HgRepository {
|
||||
private HgRepositoryImpl(@NotNull VirtualFile rootDir, @NotNull HgVcs vcs,
|
||||
@NotNull Disposable parentDisposable) {
|
||||
super(vcs.getProject(), rootDir, parentDisposable);
|
||||
rootDir.refresh(false, true);
|
||||
myHgDir = rootDir.findChild(HgUtil.DOT_HG);
|
||||
assert myHgDir != null : ".hg directory wasn't found under " + rootDir.getPresentableUrl();
|
||||
myReader = new HgRepositoryReader(vcs, VfsUtilCore.virtualToIoFile(myHgDir));
|
||||
|
||||
@@ -59,11 +59,12 @@ public class HgRealRepositoryReaderTest extends HgPlatformTest {
|
||||
|
||||
public void testBranches() {
|
||||
VcsTestUtil.assertEqualCollections(myRepositoryReader.readBranches().keySet(),
|
||||
Arrays.asList("default", "branchA", "branchB"));
|
||||
Arrays.asList("default", "branchA", "branchB"));
|
||||
}
|
||||
|
||||
public void testOpenedBranches() {
|
||||
cd(myRepository);
|
||||
myRepository.refresh(false, true);
|
||||
HgRepository hgRepository = HgRepositoryImpl.getInstance(myRepository, myProject, myProject);
|
||||
hg("up branchA");
|
||||
hg("commit -m 'close branch' --close-branch");
|
||||
@@ -74,12 +75,12 @@ public class HgRealRepositoryReaderTest extends HgPlatformTest {
|
||||
|
||||
public void testTags() {
|
||||
VcsTestUtil.assertEqualCollections(HgUtil.getNamesWithoutHashes(myRepositoryReader.readTags()),
|
||||
Arrays.asList("tag1", "tag2"));
|
||||
Arrays.asList("tag1", "tag2"));
|
||||
}
|
||||
|
||||
public void testLocalTags() {
|
||||
VcsTestUtil.assertEqualCollections(HgUtil.getNamesWithoutHashes(myRepositoryReader.readLocalTags()),
|
||||
Arrays.asList("localTag"));
|
||||
Arrays.asList("localTag"));
|
||||
}
|
||||
|
||||
public void testCurrentBookmark() {
|
||||
@@ -89,7 +90,7 @@ public class HgRealRepositoryReaderTest extends HgPlatformTest {
|
||||
|
||||
public void testBookmarks() {
|
||||
VcsTestUtil.assertEqualCollections(HgUtil.getNamesWithoutHashes(myRepositoryReader.readBookmarks()),
|
||||
Arrays.asList("A_BookMark", "B_BookMark", "C_BookMark"));
|
||||
Arrays.asList("A_BookMark", "B_BookMark", "C_BookMark"));
|
||||
}
|
||||
|
||||
private void createBranchesAndTags() {
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.intellij.openapi.application.QueryExecutorBase;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.Processor;
|
||||
@@ -39,17 +38,16 @@ public class PyKeywordArgumentSearchExecutor extends QueryExecutorBase<PsiRefere
|
||||
if (!(element instanceof PyNamedParameter)) {
|
||||
return;
|
||||
}
|
||||
final ScopeOwner owner = ScopeUtil.getScopeOwner(element);
|
||||
final ScopeOwner owner = ApplicationManager.getApplication().runReadAction(new Computable<ScopeOwner>() {
|
||||
@Override
|
||||
public ScopeOwner compute() {
|
||||
return ScopeUtil.getScopeOwner(element);
|
||||
}
|
||||
});
|
||||
if (!(owner instanceof PyFunction)) {
|
||||
return;
|
||||
}
|
||||
SearchScope scope = ApplicationManager.getApplication().runReadAction(new Computable<SearchScope>() {
|
||||
@Override
|
||||
public SearchScope compute() {
|
||||
return queryParameters.getEffectiveSearchScope();
|
||||
}
|
||||
});
|
||||
ReferencesSearch.search(owner, scope).forEach(new Processor<PsiReference>() {
|
||||
ReferencesSearch.search(owner, queryParameters.getScopeDeterminedByUser()).forEach(new Processor<PsiReference>() {
|
||||
@Override
|
||||
public boolean process(PsiReference reference) {
|
||||
final PsiElement refElement = reference.getElement();
|
||||
|
||||
Reference in New Issue
Block a user