mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' into uta-python
This commit is contained in:
+1
-1
@@ -809,7 +809,7 @@
|
||||
<inspection_tool class="WaitNotInLoop" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="WaitNotInSynchronizedContext" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="WaitWhileHoldingTwoLocks" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="WeakerAccess" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<inspection_tool class="WeakerAccess" enabled="false" level="WARNING" enabled_by_default="true">
|
||||
<option name="SUGGEST_PACKAGE_LOCAL_FOR_MEMBERS" value="false" />
|
||||
<option name="SUGGEST_PACKAGE_LOCAL_FOR_TOP_CLASSES" value="false" />
|
||||
<option name="SUGGEST_PRIVATE_FOR_INNERS" value="false" />
|
||||
|
||||
@@ -214,6 +214,7 @@ libraryLicense(name: "imgscalr", libraryName: "imgscalr", version: "4.2", licens
|
||||
libraryLicense(name: "batik", libraryName: "batik", version: "1.7.1", license: "Apache 2.0", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0.txt", url: "https://svn.apache.org/repos/asf/xmlgraphics/batik")
|
||||
libraryLicense(name: "xmlgraphics-commons", libraryName: "xmlgraphics-commons", version: "1.5", license: "Apache 2.0", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0.txt", url: "https://svn.apache.org/repos/asf/xmlgraphics/commons")
|
||||
libraryLicense(name: "xml-apis-ext", libraryName: "xml-apis-ext", version: "1.3", license: "Apache 2.0", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0.txt", url: "http://xerces.apache.org/xml-commons/components/external")
|
||||
libraryLicense(name: "ImageIO", libraryName: "com.twelvemonkeys.imageio:imageio-tiff:3.2.1", version: "3.2.1", license: "BSD", url: "https://github.com/haraldk/TwelveMonkeys", licenseUrl: "https://github.com/haraldk/TwelveMonkeys#license")
|
||||
libraryLicense(name: "ini4j", libraryName: "ini4j-0.5.2-patched", version: "0.5.2 (with a patch by JetBrains)", license: "Apache 2.0", url: "http://ini4j.sourceforge.net/", attachedTo: "git4idea")
|
||||
libraryLicense(name: "ISO RELAX", libraryName: "isorelax.jar", license: "MIT License", url: "http://sourceforge.net/projects/iso-relax/", licenseUrl: "http://www.opensource.org/licenses/mit-license.html")
|
||||
libraryLicense(name: "Jakarta ORO", libraryName: "OroMatcher", version: "2.0.8", license: "Apache", url: "http://jakarta.apache.org/oro/", licenseUrl: "http://svn.apache.org/repos/asf/jakarta/oro/trunk/LICENSE")
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.intellij.images.editor.ImageEditor;
|
||||
import org.intellij.images.editor.ImageZoomModel;
|
||||
import org.intellij.images.fileTypes.ImageFileTypeManager;
|
||||
import org.intellij.images.thumbnail.actionSystem.ThumbnailViewActions;
|
||||
import org.intellij.images.ui.ImageComponent;
|
||||
import org.intellij.images.vfs.IfsUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -37,13 +36,13 @@ import javax.swing.*;
|
||||
*
|
||||
* @author <a href="mailto:aefimov.box@gmail.com">Alexey Efimov</a>
|
||||
*/
|
||||
final class ImageEditorImpl implements ImageEditor {
|
||||
public final class ImageEditorImpl implements ImageEditor {
|
||||
private final Project project;
|
||||
private final VirtualFile file;
|
||||
private final ImageEditorUI editorUI;
|
||||
private boolean disposed;
|
||||
|
||||
ImageEditorImpl(@NotNull Project project, @NotNull VirtualFile file) {
|
||||
public ImageEditorImpl(@NotNull Project project, @NotNull VirtualFile file) {
|
||||
this.project = project;
|
||||
this.file = file;
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
|
||||
@Override
|
||||
public void visitAnonymousClass(PsiAnonymousClass aClass) {
|
||||
for (PsiMethod psiMethod : aClass.getMethods()) {
|
||||
targets.add(new MethodSmartStepTarget(psiMethod, getCurrentParamName(), psiMethod.getBody(), true, null));
|
||||
targets.add(0, new MethodSmartStepTarget(psiMethod, getCurrentParamName(), psiMethod.getBody(), true, null));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,7 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
|
||||
myInsideLambda = true;
|
||||
super.visitLambdaExpression(expression);
|
||||
myInsideLambda = inLambda;
|
||||
targets.add(new LambdaSmartStepTarget(expression, getCurrentParamName(), expression.getBody(), myNextLambdaExpressionOrdinal++, null));
|
||||
targets.add(0, new LambdaSmartStepTarget(expression, getCurrentParamName(), expression.getBody(), myNextLambdaExpressionOrdinal++, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,7 +122,7 @@ public class JavaSmartStepIntoHandler extends JvmSmartStepIntoHandler {
|
||||
if (element instanceof PsiMethod) {
|
||||
PsiElement navMethod = element.getNavigationElement();
|
||||
if (navMethod instanceof PsiMethod) {
|
||||
targets.add(new MethodSmartStepTarget(((PsiMethod)navMethod), null, expression, true, null));
|
||||
targets.add(0, new MethodSmartStepTarget(((PsiMethod)navMethod), null, expression, true, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,8 +73,9 @@ public abstract class JvmSmartStepIntoHandler {
|
||||
}
|
||||
});
|
||||
ListPopupImpl popup = new ListPopupImpl(popupStep);
|
||||
DebuggerUIUtil.registerExtraHandleShortcuts(popup, XDebuggerActions.STEP_INTO);
|
||||
DebuggerUIUtil.registerExtraHandleShortcuts(popup, XDebuggerActions.SMART_STEP_INTO);
|
||||
DebuggerUIUtil.registerExtraHandleShortcuts(popup, XDebuggerActions.STEP_INTO, XDebuggerActions.SMART_STEP_INTO);
|
||||
popup.setAdText(DebuggerUIUtil.getSelectionShortcutsAdText(XDebuggerActions.STEP_INTO, XDebuggerActions.SMART_STEP_INTO));
|
||||
|
||||
popup.addListSelectionListener(new ListSelectionListener() {
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
popupStep.getScopeHighlighter().dropHighlight();
|
||||
|
||||
@@ -39,6 +39,7 @@ import com.intellij.xdebugger.XSourcePosition;
|
||||
import com.intellij.xdebugger.evaluation.EvaluationMode;
|
||||
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
|
||||
import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl;
|
||||
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -74,6 +75,10 @@ public class JavaDebuggerEvaluator extends XDebuggerEvaluator {
|
||||
|
||||
@Override
|
||||
public void threadAction() {
|
||||
if (DebuggerUIUtil.isObsolete(callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
JavaDebugProcess process = myDebugProcess.getXdebugProcess();
|
||||
if (process == null) {
|
||||
callback.errorOccurred("No debug process");
|
||||
|
||||
@@ -141,6 +141,9 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
|
||||
|
||||
@Override
|
||||
public void contextAction() throws Exception {
|
||||
if (node.isObsolete()) {
|
||||
return;
|
||||
}
|
||||
if (!myContextSet) {
|
||||
myValueDescriptor.setContext(myEvaluationContext);
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ public class RequestHint {
|
||||
}
|
||||
}
|
||||
// smart step feature
|
||||
if (myMethodFilter != null) {
|
||||
if (myMethodFilter != null && !mySteppedOut) {
|
||||
return StepRequest.STEP_OUT;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ public class DefaultCodeFragmentFactory extends CodeFragmentFactory {
|
||||
|
||||
final DebuggerContextImpl debuggerContext = DebuggerManagerEx.getInstanceEx(project).getContext();
|
||||
DebuggerSession debuggerSession = debuggerContext.getDebuggerSession();
|
||||
if (debuggerSession != null) {
|
||||
if (debuggerSession != null && debuggerContext.getSuspendContext() != null) {
|
||||
final Semaphore semaphore = new Semaphore();
|
||||
semaphore.down();
|
||||
final AtomicReference<PsiType> nameRef = new AtomicReference<PsiType>();
|
||||
|
||||
+9
-3
@@ -30,6 +30,7 @@ public abstract class DebuggerContextCommandImpl extends SuspendContextCommandIm
|
||||
|
||||
private final DebuggerContextImpl myDebuggerContext;
|
||||
private final ThreadReferenceProxyImpl myCustomThread; // thread to perform command in
|
||||
private SuspendContextImpl myCustomSuspendContext;
|
||||
|
||||
protected DebuggerContextCommandImpl(@NotNull DebuggerContextImpl debuggerContext) {
|
||||
this(debuggerContext, null);
|
||||
@@ -44,10 +45,15 @@ public abstract class DebuggerContextCommandImpl extends SuspendContextCommandIm
|
||||
@Nullable
|
||||
@Override
|
||||
public SuspendContextImpl getSuspendContext() {
|
||||
if (myCustomThread != null) {
|
||||
return SuspendManagerUtil.findContextByThread(myDebuggerContext.getDebugProcess().getSuspendManager(), getThread());
|
||||
if (myCustomSuspendContext == null) {
|
||||
myCustomSuspendContext = super.getSuspendContext();
|
||||
ThreadReferenceProxyImpl thread = getThread();
|
||||
if (myCustomThread != null &&
|
||||
(myCustomSuspendContext == null || myCustomSuspendContext.isResumed() || !myCustomSuspendContext.suspends(thread))) {
|
||||
myCustomSuspendContext = SuspendManagerUtil.findContextByThread(myDebuggerContext.getDebugProcess().getSuspendManager(), thread);
|
||||
}
|
||||
}
|
||||
return super.getSuspendContext();
|
||||
return myCustomSuspendContext;
|
||||
}
|
||||
|
||||
private ThreadReferenceProxyImpl getThread() {
|
||||
|
||||
+12
-1
@@ -34,6 +34,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.PsiElementProcessor;
|
||||
import com.intellij.psi.util.ClassUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
@@ -163,6 +164,7 @@ public abstract class AbstractPatternBasedConfigurationProducer<T extends Module
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
final PsiElement element = CommonDataKeys.PSI_ELEMENT.getData(dataContext);
|
||||
final VirtualFile[] files = CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext);
|
||||
if (files != null) {
|
||||
Project project = CommonDataKeys.PROJECT.getData(dataContext);
|
||||
@@ -171,7 +173,16 @@ public abstract class AbstractPatternBasedConfigurationProducer<T extends Module
|
||||
for (VirtualFile file : files) {
|
||||
final PsiFile psiFile = psiManager.findFile(file);
|
||||
if (psiFile instanceof PsiClassOwner) {
|
||||
collectTestMembers(((PsiClassOwner)psiFile).getClasses(), checkAbstract, checkIsTest, processor);
|
||||
PsiClass[] psiClasses = ((PsiClassOwner)psiFile).getClasses();
|
||||
if (element != null && psiClasses.length > 0) {
|
||||
for (PsiClass aClass : psiClasses) {
|
||||
if (PsiTreeUtil.isAncestor(aClass, element, false)) {
|
||||
psiClasses = new PsiClass[] {aClass};
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
collectTestMembers(psiClasses, checkAbstract, checkIsTest, processor);
|
||||
for (PsiElement psiMember : processor.getCollection()) {
|
||||
classes.add(((PsiClass)psiMember).getQualifiedName());
|
||||
}
|
||||
|
||||
@@ -98,6 +98,7 @@ public abstract class LanguageLevelCombo extends ComboBox {
|
||||
}
|
||||
else if (!(getItemAt(0) instanceof String)) {
|
||||
addDefaultItem();
|
||||
setSelectedIndex(0);
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
|
||||
+5
-1
@@ -230,7 +230,7 @@ class AccessCanBeTightenedInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
}
|
||||
|
||||
return myVisibilityInspection.SUGGEST_PRIVATE_FOR_INNERS ||
|
||||
memberClass == aClass && memberClass.getContainingClass() == null ? PsiUtil.ACCESS_LEVEL_PRIVATE : suggestPackageLocal(member);
|
||||
!isInnerClass(memberClass) ? PsiUtil.ACCESS_LEVEL_PRIVATE : suggestPackageLocal(member);
|
||||
}
|
||||
//if (file == memberFile) {
|
||||
// return PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL;
|
||||
@@ -253,6 +253,10 @@ class AccessCanBeTightenedInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isInnerClass(@NotNull PsiClass memberClass) {
|
||||
return memberClass.getContainingClass() != null || memberClass instanceof PsiAnonymousClass;
|
||||
}
|
||||
|
||||
private static boolean isInReferenceList(@Nullable PsiElement list, @NotNull final PsiMember member) {
|
||||
if (list == null) return false;
|
||||
final PsiManager psiManager = member.getManager();
|
||||
|
||||
@@ -1230,9 +1230,7 @@ public class ExpectedTypesProvider {
|
||||
final PsiClassType type =
|
||||
substitutor == null ? facade.getElementFactory().createType(aClass) : facade.getElementFactory().createType(aClass, substitutor);
|
||||
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC) ||
|
||||
method.hasModifierProperty(PsiModifier.FINAL) ||
|
||||
method.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC) || method.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
types.add(createInfoImpl(type, ExpectedTypeInfo.TYPE_STRICTLY, type, TailType.DOT));
|
||||
} else if (method.findSuperMethods().length == 0) {
|
||||
types.add(createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, TailType.DOT));
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.daemon;
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.ide.scratch.ScratchFileType;
|
||||
import com.intellij.openapi.roots.JavaProjectRootsUtil;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiFile;
|
||||
@@ -36,8 +37,11 @@ public class JavaProblemHighlightFilter extends ProblemHighlightFilter {
|
||||
if (shouldHighlight) {
|
||||
if (psiFile.getFileType() == JavaFileType.INSTANCE) {
|
||||
final VirtualFile virtualFile = psiFile.getVirtualFile();
|
||||
if (virtualFile != null && ProjectRootManager.getInstance(psiFile.getProject()).getFileIndex().isInLibrarySource(virtualFile)) {
|
||||
return false;
|
||||
if (virtualFile != null) {
|
||||
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(psiFile.getProject()).getFileIndex();
|
||||
if (fileIndex.isInLibrarySource(virtualFile)) {
|
||||
return fileIndex.isInSourceContent(virtualFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.intellij.codeInsight.editorActions.wordSelection;
|
||||
|
||||
import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandler;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiForStatement;
|
||||
import com.intellij.psi.PsiForeachStatement;
|
||||
import com.intellij.psi.PsiJavaToken;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class ForStatementHeaderSelectioner implements ExtendWordSelectionHandler {
|
||||
@Override
|
||||
public boolean canSelect(PsiElement e) {
|
||||
return e instanceof PsiForStatement || e instanceof PsiForeachStatement;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TextRange> select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
|
||||
PsiJavaToken lParen = e instanceof PsiForStatement ? ((PsiForStatement)e).getLParenth()
|
||||
: e instanceof PsiForeachStatement ? ((PsiForeachStatement)e).getLParenth() : null;
|
||||
PsiJavaToken rParen = e instanceof PsiForStatement ? ((PsiForStatement)e).getRParenth()
|
||||
: e instanceof PsiForeachStatement ? ((PsiForeachStatement)e).getRParenth() : null;
|
||||
if (lParen == null || rParen == null) return null;
|
||||
TextRange result = new TextRange(lParen.getTextRange().getEndOffset(), rParen.getTextRange().getStartOffset());
|
||||
return result.containsOffset(cursorOffset) ? Collections.singletonList(result) : null;
|
||||
}
|
||||
}
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 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.
|
||||
@@ -40,8 +40,7 @@ public class MethodOrClassSelectioner extends BasicSelectioner {
|
||||
|
||||
@Override
|
||||
public List<TextRange> select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
|
||||
List<TextRange> result = ContainerUtil.newArrayList(e.getTextRange());
|
||||
result.addAll(expandToWholeLinesWithBlanks(editorText, e.getTextRange()));
|
||||
List<TextRange> result = ContainerUtil.newArrayList();
|
||||
|
||||
PsiElement firstChild = e.getFirstChild();
|
||||
PsiElement[] children = e.getChildren();
|
||||
@@ -77,6 +76,9 @@ public class MethodOrClassSelectioner extends BasicSelectioner {
|
||||
result.addAll(expandToWholeLinesWithBlanks(editorText, range));
|
||||
}
|
||||
|
||||
result.add(e.getTextRange());
|
||||
result.addAll(expandToWholeLinesWithBlanks(editorText, e.getTextRange()));
|
||||
|
||||
if (e instanceof PsiClass) {
|
||||
result.addAll(selectWithTypeParameters((PsiClass)e));
|
||||
result.addAll(selectBetweenBracesLines(children, editorText));
|
||||
|
||||
+20
-18
@@ -21,7 +21,6 @@ import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.components.StoragePathMacros;
|
||||
import com.intellij.openapi.util.Couple;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -30,7 +29,9 @@ import org.jetbrains.java.generate.template.TemplateResource;
|
||||
import org.jetbrains.java.generate.template.TemplatesManager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Set;
|
||||
|
||||
@State(
|
||||
name = "EqualsHashCodeTemplates",
|
||||
@@ -42,14 +43,23 @@ import java.util.*;
|
||||
public class EqualsHashCodeTemplatesManager extends TemplatesManager {
|
||||
private static final String DEFAULT_EQUALS = "/com/intellij/codeInsight/generation/defaultEquals.vm";
|
||||
private static final String DEFAULT_HASH_CODE = "/com/intellij/codeInsight/generation/defaultHashCode.vm";
|
||||
|
||||
private static final String APACHE3_EQUALS = "/com/intellij/codeInsight/generation/apacheEqualsBuilder3.vm";
|
||||
private static final String APACHE3_HASH_CODE = "/com/intellij/codeInsight/generation/apacheHashCodeBuilder3.vm";
|
||||
private static final String APACHE3_BUILDER = "org.apache.commons.lang3.builder.EqualsBuilder";
|
||||
|
||||
private static final String APACHE_EQUALS = "/com/intellij/codeInsight/generation/apacheEqualsBuilder.vm";
|
||||
private static final String APACHE_HASH_CODE = "/com/intellij/codeInsight/generation/apacheHashCodeBuilder.vm";
|
||||
private static final String APACHE_BUILDER = "org.apache.commons.lang.builder.EqualsBuilder";
|
||||
|
||||
|
||||
private static final String GUAVA_EQUALS = "/com/intellij/codeInsight/generation/guavaEquals.vm";
|
||||
private static final String GUAVA_HASH_CODE = "/com/intellij/codeInsight/generation/guavaHashCode.vm";
|
||||
private static final String GUAVA_BUILDER = "com.google.common.base.Objects";
|
||||
|
||||
private static final String OBJECTS_EQUALS = "/com/intellij/codeInsight/generation/objectsEquals.vm";
|
||||
private static final String OBJECTS_HASH_CODE = "/com/intellij/codeInsight/generation/objectsHashCode.vm";
|
||||
private static final String OBJECTS_BUILDER = "java.util.Objects";
|
||||
|
||||
private static final String EQUALS_SUFFIX = "equals";
|
||||
private static final String HASH_CODE_SUFFIX = "hashCode";
|
||||
@@ -72,17 +82,17 @@ public class EqualsHashCodeTemplatesManager extends TemplatesManager {
|
||||
new TemplateResource(toEqualsName(INTELLI_J_DEFAULT), readFile(DEFAULT_EQUALS), true),
|
||||
new TemplateResource(toHashCodeName(INTELLI_J_DEFAULT), readFile(DEFAULT_HASH_CODE), true),
|
||||
|
||||
new TemplateResource(toEqualsName(EQUALS_HASH_CODE_BUILDER_APACHE_COMMONS_LANG), readFile(APACHE_EQUALS), true),
|
||||
new TemplateResource(toHashCodeName(EQUALS_HASH_CODE_BUILDER_APACHE_COMMONS_LANG), readFile(APACHE_HASH_CODE), true),
|
||||
new TemplateResource(toEqualsName(EQUALS_HASH_CODE_BUILDER_APACHE_COMMONS_LANG), readFile(APACHE_EQUALS), true, APACHE_BUILDER),
|
||||
new TemplateResource(toHashCodeName(EQUALS_HASH_CODE_BUILDER_APACHE_COMMONS_LANG), readFile(APACHE_HASH_CODE), true, APACHE_BUILDER),
|
||||
|
||||
new TemplateResource(toEqualsName(EQUALS_HASH_CODE_BUILDER_APACHE_COMMONS_LANG_3), readFile(APACHE3_EQUALS), true),
|
||||
new TemplateResource(toHashCodeName(EQUALS_HASH_CODE_BUILDER_APACHE_COMMONS_LANG_3), readFile(APACHE3_HASH_CODE), true),
|
||||
new TemplateResource(toEqualsName(EQUALS_HASH_CODE_BUILDER_APACHE_COMMONS_LANG_3), readFile(APACHE3_EQUALS), true, APACHE3_BUILDER),
|
||||
new TemplateResource(toHashCodeName(EQUALS_HASH_CODE_BUILDER_APACHE_COMMONS_LANG_3), readFile(APACHE3_HASH_CODE), true, APACHE3_BUILDER),
|
||||
|
||||
new TemplateResource(toEqualsName(OBJECTS_EQUAL_AND_HASH_CODE_GUAVA), readFile(GUAVA_EQUALS), true),
|
||||
new TemplateResource(toHashCodeName(OBJECTS_EQUAL_AND_HASH_CODE_GUAVA), readFile(GUAVA_HASH_CODE), true),
|
||||
new TemplateResource(toEqualsName(OBJECTS_EQUAL_AND_HASH_CODE_GUAVA), readFile(GUAVA_EQUALS), true, GUAVA_BUILDER),
|
||||
new TemplateResource(toHashCodeName(OBJECTS_EQUAL_AND_HASH_CODE_GUAVA), readFile(GUAVA_HASH_CODE), true, GUAVA_BUILDER),
|
||||
|
||||
new TemplateResource(toEqualsName(JAVA_UTIL_OBJECTS_EQUALS_AND_HASH_CODE), readFile(OBJECTS_EQUALS), true),
|
||||
new TemplateResource(toHashCodeName(JAVA_UTIL_OBJECTS_EQUALS_AND_HASH_CODE), readFile(OBJECTS_HASH_CODE), true)
|
||||
new TemplateResource(toEqualsName(JAVA_UTIL_OBJECTS_EQUALS_AND_HASH_CODE), readFile(OBJECTS_EQUALS), true, OBJECTS_BUILDER),
|
||||
new TemplateResource(toHashCodeName(JAVA_UTIL_OBJECTS_EQUALS_AND_HASH_CODE), readFile(OBJECTS_HASH_CODE), true, OBJECTS_BUILDER)
|
||||
};
|
||||
}
|
||||
catch (IOException e) {
|
||||
@@ -110,14 +120,6 @@ public class EqualsHashCodeTemplatesManager extends TemplatesManager {
|
||||
return getDefaultTemplate(HASH_CODE_SUFFIX, EQUALS_SUFFIX, template);
|
||||
}
|
||||
|
||||
public String[] getTemplateNames() {
|
||||
final Set<String> names = new LinkedHashSet<String>();
|
||||
for (TemplateResource resource : getAllTemplates()) {
|
||||
names.add(getTemplateBaseName(resource));
|
||||
}
|
||||
return ArrayUtil.toStringArray(names);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getTemplateBaseName(TemplateResource resource) {
|
||||
return StringUtil.trimEnd(StringUtil.trimEnd(resource.getFileName(), EQUALS_SUFFIX), HASH_CODE_SUFFIX).trim();
|
||||
|
||||
+44
-12
@@ -29,18 +29,21 @@ import com.intellij.openapi.projectRoots.JavaVersionService;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import com.intellij.openapi.ui.ComponentWithBrowseButton;
|
||||
import com.intellij.openapi.ui.VerticalFlowLayout;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.refactoring.classMembers.AbstractMemberInfoModel;
|
||||
import com.intellij.refactoring.classMembers.MemberInfoBase;
|
||||
import com.intellij.refactoring.classMembers.MemberInfoTooltipManager;
|
||||
import com.intellij.refactoring.ui.AbstractMemberSelectionPanel;
|
||||
import com.intellij.refactoring.ui.MemberSelectionPanel;
|
||||
import com.intellij.refactoring.util.classMembers.MemberInfo;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.ListCellRendererWrapper;
|
||||
import com.intellij.ui.NonFocusableCheckBox;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.java.generate.psi.PsiAdapter;
|
||||
import org.jetbrains.java.generate.template.TemplateResource;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
@@ -265,7 +268,7 @@ public class GenerateEqualsWizard extends AbstractGenerateEqualsWizard<PsiClass,
|
||||
@Override
|
||||
protected void addSteps() {
|
||||
if (myEqualsPanel != null) {
|
||||
addStep(new TemplateChooserStep(myClass.hasModifierProperty(PsiModifier.FINAL), myClass.getProject()));
|
||||
addStep(new TemplateChooserStep(myClass.hasModifierProperty(PsiModifier.FINAL), myClass));
|
||||
}
|
||||
super.addSteps();
|
||||
}
|
||||
@@ -352,19 +355,19 @@ public class GenerateEqualsWizard extends AbstractGenerateEqualsWizard<PsiClass,
|
||||
private static class TemplateChooserStep extends StepAdapter {
|
||||
private final JComponent myPanel;
|
||||
|
||||
private TemplateChooserStep(boolean isFinal, Project project) {
|
||||
private TemplateChooserStep(boolean isFinal, PsiClass psiClass) {
|
||||
myPanel = new JPanel(new VerticalFlowLayout());
|
||||
final JPanel templateChooserPanel = new JPanel(new BorderLayout());
|
||||
final JLabel templateChooserLabel = new JLabel(CodeInsightBundle.message("generate.equals.hashcode.template"));
|
||||
templateChooserPanel.add(templateChooserLabel, BorderLayout.WEST);
|
||||
|
||||
|
||||
final ComboBox comboBox = new ComboBox();
|
||||
final ComponentWithBrowseButton<ComboBox> comboBoxWithBrowseButton =
|
||||
new ComponentWithBrowseButton<ComboBox>(comboBox, new MyEditTemplatesListener(project, myPanel, comboBox));
|
||||
new ComponentWithBrowseButton<ComboBox>(comboBox, new MyEditTemplatesListener(psiClass, myPanel, comboBox));
|
||||
templateChooserLabel.setLabelFor(comboBox);
|
||||
final EqualsHashCodeTemplatesManager manager = EqualsHashCodeTemplatesManager.getInstance();
|
||||
comboBox.setModel(new DefaultComboBoxModel(manager.getTemplateNames()));
|
||||
comboBox.setSelectedItem(manager.getDefaultTemplateBaseName());
|
||||
setupCombobox(manager, comboBox, psiClass);
|
||||
comboBox.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(@NotNull final ActionEvent M) {
|
||||
manager.setDefaultTemplate((String)comboBox.getSelectedItem());
|
||||
@@ -400,13 +403,43 @@ public class GenerateEqualsWizard extends AbstractGenerateEqualsWizard<PsiClass,
|
||||
return myPanel;
|
||||
}
|
||||
|
||||
private static void setupCombobox(EqualsHashCodeTemplatesManager templatesManager,
|
||||
ComboBox comboBox,
|
||||
PsiClass psiClass) {
|
||||
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(psiClass.getProject());
|
||||
final GlobalSearchScope resolveScope = psiClass.getResolveScope();
|
||||
final Set<String> names = new LinkedHashSet<String>();
|
||||
|
||||
final Set<String> invalid = new HashSet<String>();
|
||||
for (TemplateResource resource : templatesManager.getAllTemplates()) {
|
||||
final String templateBaseName = EqualsHashCodeTemplatesManager.getTemplateBaseName(resource);
|
||||
if (names.add(templateBaseName)) {
|
||||
final String className = resource.getClassName();
|
||||
if (className != null && psiFacade.findClass(className, resolveScope) == null) {
|
||||
invalid.add(templateBaseName);
|
||||
}
|
||||
}
|
||||
}
|
||||
comboBox.setRenderer(new ListCellRendererWrapper<String>() {
|
||||
@Override
|
||||
public void customize(JList list, String value, int index, boolean selected, boolean hasFocus) {
|
||||
setText(value);
|
||||
if (invalid.contains(value)) {
|
||||
setForeground(JBColor.RED);
|
||||
}
|
||||
}
|
||||
});
|
||||
comboBox.setModel(new DefaultComboBoxModel(names.toArray(new String[names.size()])));
|
||||
comboBox.setSelectedItem(templatesManager.getDefaultTemplateBaseName());
|
||||
}
|
||||
|
||||
private static class MyEditTemplatesListener implements ActionListener {
|
||||
private final Project myProject;
|
||||
private final PsiClass myPsiClass;
|
||||
private final JComponent myParent;
|
||||
private final ComboBox myComboBox;
|
||||
|
||||
public MyEditTemplatesListener(Project project, JComponent panel, ComboBox comboBox) {
|
||||
myProject = project;
|
||||
public MyEditTemplatesListener(PsiClass psiClass, JComponent panel, ComboBox comboBox) {
|
||||
myPsiClass = psiClass;
|
||||
myParent = panel;
|
||||
myComboBox = comboBox;
|
||||
}
|
||||
@@ -414,11 +447,10 @@ public class GenerateEqualsWizard extends AbstractGenerateEqualsWizard<PsiClass,
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final EqualsHashCodeTemplatesManager templatesManager = EqualsHashCodeTemplatesManager.getInstance();
|
||||
final EqualsHashCodeTemplatesPanel ui = new EqualsHashCodeTemplatesPanel(myProject, EqualsHashCodeTemplatesManager.getInstance());
|
||||
final EqualsHashCodeTemplatesPanel ui = new EqualsHashCodeTemplatesPanel(myPsiClass.getProject(), EqualsHashCodeTemplatesManager.getInstance());
|
||||
ui.selectNodeInTree(templatesManager.getDefaultTemplateBaseName());
|
||||
ShowSettingsUtil.getInstance().editConfigurable(myParent, ui);
|
||||
myComboBox.setModel(new DefaultComboBoxModel(templatesManager.getTemplateNames()));
|
||||
myComboBox.setSelectedItem(templatesManager.getDefaultTemplateBaseName());
|
||||
setupCombobox(templatesManager, myComboBox, myPsiClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+5
-3
@@ -26,6 +26,7 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.refactoring.HelpID;
|
||||
import com.intellij.refactoring.RefactoringActionHandler;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
@@ -140,20 +141,21 @@ public class ExtractInterfaceHandler implements RefactoringActionHandler, Elemen
|
||||
String interfaceName,
|
||||
MemberInfo[] selectedMembers,
|
||||
DocCommentPolicy javaDocPolicy) throws IncorrectOperationException {
|
||||
aClass.getProject().getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC)
|
||||
final Project project = aClass.getProject();
|
||||
project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC)
|
||||
.refactoringStarted(ExtractSuperClassUtil.REFACTORING_EXTRACT_SUPER_ID, ExtractSuperClassUtil.createBeforeData(aClass, selectedMembers));
|
||||
final PsiClass anInterface = JavaDirectoryService.getInstance().createInterface(targetDir, interfaceName);
|
||||
try {
|
||||
PsiJavaCodeReferenceElement ref = ExtractSuperClassUtil.createExtendingReference(anInterface, aClass, selectedMembers);
|
||||
final PsiReferenceList referenceList = aClass.isInterface() ? aClass.getExtendsList() : aClass.getImplementsList();
|
||||
assert referenceList != null;
|
||||
referenceList.add(ref);
|
||||
CodeStyleManager.getInstance(project).reformat(referenceList.add(ref));
|
||||
PullUpProcessor pullUpHelper = new PullUpProcessor(aClass, anInterface, selectedMembers, javaDocPolicy);
|
||||
pullUpHelper.moveMembersToBase();
|
||||
return anInterface;
|
||||
}
|
||||
finally {
|
||||
aClass.getProject().getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC)
|
||||
project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC)
|
||||
.refactoringDone(ExtractSuperClassUtil.REFACTORING_EXTRACT_SUPER_ID, ExtractSuperClassUtil.createAfterData(anInterface));
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -95,10 +95,11 @@ public class ExtractSuperClassUtil {
|
||||
|
||||
// make original class extend extracted superclass
|
||||
PsiJavaCodeReferenceElement ref = createExtendingReference(superclass, subclass, selectedMemberInfos);
|
||||
final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
|
||||
if (subClassExtends != null) {
|
||||
subclass.getExtendsList().add(ref);
|
||||
codeStyleManager.reformat(subclass.getExtendsList().add(ref));
|
||||
} else if (subclass instanceof PsiAnonymousClass) {
|
||||
((PsiAnonymousClass)subclass).getBaseClassReference().replace(ref);
|
||||
codeStyleManager.reformat(((PsiAnonymousClass)subclass).getBaseClassReference().replace(ref));
|
||||
}
|
||||
|
||||
PullUpProcessor pullUpHelper = new PullUpProcessor(subclass, superclass, selectedMemberInfos,
|
||||
|
||||
+10
-1
@@ -302,7 +302,11 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
|
||||
final InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(project);
|
||||
PsiElement elementAtStart = file.findElementAt(startOffset);
|
||||
if (elementAtStart == null || elementAtStart instanceof PsiWhiteSpace || elementAtStart instanceof PsiComment) {
|
||||
elementAtStart = PsiTreeUtil.skipSiblingsForward(elementAtStart, PsiWhiteSpace.class, PsiComment.class);
|
||||
final PsiElement element = PsiTreeUtil.skipSiblingsForward(elementAtStart, PsiWhiteSpace.class, PsiComment.class);
|
||||
if (element != null) {
|
||||
startOffset = element.getTextOffset();
|
||||
elementAtStart = file.findElementAt(startOffset);
|
||||
}
|
||||
if (elementAtStart == null) {
|
||||
if (injectedLanguageManager.isInjectedFragment(file)) {
|
||||
return getSelectionFromInjectedHost(project, file, injectedLanguageManager, startOffset, endOffset);
|
||||
@@ -323,6 +327,11 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase {
|
||||
|
||||
PsiElement elementAt = PsiTreeUtil.findCommonParent(elementAtStart, elementAtEnd);
|
||||
final PsiExpression containingExpression = PsiTreeUtil.getParentOfType(elementAt, PsiExpression.class, false);
|
||||
|
||||
if (containingExpression != null && containingExpression == elementAtEnd && startOffset == containingExpression.getTextOffset()) {
|
||||
return containingExpression;
|
||||
}
|
||||
|
||||
if (containingExpression == null || containingExpression instanceof PsiLambdaExpression) {
|
||||
if (injectedLanguageManager.isInjectedFragment(file)) {
|
||||
return getSelectionFromInjectedHost(project, file, injectedLanguageManager, startOffset, endOffset);
|
||||
|
||||
@@ -17,7 +17,6 @@ package com.intellij.refactoring.memberPushDown;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.ChangeContextUtil;
|
||||
import com.intellij.codeInsight.generation.OverrideImplementExploreUtil;
|
||||
import com.intellij.codeInsight.generation.OverrideImplementUtil;
|
||||
import com.intellij.codeInsight.intention.impl.CreateClassDialog;
|
||||
import com.intellij.codeInsight.intention.impl.CreateSubclassAction;
|
||||
@@ -319,13 +318,6 @@ public class PushDownProcessor extends BaseRefactoringProcessor {
|
||||
}
|
||||
|
||||
private void decodeRefs(final PsiMember member, final PsiClass targetClass) {
|
||||
try {
|
||||
ChangeContextUtil.decodeContextInfo(member, null, null);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
|
||||
final PsiElementFactory factory = JavaPsiFacade.getInstance(myProject).getElementFactory();
|
||||
member.accept(new JavaRecursiveElementWalkingVisitor() {
|
||||
@Override public void visitReferenceExpression(PsiReferenceExpression expression) {
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ public class SafeDeleteExtendsClassUsageInfo extends SafeDeleteReferenceUsageInf
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(refClass.getProject()).getElementFactory();
|
||||
|
||||
final PsiReferenceList extendsList = refClass.getExtendsList();
|
||||
final PsiReferenceList extendingImplementsList = myExtendingClass.getImplementsList();
|
||||
final PsiReferenceList extendingImplementsList = myExtendingClass instanceof PsiTypeParameter ? myExtendingClass.getExtendsList() : myExtendingClass.getImplementsList();
|
||||
if (extendsList != null) {
|
||||
final PsiClassType[] referenceTypes = extendsList.getReferencedTypes();
|
||||
final PsiReferenceList listToAddExtends = refClass.isInterface() == myExtendingClass.isInterface() || myExtendingClass instanceof PsiTypeParameter ? myExtendingClass.getExtendsList() : extendingImplementsList;
|
||||
|
||||
@@ -154,12 +154,26 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
|
||||
final Set<PsiClass> occurrenceClasses = new HashSet<PsiClass>();
|
||||
for (final PsiExpression occurrence : myOccurrences) {
|
||||
final PsiType occurrenceType = occurrence.getType();
|
||||
collectOccurrenceClasses(occurrenceClasses, occurrenceType);
|
||||
}
|
||||
return new ExpectedTypeUtil.ExpectedClassesFromSetProvider(occurrenceClasses);
|
||||
}
|
||||
|
||||
private static void collectOccurrenceClasses(Set<PsiClass> occurrenceClasses, PsiType occurrenceType) {
|
||||
if (occurrenceType instanceof PsiIntersectionType) {
|
||||
for (PsiType type : ((PsiIntersectionType)occurrenceType).getConjuncts()) {
|
||||
collectOccurrenceClasses(occurrenceClasses, type);
|
||||
}
|
||||
}
|
||||
else if (occurrenceType instanceof PsiCapturedWildcardType) {
|
||||
collectOccurrenceClasses(occurrenceClasses, ((PsiCapturedWildcardType)occurrenceType).getUpperBound());
|
||||
}
|
||||
else {
|
||||
final PsiClass aClass = PsiUtil.resolveClassInType(occurrenceType);
|
||||
if (aClass != null) {
|
||||
occurrenceClasses.add(aClass);
|
||||
}
|
||||
}
|
||||
return new ExpectedTypeUtil.ExpectedClassesFromSetProvider(occurrenceClasses);
|
||||
}
|
||||
|
||||
private PsiType[] getTypesForMain() {
|
||||
|
||||
@@ -46,10 +46,7 @@ import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.refactoring.PackageWrapper;
|
||||
import com.intellij.refactoring.introduceField.ElementToWorkOn;
|
||||
import com.intellij.refactoring.introduceVariable.IntroduceVariableBase;
|
||||
@@ -389,14 +386,18 @@ public class RefactoringUtil {
|
||||
PsiElementFactory factory = JavaPsiFacade.getInstance(expr.getProject()).getElementFactory();
|
||||
PsiType type = getTypeByExpression(expr, factory);
|
||||
final boolean isFunctionalType = type instanceof PsiLambdaExpressionType || type instanceof PsiMethodReferenceType || type instanceof PsiLambdaParameterType;
|
||||
if (type != null && !isFunctionalType) {
|
||||
final boolean isDenotable = PsiTypesUtil.isDenotableType(expr.getType());
|
||||
if (type != null && !isFunctionalType && isDenotable) {
|
||||
return type;
|
||||
}
|
||||
ExpectedTypeInfo[] expectedTypes = ExpectedTypesProvider.getInstance(expr.getProject()).getExpectedTypes(expr, false);
|
||||
if (expectedTypes.length == 1 || isFunctionalType && expectedTypes.length > 0) {
|
||||
if (expectedTypes.length == 1 || (isFunctionalType || !isDenotable)&& expectedTypes.length > 0 ) {
|
||||
type = expectedTypes[0].getType();
|
||||
if (!type.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) return type;
|
||||
}
|
||||
if (!isDenotable) {
|
||||
return type;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,10 +23,7 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public class MethodSignatureUtil {
|
||||
@@ -323,20 +320,16 @@ public class MethodSignatureUtil {
|
||||
result = result.put(superTypeParameters[i], factory.createType(methodTypeParameter));
|
||||
}
|
||||
|
||||
final PsiSubstitutor methodSubstitutor = methodSignature.getSubstitutor();
|
||||
|
||||
//check bounds
|
||||
for (int i = 0; i < methodTypeParameters.length; i++) {
|
||||
PsiTypeParameter methodTypeParameter = methodTypeParameters[i];
|
||||
PsiTypeParameter superTypeParameter = superTypeParameters[i];
|
||||
final Set<PsiType> methodSupers = new HashSet<PsiType>();
|
||||
for (PsiClassType methodSuper : methodTypeParameter.getSuperTypes()) {
|
||||
methodSupers.add(methodSubstitutor.substitute(methodSuper));
|
||||
}
|
||||
Collections.addAll(methodSupers, methodTypeParameter.getSuperTypes());
|
||||
|
||||
final Set<PsiType> superSupers = new HashSet<PsiType>();
|
||||
for (PsiClassType superSuper : superTypeParameter.getSuperTypes()) {
|
||||
superSupers.add(methodSubstitutor.substitute(result.substitute(superSuper)));
|
||||
superSupers.add(result.substitute(superSuper));
|
||||
}
|
||||
methodSupers.remove(PsiType.getJavaLangObject(methodTypeParameter.getManager(), methodTypeParameter.getResolveScope()));
|
||||
superSupers.remove(PsiType.getJavaLangObject(superTypeParameter.getManager(), superTypeParameter.getResolveScope()));
|
||||
|
||||
@@ -207,8 +207,8 @@ public class PsiSuperMethodImplUtil {
|
||||
}
|
||||
if (nameHint != null && !nameHint.equals(method.getName())) continue;
|
||||
if (!includePrivates && method.hasModifierProperty(PsiModifier.PRIVATE)) continue;
|
||||
final MethodSignatureBackedByPsiMethod signature = MethodSignatureBackedByPsiMethod.create(method, substitutor, isInRawContext);
|
||||
HierarchicalMethodSignatureImpl newH = new HierarchicalMethodSignatureImpl(signature);
|
||||
final MethodSignatureBackedByPsiMethod signature = MethodSignatureBackedByPsiMethod.create(method, PsiSubstitutor.EMPTY, isInRawContext);
|
||||
HierarchicalMethodSignatureImpl newH = new HierarchicalMethodSignatureImpl(MethodSignatureBackedByPsiMethod.create(method, substitutor, isInRawContext));
|
||||
|
||||
List<PsiMethod> list = sameParameterErasureMethods.get(signature);
|
||||
if (list == null) {
|
||||
@@ -238,7 +238,7 @@ public class PsiSuperMethodImplUtil {
|
||||
List<Pair<MethodSignature, HierarchicalMethodSignature>> flattened = new ArrayList<Pair<MethodSignature, HierarchicalMethodSignature>>();
|
||||
for (Map.Entry<MethodSignature, HierarchicalMethodSignature> entry : superResult.entrySet()) {
|
||||
HierarchicalMethodSignature hms = entry.getValue();
|
||||
MethodSignature signature = entry.getKey();
|
||||
MethodSignature signature = MethodSignatureBackedByPsiMethod.create(hms.getMethod(), hms.getSubstitutor(), hms.isRaw());
|
||||
PsiClass containingClass = hms.getMethod().getContainingClass();
|
||||
List<HierarchicalMethodSignature> supers = new ArrayList<HierarchicalMethodSignature>(hms.getSuperSignatures());
|
||||
for (HierarchicalMethodSignature aSuper : supers) {
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.intellij.psi.impl.source.resolve.graphInference;
|
||||
|
||||
import com.intellij.psi.PsiCall;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiSubstitutor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
class CompoundInitialState {
|
||||
private PsiSubstitutor myInitialSubstitutor;
|
||||
private Map<PsiElement, InitialInferenceState> myInitialStates;
|
||||
|
||||
CompoundInitialState(PsiSubstitutor initialSubstitutor,
|
||||
Map<PsiElement, InitialInferenceState> initialStates) {
|
||||
myInitialSubstitutor = initialSubstitutor;
|
||||
myInitialStates = initialStates;
|
||||
}
|
||||
|
||||
PsiSubstitutor getInitialSubstitutor() {
|
||||
return myInitialSubstitutor;
|
||||
}
|
||||
|
||||
Map<PsiElement, InitialInferenceState> getInitialStates() {
|
||||
return myInitialStates;
|
||||
}
|
||||
|
||||
InitialInferenceState getInitialState(PsiCall call) {
|
||||
return myInitialStates.get(call);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -167,7 +167,7 @@ public class InferenceIncorporationPhase {
|
||||
|
||||
for (PsiType lowerBound : lowerBounds) {
|
||||
if (mySession.getInferenceVariable(lowerBound) == null) {
|
||||
addConstraint(new StrictSubtypingConstraint(lowerBound, superBound));
|
||||
addConstraint(new StrictSubtypingConstraint(superBound, lowerBound));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+32
-8
@@ -156,6 +156,11 @@ public class InferenceSession {
|
||||
}
|
||||
if (parameters.length > 0) {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
//don't infer anything if number of parameters differ and method is not vararg
|
||||
if (!varargs && i >= parameters.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (args[i] != null && isPertinentToApplicability(args[i], method)) {
|
||||
PsiType parameterType = getParameterType(parameters, i, mySiteSubstitutor, varargs);
|
||||
addConstraint(new ExpressionCompatibilityConstraint(args[i], substituteWithInferenceVariables(parameterType)));
|
||||
@@ -406,9 +411,8 @@ public class InferenceSession {
|
||||
}
|
||||
}
|
||||
}
|
||||
final InferenceSession nestedCallSession = myInferenceSessionContainer.findNestedCallSession(arg, this);
|
||||
final PsiType parameterType =
|
||||
nestedCallSession.substituteWithInferenceVariables(getParameterType(parameters, i, siteSubstitutor, varargs));
|
||||
final PsiSubstitutor nestedSubstitutor = myInferenceSessionContainer.findNestedSubstitutor(arg, myInferenceSubstitution);
|
||||
final PsiType parameterType = nestedSubstitutor.substitute(getParameterType(parameters, i, siteSubstitutor, varargs));
|
||||
if (!isPertinentToApplicability(arg, parentMethod)) {
|
||||
additionalConstraints.add(new ExpressionCompatibilityConstraint(arg, parameterType));
|
||||
}
|
||||
@@ -584,13 +588,14 @@ public class InferenceSession {
|
||||
return mySiteSubstitutor;
|
||||
}
|
||||
|
||||
public InitialInferenceState createInitialState() {
|
||||
return new InitialInferenceState(myInferenceVariables,
|
||||
public InitialInferenceState createInitialState(InferenceSessionContainer container, PsiSubstitutor topInferenceSubstitutor) {
|
||||
return new InitialInferenceState(myInferenceVariables,
|
||||
topInferenceSubstitutor,
|
||||
myContext,
|
||||
myInferenceSubstitution,
|
||||
mySiteSubstitutor,
|
||||
myIncorporationPhase.getCaptures(),
|
||||
myInferenceSessionContainer);
|
||||
container);
|
||||
}
|
||||
|
||||
public void initBounds(PsiTypeParameter... typeParameters) {
|
||||
@@ -669,7 +674,7 @@ public class InferenceSession {
|
||||
}
|
||||
substitutedCapture = elementFactory.createType(psiClass, newParameters);
|
||||
|
||||
myIncorporationPhase.addCapture(copy, substitutedCapture);
|
||||
myIncorporationPhase.addCapture(copy, (PsiClassType)returnType);
|
||||
addConstraint(new TypeCompatibilityConstraint(targetType, substitutedCapture));
|
||||
}
|
||||
} else {
|
||||
@@ -848,6 +853,17 @@ public class InferenceSession {
|
||||
|
||||
public boolean collectDependencies(@Nullable PsiType type,
|
||||
@Nullable final Set<InferenceVariable> dependencies) {
|
||||
return collectDependencies(type, dependencies, new Function<PsiClassType, InferenceVariable>() {
|
||||
@Override
|
||||
public InferenceVariable fun(PsiClassType classType) {
|
||||
return getInferenceVariable(classType);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean collectDependencies(@Nullable PsiType type,
|
||||
@Nullable final Set<InferenceVariable> dependencies,
|
||||
final Function<PsiClassType, InferenceVariable> fun) {
|
||||
if (type == null) return true;
|
||||
final Boolean isProper = type.accept(new PsiTypeVisitor<Boolean>() {
|
||||
@Nullable
|
||||
@@ -879,7 +895,7 @@ public class InferenceSession {
|
||||
@Nullable
|
||||
@Override
|
||||
public Boolean visitClassType(PsiClassType classType) {
|
||||
final InferenceVariable inferenceVariable = getInferenceVariable(classType);
|
||||
final InferenceVariable inferenceVariable = fun.fun(classType);
|
||||
if (inferenceVariable != null) {
|
||||
if (dependencies != null) {
|
||||
dependencies.add(inferenceVariable);
|
||||
@@ -1727,6 +1743,10 @@ public class InferenceSession {
|
||||
return myInferenceSubstitution.substitute(type);
|
||||
}
|
||||
|
||||
public PsiSubstitutor getInferenceSubstitution() {
|
||||
return myInferenceSubstitution;
|
||||
}
|
||||
|
||||
public InferenceSessionContainer getInferenceSessionContainer() {
|
||||
return myInferenceSessionContainer;
|
||||
}
|
||||
@@ -1790,4 +1810,8 @@ public class InferenceSession {
|
||||
public List<String> getIncompatibleErrorMessages() {
|
||||
return myErrorMessages;
|
||||
}
|
||||
|
||||
public boolean isErased() {
|
||||
return myErased;
|
||||
}
|
||||
}
|
||||
|
||||
+86
-54
@@ -17,21 +17,15 @@ package com.intellij.psi.impl.source.resolve.graphInference;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.constraints.ExpressionCompatibilityConstraint;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.*;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
public class InferenceSessionContainer {
|
||||
private static final Logger LOG = Logger.getInstance("#" + InferenceSessionContainer.class.getName());
|
||||
@@ -46,15 +40,15 @@ public class InferenceSessionContainer {
|
||||
}
|
||||
|
||||
@Contract("_, !null -> !null")
|
||||
public InferenceSession findNestedCallSession(PsiElement arg, @Nullable InferenceSession defaultSession) {
|
||||
public PsiSubstitutor findNestedSubstitutor(PsiElement arg, @Nullable PsiSubstitutor defaultSession) {
|
||||
InferenceSession session = myNestedSessions.get(PsiTreeUtil.getParentOfType(arg, PsiCall.class));
|
||||
return session == null ? defaultSession : session;
|
||||
return session == null ? defaultSession : session.getInferenceSubstitution();
|
||||
}
|
||||
|
||||
public void registerNestedSession(InferenceSession session,
|
||||
PsiType returnType,
|
||||
PsiExpression returnExpression) {
|
||||
final InferenceSession callSession = findNestedCallSession(((PsiCallExpression)returnExpression).getArgumentList(), null);
|
||||
void registerNestedSession(InferenceSession session,
|
||||
PsiType returnType,
|
||||
PsiExpression returnExpression) {
|
||||
final PsiSubstitutor callSession = findNestedSubstitutor(((PsiCallExpression)returnExpression).getArgumentList(), null);
|
||||
if (callSession == null) {
|
||||
final InferenceSession inferenceSession =
|
||||
ExpressionCompatibilityConstraint.reduceExpressionCompatibilityConstraint(session, returnExpression, returnType);
|
||||
@@ -73,19 +67,29 @@ public class InferenceSessionContainer {
|
||||
final PsiExpressionList argumentList = ((PsiCall)parent).getArgumentList();
|
||||
final MethodCandidateInfo.CurrentCandidateProperties properties = MethodCandidateInfo.getCurrentMethod(argumentList);
|
||||
if (properties != null && !properties.isApplicabilityCheck()) {
|
||||
final Pair<PsiSubstitutor, Map<PsiElement, InitialInferenceState>>
|
||||
session = PsiResolveHelper.ourGraphGuard.doPreventingRecursion(parent, false,
|
||||
new Computable<Pair<PsiSubstitutor, Map<PsiElement, InitialInferenceState>>>() {
|
||||
@Override
|
||||
public Pair<PsiSubstitutor, Map<PsiElement, InitialInferenceState>> compute() {
|
||||
return createValue(parent);
|
||||
}
|
||||
});
|
||||
final InferenceSession session = PsiResolveHelper.ourGraphGuard.doPreventingRecursion(parent, false,
|
||||
new Computable<InferenceSession>() {
|
||||
@Override
|
||||
public InferenceSession compute() {
|
||||
if (MethodCandidateInfo.isOverloadCheck()) {
|
||||
return startTopLevelInference(parent);
|
||||
}
|
||||
return CachedValuesManager.getCachedValue(parent,
|
||||
new CachedValueProvider<InferenceSession>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Result<InferenceSession> compute() {
|
||||
return new Result<InferenceSession>(startTopLevelInference(parent), PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if (session != null) {
|
||||
final InitialInferenceState initialInferenceState = session.second.get(PsiTreeUtil.getParentOfType(argumentList, PsiCall.class));
|
||||
final CompoundInitialState compoundInitialState = createState(session);
|
||||
final InitialInferenceState initialInferenceState = compoundInitialState.getInitialState(PsiTreeUtil.getParentOfType(argumentList, PsiCall.class));
|
||||
if (initialInferenceState != null) {
|
||||
|
||||
return new InferenceSession(initialInferenceState).collectAdditionalAndInfer(parameters, arguments, properties, session.first);
|
||||
return new InferenceSession(initialInferenceState)
|
||||
.collectAdditionalAndInfer(parameters, arguments, properties, compoundInitialState.getInitialSubstitutor());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -95,23 +99,41 @@ public class InferenceSessionContainer {
|
||||
inferenceSession.initExpressionConstraints(parameters, arguments, parent, null);
|
||||
return inferenceSession.infer(parameters, arguments, parent);
|
||||
}
|
||||
|
||||
private static CompoundInitialState createState(InferenceSession topLevelSession) {
|
||||
final PsiSubstitutor topInferenceSubstitutor = replaceVariables(topLevelSession.getInferenceVariables());
|
||||
final Map<PsiElement, InitialInferenceState> nestedStates = new LinkedHashMap<PsiElement, InitialInferenceState>();
|
||||
|
||||
private static Pair<PsiSubstitutor, Map<PsiElement, InitialInferenceState>> createValue(@NotNull final PsiElement parent) {
|
||||
if (MethodCandidateInfo.isOverloadCheck()) {
|
||||
return startTopLevelInference(parent);
|
||||
final InferenceSessionContainer copy = new InferenceSessionContainer() {
|
||||
@Override
|
||||
public PsiSubstitutor findNestedSubstitutor(PsiElement arg, @Nullable PsiSubstitutor defaultSession) {
|
||||
final InitialInferenceState state = nestedStates.get(PsiTreeUtil.getParentOfType(arg, PsiCall.class));
|
||||
if (state != null) {
|
||||
return state.getInferenceSubstitutor();
|
||||
}
|
||||
return super.findNestedSubstitutor(arg, defaultSession);
|
||||
}
|
||||
};
|
||||
final Map<PsiElement, InferenceSession> nestedSessions = topLevelSession.getInferenceSessionContainer().myNestedSessions;
|
||||
for (Map.Entry<PsiElement, InferenceSession> entry : nestedSessions.entrySet()) {
|
||||
nestedStates.put(entry.getKey(), entry.getValue().createInitialState(copy, topInferenceSubstitutor));
|
||||
}
|
||||
return CachedValuesManager.getCachedValue(parent,
|
||||
new CachedValueProvider<Pair<PsiSubstitutor, Map<PsiElement, InitialInferenceState>>>() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Result<Pair<PsiSubstitutor, Map<PsiElement, InitialInferenceState>>> compute() {
|
||||
return new Result<Pair<PsiSubstitutor, Map<PsiElement, InitialInferenceState>>>(
|
||||
startTopLevelInference(parent), PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
});
|
||||
|
||||
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
|
||||
for (InferenceVariable variable : topLevelSession.getInferenceVariables()) {
|
||||
final PsiType instantiation = variable.getInstantiation();
|
||||
if (instantiation != PsiType.NULL) {
|
||||
final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(topInferenceSubstitutor.substitute(variable));
|
||||
if (psiClass instanceof InferenceVariable) {
|
||||
substitutor = substitutor.put((PsiTypeParameter)psiClass, instantiation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new CompoundInitialState(substitutor, nestedStates);
|
||||
}
|
||||
|
||||
private static Pair<PsiSubstitutor, Map<PsiElement, InitialInferenceState>> startTopLevelInference(@NotNull final PsiElement parent) {
|
||||
private static InferenceSession startTopLevelInference(@NotNull final PsiElement parent) {
|
||||
final PsiCall topLevelCall = treeWalkUp(parent);
|
||||
if (topLevelCall != null) {
|
||||
final JavaResolveResult result = topLevelCall.resolveMethodGenerics();
|
||||
@@ -125,28 +147,38 @@ public class InferenceSessionContainer {
|
||||
new InferenceSession(method.getTypeParameters(), ((MethodCandidateInfo)result).getSiteSubstitutor(), topLevelCall.getManager(), topLevelCall);
|
||||
topLevelSession.initExpressionConstraints(topLevelParameters, topLevelArguments, topLevelCall, method, ((MethodCandidateInfo)result).isVarargs());
|
||||
topLevelSession.infer(topLevelParameters, topLevelArguments, topLevelCall, ((MethodCandidateInfo)result).createProperties());
|
||||
|
||||
final Map<PsiElement, InferenceSession> nestedSessions = topLevelSession.getInferenceSessionContainer().myNestedSessions;
|
||||
Map<PsiElement, InitialInferenceState> nestedStates = new LinkedHashMap<PsiElement, InitialInferenceState>();
|
||||
for (Map.Entry<PsiElement, InferenceSession> entry : nestedSessions.entrySet()) {
|
||||
nestedStates.put(entry.getKey(), entry.getValue().createInitialState());
|
||||
}
|
||||
|
||||
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
|
||||
for (InferenceVariable variable : topLevelSession.getInferenceVariables()) {
|
||||
final PsiType instantiation = variable.getInstantiation();
|
||||
if (instantiation != PsiType.NULL) {
|
||||
substitutor = substitutor.put(variable, instantiation);
|
||||
}
|
||||
}
|
||||
|
||||
return Pair.create(substitutor, nestedStates);
|
||||
return topLevelSession;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiSubstitutor replaceVariables(Collection<InferenceVariable> inferenceVariables) {
|
||||
final List<InferenceVariable> targetVars = new ArrayList<InferenceVariable>();
|
||||
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
|
||||
final InferenceVariable[] oldVars = inferenceVariables.toArray(new InferenceVariable[inferenceVariables.size()]);
|
||||
for (InferenceVariable variable : oldVars) {
|
||||
final InferenceVariable newVariable = new InferenceVariable(variable.getCallContext(), variable.getParameter());
|
||||
substitutor = substitutor.put(variable, JavaPsiFacade.getElementFactory(variable.getProject()).createType(newVariable));
|
||||
targetVars.add(newVariable);
|
||||
if (variable.isThrownBound()) {
|
||||
newVariable.setThrownBound();
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < targetVars.size(); i++) {
|
||||
InferenceVariable var = targetVars.get(i);
|
||||
for (InferenceBound boundType : InferenceBound.values()) {
|
||||
for (PsiType bound : oldVars[i].getBounds(boundType)) {
|
||||
var.addBound(substitutor.substitute(bound), boundType);
|
||||
}
|
||||
}
|
||||
}
|
||||
return substitutor;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiCall treeWalkUp(PsiElement context) {
|
||||
if (context instanceof PsiExpression && !PsiPolyExpressionUtil.isPolyExpression((PsiExpression)context)) {
|
||||
|
||||
+39
-37
@@ -17,12 +17,14 @@ package com.intellij.psi.impl.source.resolve.graphInference;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class InitialInferenceState {
|
||||
class InitialInferenceState {
|
||||
private final Set<InferenceVariable> myInferenceVariables;
|
||||
private final PsiElement myContext;
|
||||
|
||||
@@ -31,48 +33,48 @@ public class InitialInferenceState {
|
||||
private final List<Pair<PsiTypeParameter[], PsiClassType>> myCaptures;
|
||||
private final InferenceSessionContainer myInferenceSessionContainer;
|
||||
|
||||
public InitialInferenceState(Set<InferenceVariable> inferenceVariables,
|
||||
PsiElement context,
|
||||
PsiSubstitutor inferenceSubstitutor,
|
||||
PsiSubstitutor siteSubstitutor,
|
||||
List<Pair<PsiTypeParameter[], PsiClassType>> captures,
|
||||
InferenceSessionContainer inferenceSessionContainer) {
|
||||
myInferenceVariables = inferenceVariables;
|
||||
myContext = context;
|
||||
myInferenceSubstitutor = inferenceSubstitutor;
|
||||
mySiteSubstitutor = siteSubstitutor;
|
||||
myCaptures = captures;
|
||||
myInferenceSessionContainer = inferenceSessionContainer;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static PsiSubstitutor copyVariables(List<InferenceVariable> targetVars,
|
||||
Set<InferenceVariable> inferenceVariables,
|
||||
PsiElement context) {
|
||||
InitialInferenceState(Set<InferenceVariable> inferenceVariables,
|
||||
PsiSubstitutor topInferenceSubstitutor,
|
||||
PsiElement context,
|
||||
PsiSubstitutor inferenceSubstitutor,
|
||||
PsiSubstitutor siteSubstitutor,
|
||||
List<Pair<PsiTypeParameter[], PsiClassType>> captures,
|
||||
InferenceSessionContainer inferenceSessionContainer) {
|
||||
myInferenceVariables = new HashSet<InferenceVariable>();
|
||||
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
|
||||
final InferenceVariable[] oldVars = inferenceVariables.toArray(new InferenceVariable[inferenceVariables.size()]);
|
||||
for (InferenceVariable variable : oldVars) {
|
||||
final InferenceVariable newVariable = new InferenceVariable(context, variable.getParameter());
|
||||
substitutor = substitutor.put(variable, JavaPsiFacade.getElementFactory(variable.getProject()).createType(newVariable));
|
||||
targetVars.add(newVariable);
|
||||
}
|
||||
|
||||
for (int i = 0; i < targetVars.size(); i++) {
|
||||
InferenceVariable var = targetVars.get(i);
|
||||
for (InferenceBound boundType : InferenceBound.values()) {
|
||||
for (PsiType bound : oldVars[i].getBounds(boundType)) {
|
||||
var.addBound(substitutor.substitute(bound), boundType);
|
||||
PsiSubstitutor subst = PsiSubstitutor.EMPTY;
|
||||
for (InferenceVariable variable : inferenceVariables) {
|
||||
final PsiType substitute = topInferenceSubstitutor.substitute(variable);
|
||||
final PsiClass aClass = PsiUtil.resolveClassInClassTypeOnly(substitute);
|
||||
if (aClass instanceof InferenceVariable) {
|
||||
myInferenceVariables.add((InferenceVariable)aClass);
|
||||
if (inferenceSubstitutor.getSubstitutionMap().containsValue(PsiSubstitutor.EMPTY.substitute(variable))) {
|
||||
substitutor = substitutor.put(variable.getParameter(), substitute);
|
||||
subst = subst.put(variable, substitute);
|
||||
}
|
||||
}
|
||||
}
|
||||
return substitutor;
|
||||
myInferenceSubstitutor = substitutor;
|
||||
myContext = context;
|
||||
mySiteSubstitutor = siteSubstitutor;
|
||||
myCaptures = new ArrayList<Pair<PsiTypeParameter[], PsiClassType>>();
|
||||
for (Pair<PsiTypeParameter[], PsiClassType> capture : captures) {
|
||||
PsiTypeParameter[] newParameters = new PsiTypeParameter[capture.first.length];
|
||||
PsiTypeParameter[] parameters = capture.first;
|
||||
for (int i = 0; i < parameters.length; i++) {
|
||||
final PsiType substitute = topInferenceSubstitutor.substitute(parameters[i]);
|
||||
newParameters[i] = (PsiTypeParameter)PsiUtil.resolveClassInClassTypeOnly(substitute);
|
||||
}
|
||||
myCaptures.add(Pair.create(newParameters, (PsiClassType)subst.substitute(capture.second)));
|
||||
}
|
||||
myInferenceSessionContainer = inferenceSessionContainer;
|
||||
}
|
||||
|
||||
public InferenceSessionContainer getInferenceSessionContainer() {
|
||||
InferenceSessionContainer getInferenceSessionContainer() {
|
||||
return myInferenceSessionContainer;
|
||||
}
|
||||
|
||||
public Set<InferenceVariable> getInferenceVariables() {
|
||||
Set<InferenceVariable> getInferenceVariables() {
|
||||
return myInferenceVariables;
|
||||
}
|
||||
|
||||
@@ -80,11 +82,11 @@ public class InitialInferenceState {
|
||||
return myContext;
|
||||
}
|
||||
|
||||
public PsiSubstitutor getInferenceSubstitutor() {
|
||||
PsiSubstitutor getInferenceSubstitutor() {
|
||||
return myInferenceSubstitutor;
|
||||
}
|
||||
|
||||
public PsiSubstitutor getSiteSubstitutor() {
|
||||
PsiSubstitutor getSiteSubstitutor() {
|
||||
return mySiteSubstitutor;
|
||||
}
|
||||
|
||||
|
||||
+11
-2
@@ -56,8 +56,14 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
|
||||
return false;
|
||||
}
|
||||
|
||||
if (exprType instanceof PsiClassType && ((PsiClassType)exprType).resolve() == null) {
|
||||
return true;
|
||||
if (exprType instanceof PsiClassType) {
|
||||
if (((PsiClassType)exprType).resolve() == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (((PsiClassType)exprType).isRaw()) {
|
||||
session.setErased();
|
||||
}
|
||||
}
|
||||
|
||||
if (exprType != null && exprType != PsiType.NULL) {
|
||||
@@ -94,6 +100,9 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
|
||||
if (callSession != session) {
|
||||
session.getInferenceSessionContainer().registerNestedSession(callSession);
|
||||
session.propagateVariables(callSession.getInferenceVariables());
|
||||
if (callSession.isErased()) {
|
||||
session.setErased();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
+12
-3
@@ -4,9 +4,11 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.InferenceVariable;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.Function;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -76,9 +78,16 @@ public class LambdaExpressionCompatibilityConstraint implements ConstraintFormul
|
||||
session.registerIncompatibleErrorMessage("Incompatible types: expected not void but the lambda body is a block that is not value-compatible");
|
||||
return false;
|
||||
}
|
||||
InferenceSession callsession = session.getInferenceSessionContainer().findNestedCallSession(myExpression, session);
|
||||
returnType = callsession.substituteWithInferenceVariables(substitutor.substitute(returnType));
|
||||
if (!callsession.isProperType(returnType)) {
|
||||
final PsiSubstitutor nestedSubstitutor = session.getInferenceSessionContainer().findNestedSubstitutor(myExpression, session.getInferenceSubstitution());
|
||||
returnType = nestedSubstitutor.substitute(substitutor.substitute(returnType));
|
||||
boolean isProperType = InferenceSession.collectDependencies(returnType, null, new Function<PsiClassType, InferenceVariable>() {
|
||||
@Override
|
||||
public InferenceVariable fun(PsiClassType type) {
|
||||
final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(type);
|
||||
return psiClass instanceof InferenceVariable && nestedSubstitutor.getSubstitutionMap().containsValue(type) ? (InferenceVariable)psiClass : null;
|
||||
}
|
||||
});
|
||||
if (!isProperType) {
|
||||
for (PsiExpression returnExpression : returnExpressions) {
|
||||
constraints.add(new ExpressionCompatibilityConstraint(returnExpression, returnType));
|
||||
}
|
||||
|
||||
+1
@@ -32,6 +32,7 @@ public class StrictSubtypingConstraint implements ConstraintFormula {
|
||||
private PsiType myS;
|
||||
private PsiType myT;
|
||||
|
||||
//t < s
|
||||
public StrictSubtypingConstraint(PsiType t, PsiType s) {
|
||||
myT = t;
|
||||
myS = s;
|
||||
|
||||
-6
@@ -675,12 +675,6 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
|
||||
}
|
||||
}
|
||||
|
||||
final boolean raw1 = PsiUtil.isRawSubstitutor(method1, classSubstitutor1);
|
||||
final boolean raw2 = PsiUtil.isRawSubstitutor(method2, classSubstitutor2);
|
||||
if (raw1 ^ raw2) {
|
||||
return raw1 ? Specifics.SECOND : Specifics.FIRST;
|
||||
}
|
||||
|
||||
final boolean varargs1 = info1.isVarargs();
|
||||
final boolean varargs2 = info2.isVarargs();
|
||||
if (varargs1 ^ varargs2) {
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class Main {
|
||||
static List<? extends Child> foo() {
|
||||
return get ();
|
||||
}
|
||||
|
||||
static <T extends Base> List<? extends T> get() {
|
||||
return null;
|
||||
}
|
||||
|
||||
static class Base {}
|
||||
static class Child extends Base {}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
|
||||
interface Item<K, V>{}
|
||||
interface Holder<A, B> {
|
||||
boolean apply(Item<? extends A, ? extends B> i);
|
||||
}
|
||||
class C {
|
||||
void f(Holder<?,?> h) {
|
||||
h.apply(create());
|
||||
}
|
||||
|
||||
private <L, M> Item<L,M> create() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import java.util.List;
|
||||
|
||||
class Temp<K> {
|
||||
|
||||
public static List<String> foo() {
|
||||
return parallelizePairs(asList(new Tuple())).partitionBy();
|
||||
}
|
||||
|
||||
public static <T> List<T> asList(T a) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <K> Temp<K> parallelizePairs(List<Tuple<K>> list) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<K> partitionBy() { return null; }
|
||||
}
|
||||
|
||||
class Tuple<A> {
|
||||
public Tuple() {}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import java.util.concurrent.Callable;
|
||||
class Test {
|
||||
|
||||
public void test() {
|
||||
Foo<String> f = new Foo<>(() -> "this doesn't compile");
|
||||
}
|
||||
|
||||
public class Foo<T> {
|
||||
public Foo(Callable<T> supplier) {
|
||||
}
|
||||
|
||||
public Foo(T value) {
|
||||
}
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class LazyVal<T> {
|
||||
public LazyVal(Supplier<T> supplier) {}
|
||||
public LazyVal(T value) {}
|
||||
}
|
||||
|
||||
class Sample {
|
||||
|
||||
String getString() {
|
||||
return "";
|
||||
}
|
||||
|
||||
public void usage() {
|
||||
new LazyVal<>(() -> new Sample().getString());
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
class Test {
|
||||
{
|
||||
Set<Class<? extends Throwable>> exceptions = null;
|
||||
transform(exceptions, x -> x.getSimpleName());
|
||||
}
|
||||
|
||||
public static <F, T> Collection<T> transform(Collection<F> fromCollection, Function<? super F, T> function) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
abstract class Test {
|
||||
|
||||
public void foo(List list) {
|
||||
set<error descr="Ambiguous method call: both 'Test.set(Set<List>, List)' and 'Test.set(Set, List)' match">(get(), list)</error>;
|
||||
}
|
||||
|
||||
abstract <Y> Set<Y> get();
|
||||
|
||||
abstract <Y, X extends Y> void set(Set<Y> set, X x);
|
||||
abstract <Y> void set(Set<Y> set, List<? extends Y> l);
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Add 'String' as 2nd parameter to method 'get'" "true"
|
||||
import java.util.List;
|
||||
class Test<T> {
|
||||
|
||||
public LazyVal(final List<T> ts) {
|
||||
get(ts, "");
|
||||
}
|
||||
public static <T1> void get(List<T1> l, String s) {}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Add 'String' as 2nd parameter to method 'get'" "true"
|
||||
import java.util.List;
|
||||
class Test<T> {
|
||||
|
||||
public LazyVal(final List<T> ts) {
|
||||
get(t<caret>s, "");
|
||||
}
|
||||
public static <T1> void get(List<T1> l) {}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
public class Test<A, B extends Number> {
|
||||
public B m(A a){return null;}
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
public class TestSubclass<A, B extends Number> extends Test<A, B> {
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
public class Test<A, B extends Number> {
|
||||
public B m(A a){return null;}
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
interface Int<T> {
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
abstract class Test implements Runnable {
|
||||
<T extends Runnable> void m() {
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
interface Int<T> {
|
||||
}
|
||||
abstract class Super implements Runnable {
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
abstract class Test extends Super {
|
||||
<T extends Super> void m() {
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
|
||||
interface IA {
|
||||
void a();
|
||||
}
|
||||
|
||||
interface IB {
|
||||
void b();
|
||||
}
|
||||
|
||||
interface IC<T extends IA>{
|
||||
T c();
|
||||
}
|
||||
|
||||
class K {
|
||||
void foo(IC<? extends IB> x){
|
||||
IA m = x.c();
|
||||
m.a();
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
|
||||
interface IA {
|
||||
void a();
|
||||
}
|
||||
|
||||
interface IB {
|
||||
void b();
|
||||
}
|
||||
|
||||
interface IC<T extends IA>{
|
||||
T c();
|
||||
}
|
||||
|
||||
class K {
|
||||
void foo(IC<? extends IB> x){
|
||||
<selection>x.c()</selection>.a();
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class Test {
|
||||
{
|
||||
final String ab = "".substring(1)
|
||||
.substring(1);
|
||||
ab // comment
|
||||
.notify()
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class Test {
|
||||
{
|
||||
<selection> "".substring(1)
|
||||
.substring(1) // comment</selection>
|
||||
.notify()
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
class A {
|
||||
public final void foo() {}
|
||||
}
|
||||
class B extends A {}
|
||||
class C {
|
||||
void f(B b) {
|
||||
B v = b;
|
||||
v.foo();
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class A {
|
||||
public final void foo() {}
|
||||
}
|
||||
class B extends A {}
|
||||
class C {
|
||||
void f(B b) {
|
||||
<selection>b</selection>.foo();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import static InlineIssue.ClassToMove.F1;
|
||||
abstract class InlineIssue {
|
||||
public enum ClassToMove { F1 }
|
||||
|
||||
public InlineIssue cre<caret>ate(ClassToMove e) {
|
||||
F1.notify();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
class Desc extends InlineIssue {
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import static Desc.ClassToMove.F1;
|
||||
abstract class InlineIssue {
|
||||
|
||||
}
|
||||
|
||||
class Desc extends InlineIssue {
|
||||
public InlineIssue create(ClassToMove e) {
|
||||
F1.notify();
|
||||
return null;
|
||||
}
|
||||
|
||||
public enum ClassToMove { F1 }
|
||||
}
|
||||
+12
@@ -347,6 +347,18 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testCaptureConstraint() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testPullUncheckedWarningNotionThroughNestedCalls() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIDEA149774() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() throws Exception {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
+13
-1
@@ -248,6 +248,18 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIDEA149224() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIDEA149670() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIDEA149709() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
@@ -269,4 +281,4 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
}
|
||||
return suite;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
+4
@@ -191,6 +191,10 @@ public class OverloadResolutionTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
public void testNoNeedToPreferGenericToRawSubstitution() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(true);
|
||||
}
|
||||
|
||||
@@ -59,6 +59,10 @@ public class ExtractSuperClassTest extends RefactoringTestCase {
|
||||
doTest("Test", "TestSubclass", new RefactoringTestUtil.MemberDescriptor("m", PsiMethod.class));
|
||||
}
|
||||
|
||||
public void testMultipleTypeParameters() throws Exception {
|
||||
doTest("Test", "TestSubclass", new RefactoringTestUtil.MemberDescriptor("m", PsiMethod.class));
|
||||
}
|
||||
|
||||
|
||||
public void testEmptyForeach() throws Exception {
|
||||
doTest("Test", "TestSubclass", new RefactoringTestUtil.MemberDescriptor("m", PsiMethod.class));
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.intellij.refactoring;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.refactoring.inlineSuperClass.InlineSuperClassRefactoringProcessor;
|
||||
@@ -70,6 +69,7 @@ public class InlineSuperClassTest extends MultiFileTestCase {
|
||||
public void testMultipleSubclassesInheritsOneBaseBase() { doTestMultipleSubclasses(); }
|
||||
public void testInlineSuperclassExtendsList() { doTest(); }
|
||||
public void testInterfaceHierarchyWithSubstitution() { doTest(); }
|
||||
public void testTypeParameterBound() { doTest();}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false, false);
|
||||
|
||||
@@ -313,6 +313,10 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase {
|
||||
doTest(new MockIntroduceVariableHandler("ab", true, true, false, "boolean"));
|
||||
}
|
||||
|
||||
public void testSubexpressionWithSpacesInSelectionAndTailingComment() {
|
||||
doTest(new MockIntroduceVariableHandler("ab", true, true, false, CommonClassNames.JAVA_LANG_STRING));
|
||||
}
|
||||
|
||||
public void testDuplicatesAnonymousClassCreationWithSimilarParameters () {
|
||||
doTest(new MockIntroduceVariableHandler("foo1", true, true, false, "Foo"));
|
||||
}
|
||||
@@ -517,6 +521,29 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase {
|
||||
});
|
||||
}
|
||||
|
||||
public void testTypesHierarchyBasedOnCalledMethod() {
|
||||
doTest(new MockIntroduceVariableHandler("v", true, false, false, "B") {
|
||||
@Override
|
||||
public IntroduceVariableSettings getSettings(Project project, Editor editor,
|
||||
PsiExpression expr, PsiExpression[] occurrences,
|
||||
TypeSelectorManagerImpl typeSelectorManager,
|
||||
boolean declareFinalIfAll,
|
||||
boolean anyAssignmentLHS,
|
||||
InputValidator validator,
|
||||
PsiElement anchor, final OccurrencesChooser.ReplaceChoice replaceChoice) {
|
||||
final PsiType[] types = typeSelectorManager.getTypesForAll();
|
||||
assertTrue(types[0].getPresentableText(), types[0].getPresentableText().equals("B"));
|
||||
assertTrue(types[1].getPresentableText(), types[1].getPresentableText().equals("A"));
|
||||
return super.getSettings(project, editor, expr, occurrences, typeSelectorManager, declareFinalIfAll, anyAssignmentLHS,
|
||||
validator, anchor, replaceChoice);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void testChooseIntersectionConjunctBasedOnFollowingCalls() throws Exception {
|
||||
doTest(new MockIntroduceVariableHandler("m", false, false, false, "IA"));
|
||||
}
|
||||
|
||||
private void doTest(IntroduceVariableBase testMe) {
|
||||
String baseName = "/refactoring/introduceVariable/" + getTestName(false);
|
||||
configureByFile(baseName + ".java");
|
||||
|
||||
@@ -63,6 +63,8 @@ public class PushDownTest extends LightRefactoringTestCase {
|
||||
|
||||
public void testInterfaceConstants() { doTest();}
|
||||
|
||||
public void testReferenceForMovedInnerClass() { doTest();}
|
||||
|
||||
public void testInsertOverrideWhenKeepAbstract() throws Exception {
|
||||
doTestImplements(true);
|
||||
}
|
||||
@@ -92,6 +94,13 @@ public class PushDownTest extends LightRefactoringTestCase {
|
||||
membersToMove.add(memberInfo);
|
||||
}
|
||||
|
||||
final PsiClass classByName = currentClass.findInnerClassByName("ClassToMove", false);
|
||||
if (classByName != null) {
|
||||
final MemberInfo memberInfo = new MemberInfo(classByName);
|
||||
memberInfo.setChecked(true);
|
||||
membersToMove.add(memberInfo);
|
||||
}
|
||||
|
||||
final MemberInfo memberInfo = new MemberInfo(psiMember);
|
||||
memberInfo.setChecked(true);
|
||||
membersToMove.add(memberInfo);
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -349,7 +349,7 @@ public class Main {
|
||||
scrollPane.setPreferredSize(new Dimension(Math.min(maxWidth, component.width), Math.min(maxHeight, component.height)));
|
||||
}
|
||||
|
||||
int type = error ? JOptionPane.ERROR_MESSAGE : JOptionPane.INFORMATION_MESSAGE;
|
||||
int type = error ? JOptionPane.ERROR_MESSAGE : JOptionPane.WARNING_MESSAGE;
|
||||
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), scrollPane, title, type);
|
||||
}
|
||||
catch (Throwable t) {
|
||||
|
||||
@@ -12,5 +12,6 @@
|
||||
<orderEntry type="module" module-name="platform-api" />
|
||||
<orderEntry type="module" module-name="platform-impl" />
|
||||
<orderEntry type="module" module-name="vcs-api-core" />
|
||||
<orderEntry type="module" module-name="vcs-api" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -37,9 +37,11 @@ import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -103,23 +105,13 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory {
|
||||
@Override
|
||||
@NotNull
|
||||
public String getContentTitle(@NotNull VirtualFile file) {
|
||||
if (file.isDirectory()) return file.getPath();
|
||||
|
||||
VirtualFile parent = file.getParent();
|
||||
return getContentTitle(file.getName(), file.getPath(), parent != null ? parent.getPath() : null);
|
||||
return getContentTitle(VcsUtil.getFilePath(file));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getTitle(@NotNull VirtualFile file1, @NotNull VirtualFile file2) {
|
||||
if ((file1.isDirectory() || file2.isDirectory()) && file1.getPath().equals(file2.getPath())) return file1.getPath();
|
||||
if (file1.isDirectory() ^ file2.isDirectory()) return getContentTitle(file1) + " vs " + getContentTitle(file2);
|
||||
|
||||
VirtualFile parent1 = file1.getParent();
|
||||
VirtualFile parent2 = file2.getParent();
|
||||
return getRequestTitle(file1.getName(), file1.getPath(), parent1 != null ? parent1.getPath() : null,
|
||||
file2.getName(), file2.getPath(), parent2 != null ? parent2.getPath() : null,
|
||||
" vs ");
|
||||
return getTitle(VcsUtil.getFilePath(file1), VcsUtil.getFilePath(file2), " vs ");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -130,20 +122,29 @@ public class DiffRequestFactoryImpl extends DiffRequestFactory {
|
||||
|
||||
@NotNull
|
||||
public static String getContentTitle(@NotNull FilePath path) {
|
||||
if (path.isDirectory()) return path.getPath();
|
||||
if (path.isDirectory()) return path.getPresentableUrl();
|
||||
FilePath parent = path.getParentPath();
|
||||
return getContentTitle(path.getName(), path.getPath(), parent != null ? parent.getPath() : null);
|
||||
return getContentTitle(path.getName(), path.getPresentableUrl(), parent != null ? parent.getPresentableUrl() : null);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getTitle(@NotNull FilePath path1, @NotNull FilePath path2, @NotNull String separator) {
|
||||
if ((path1.isDirectory() || path2.isDirectory()) && path1.getPath().equals(path2.getPath())) return path1.getPath();
|
||||
if (path1.isDirectory() ^ path2.isDirectory()) return getContentTitle(path1) + " vs " + getContentTitle(path2);
|
||||
if ((path1.isDirectory() || path2.isDirectory()) && path1.getPresentableUrl().equals(path2.getPresentableUrl())) {
|
||||
return path1.getPresentableUrl();
|
||||
}
|
||||
|
||||
String name1 = path1.getName();
|
||||
String name2 = path2.getName();
|
||||
|
||||
if (path1.isDirectory() ^ path2.isDirectory()) {
|
||||
if (path1.isDirectory()) name1 += File.separatorChar;
|
||||
if (path2.isDirectory()) name2 += File.separatorChar;
|
||||
}
|
||||
|
||||
FilePath parent1 = path1.getParentPath();
|
||||
FilePath parent2 = path2.getParentPath();
|
||||
return getRequestTitle(path1.getName(), path1.getPath(), parent1 != null ? parent1.getPath() : null,
|
||||
path2.getName(), path2.getPath(), parent2 != null ? parent2.getPath() : null,
|
||||
return getRequestTitle(name1, path1.getPresentableUrl(), parent1 != null ? parent1.getPresentableUrl() : null,
|
||||
name2, path2.getPresentableUrl(), parent2 != null ? parent2.getPresentableUrl() : null,
|
||||
separator);
|
||||
}
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ public class CompareFilesAction extends BaseShowDiffAction {
|
||||
|
||||
Type type = getType(file);
|
||||
if (type == Type.DIRECTORY || type == Type.ARCHIVE) {
|
||||
descriptor = new FileChooserDescriptor(false, true, true, false, false, false);
|
||||
descriptor = new FileChooserDescriptor(false, true, true, true, true, false);
|
||||
key = LAST_USED_FOLDER_KEY;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -187,6 +187,7 @@ public class DiffUtil {
|
||||
editor.getSettings().setShowIntentionBulb(false);
|
||||
((EditorMarkupModel)editor.getMarkupModel()).setErrorStripeVisible(true);
|
||||
editor.getGutterComponentEx().setShowDefaultGutterPopup(false);
|
||||
editor.getGutterComponentEx().setShowRightFreePaintersArea(false);
|
||||
|
||||
if (enableFolding) {
|
||||
setFoldingModelSupport(editor);
|
||||
|
||||
+1
@@ -37,6 +37,7 @@ class ChangeCompareModeAction extends DumbAwareAction {
|
||||
|
||||
ChangeCompareModeAction(DirDiffTableModel model, DirDiffSettings.CompareMode mode) {
|
||||
super(mode.getPresentableName(model.getSettings()));
|
||||
getTemplatePresentation().setIcon(OFF);
|
||||
myModel = model;
|
||||
myMode = mode;
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@ package com.intellij.execution.console;
|
||||
import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.openapi.util.SimpleModificationTracker;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -30,13 +30,13 @@ import java.util.List;
|
||||
*/
|
||||
class ConsoleHistoryModel extends SimpleModificationTracker {
|
||||
/** @noinspection FieldCanBeLocal*/
|
||||
private final ConsoleHistoryModel myMasterModel; // hard ref
|
||||
private int myIndex;
|
||||
private final Object myLock;
|
||||
private final LinkedList<String> myEntries;
|
||||
private int myIndex;
|
||||
|
||||
ConsoleHistoryModel(ConsoleHistoryModel masterModel) {
|
||||
myMasterModel = masterModel;
|
||||
myEntries = myMasterModel == null ? new LinkedList<String>() : myMasterModel.myEntries;
|
||||
ConsoleHistoryModel(@Nullable ConsoleHistoryModel masterModel) {
|
||||
myEntries = masterModel == null ? new LinkedList<String>() : masterModel.myEntries;
|
||||
myLock = masterModel == null ? this : masterModel.myLock; // hard ref to master model
|
||||
resetIndex();
|
||||
}
|
||||
|
||||
@@ -44,23 +44,27 @@ class ConsoleHistoryModel extends SimpleModificationTracker {
|
||||
return new ConsoleHistoryModel(this);
|
||||
}
|
||||
|
||||
public synchronized void resetEntries(@NotNull List<String> entries) {
|
||||
myEntries.clear();
|
||||
myEntries.addAll(entries.subList(0, Math.min(entries.size(), getMaxHistorySize())));
|
||||
incModificationCount();
|
||||
public void resetEntries(@NotNull List<String> entries) {
|
||||
synchronized (myLock) {
|
||||
myEntries.clear();
|
||||
myEntries.addAll(entries.subList(0, Math.min(entries.size(), getMaxHistorySize())));
|
||||
incModificationCount();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void addToHistory(@Nullable String statement) {
|
||||
public void addToHistory(@Nullable String statement) {
|
||||
if (StringUtil.isEmptyOrSpaces(statement)) return;
|
||||
|
||||
int maxHistorySize = getMaxHistorySize();
|
||||
myEntries.remove(statement);
|
||||
int size = myEntries.size();
|
||||
if (size >= maxHistorySize && size > 0) {
|
||||
myEntries.removeFirst();
|
||||
synchronized (myLock) {
|
||||
int maxHistorySize = getMaxHistorySize();
|
||||
myEntries.remove(statement);
|
||||
int size = myEntries.size();
|
||||
if (size >= maxHistorySize && size > 0) {
|
||||
myEntries.removeFirst();
|
||||
}
|
||||
myEntries.addLast(statement);
|
||||
incModificationCount();
|
||||
}
|
||||
myEntries.addLast(statement);
|
||||
incModificationCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,48 +73,66 @@ class ConsoleHistoryModel extends SimpleModificationTracker {
|
||||
super.incModificationCount();
|
||||
}
|
||||
|
||||
protected synchronized void resetIndex() {
|
||||
myIndex = myEntries.size();
|
||||
protected void resetIndex() {
|
||||
synchronized (myLock) {
|
||||
myIndex = myEntries.size();
|
||||
}
|
||||
}
|
||||
|
||||
public int getMaxHistorySize() {
|
||||
return UISettings.getInstance().CONSOLE_COMMAND_HISTORY_LIMIT;
|
||||
}
|
||||
|
||||
public synchronized void removeFromHistory(String statement) {
|
||||
myEntries.remove(statement);
|
||||
incModificationCount();
|
||||
public void removeFromHistory(String statement) {
|
||||
synchronized (myLock) {
|
||||
myEntries.remove(statement);
|
||||
incModificationCount();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized List<String> getEntries() {
|
||||
return new ArrayList<String>(myEntries);
|
||||
public List<String> getEntries() {
|
||||
synchronized (myLock) {
|
||||
return ContainerUtil.newArrayList(myEntries);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized int getHistorySize() {
|
||||
return myEntries.size();
|
||||
public int getHistorySize() {
|
||||
synchronized (myLock) {
|
||||
return myEntries.size();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public synchronized String getHistoryNext() {
|
||||
if (myIndex >= 0) --myIndex;
|
||||
return getCurrentEntry();
|
||||
public String getHistoryNext() {
|
||||
synchronized (myLock) {
|
||||
if (myIndex >= 0) --myIndex;
|
||||
return getCurrentEntry();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public synchronized String getHistoryPrev() {
|
||||
if (myIndex <= myEntries.size() - 1) ++myIndex;
|
||||
return getCurrentEntry();
|
||||
public String getHistoryPrev() {
|
||||
synchronized (myLock) {
|
||||
if (myIndex <= myEntries.size() - 1) ++myIndex;
|
||||
return getCurrentEntry();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean hasHistory(final boolean next) {
|
||||
return next ? myIndex > 0 : myIndex < myEntries.size() - 1;
|
||||
public boolean hasHistory(final boolean next) {
|
||||
synchronized (myLock) {
|
||||
return next ? myIndex > 0 : myIndex < myEntries.size() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
synchronized String getCurrentEntry() {
|
||||
return myIndex >= 0 && myIndex < myEntries.size() ? myEntries.get(myIndex) : null;
|
||||
String getCurrentEntry() {
|
||||
synchronized (myLock) {
|
||||
return myIndex >= 0 && myIndex < myEntries.size() ? myEntries.get(myIndex) : null;
|
||||
}
|
||||
}
|
||||
|
||||
synchronized int getCurrentIndex() {
|
||||
return myIndex;
|
||||
int getCurrentIndex() {
|
||||
synchronized (myLock) {
|
||||
return myIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1179,7 +1179,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
myTitle.setText(title);
|
||||
myMainPanel.add(createTitle(" " + title), BorderLayout.NORTH);
|
||||
}
|
||||
myMainPanel.add(cmp, BorderLayout.WEST);
|
||||
myMainPanel.add(cmp, BorderLayout.CENTER);
|
||||
if (cmp instanceof Accessible) {
|
||||
myMainPanel.setAccessible((Accessible)cmp);
|
||||
}
|
||||
|
||||
@@ -52,6 +52,21 @@ class SearchEverywherePsiRenderer extends PsiElementListCellRenderer<PsiElement>
|
||||
public SearchEverywherePsiRenderer(JList list) {
|
||||
myList = list;
|
||||
setFocusBorderEnabled(false);
|
||||
setLayout(new BorderLayout() {
|
||||
@Override
|
||||
public void layoutContainer(Container target) {
|
||||
super.layoutContainer(target);
|
||||
final Component right = getLayoutComponent(EAST);
|
||||
final Component left = getLayoutComponent(WEST);
|
||||
|
||||
//IDEA-140824
|
||||
if (right != null && left != null && left.getBounds().x + left.getBounds().width > right.getBounds().x) {
|
||||
final Rectangle bounds = right.getBounds();
|
||||
final int newX = left.getBounds().x + left.getBounds().width;
|
||||
right.setBounds(newX, bounds.y, bounds.width - (newX - bounds.x), bounds.height);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -357,7 +357,7 @@ public class Bookmark implements Navigatable, Comparable<Bookmark> {
|
||||
private static class MyCheckedIcon implements Icon, RetrievableIcon {
|
||||
@Nullable
|
||||
@Override
|
||||
public Icon retrieve() {
|
||||
public Icon retrieveIcon() {
|
||||
return PlatformIcons.CHECK_ICON;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,6 @@ import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
import org.jetbrains.ide.PooledThreadExecutor;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -250,8 +249,8 @@ public class DeferredIconImpl<T> implements DeferredIcon, RetrievableIcon {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Icon retrieve() {
|
||||
return evaluate();
|
||||
public Icon retrieveIcon() {
|
||||
return isDone() ? myDelegateIcon : evaluate();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -378,12 +377,6 @@ public class DeferredIconImpl<T> implements DeferredIcon, RetrievableIcon {
|
||||
equalIcons(myDelegateIcon, ((DeferredIconImpl)icon).myDelegateIcon);
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
@NotNull
|
||||
Icon getDelegateIcon() {
|
||||
return myDelegateIcon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Deferred. Base=" + myDelegateIcon;
|
||||
|
||||
@@ -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.
|
||||
@@ -44,15 +44,17 @@ public class ProgressManagerQueue extends AbstractTaskQueue<Runnable> {
|
||||
protected void runMe() {
|
||||
if (!myIsStarted) return;
|
||||
if (ApplicationManager.getApplication().isDispatchThread()) {
|
||||
if (myQueuePollTask.myProject.isDisposed() || isEmpty()) return;
|
||||
myProgressManager.run(myQueuePollTask);
|
||||
if (!myQueuePollTask.myProject.isDisposed()) {
|
||||
myProgressManager.run(myQueuePollTask);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myQueuePollTask.myProject.isDisposed() || isEmpty()) return;
|
||||
myProgressManager.run(myQueuePollTask);
|
||||
if (!myQueuePollTask.myProject.isDisposed()) {
|
||||
myProgressManager.run(myQueuePollTask);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -745,7 +745,9 @@ public class ThreeComponentsSplitter extends JPanel implements Disposable {
|
||||
case MouseEvent.MOUSE_PRESSED:
|
||||
if (isInside(e.getPoint())) {
|
||||
myWasPressedOnMe = true;
|
||||
myGlassPane.setCursor(getResizeCursor(), myListener);
|
||||
if (myGlassPane != null) {
|
||||
myGlassPane.setCursor(getResizeCursor(), myListener);
|
||||
}
|
||||
e.consume();
|
||||
} else {
|
||||
myWasPressedOnMe = false;
|
||||
@@ -755,7 +757,7 @@ public class ThreeComponentsSplitter extends JPanel implements Disposable {
|
||||
if (myWasPressedOnMe) {
|
||||
e.consume();
|
||||
}
|
||||
if (isInside(e.getPoint())) {
|
||||
if (isInside(e.getPoint()) && myGlassPane != null) {
|
||||
myGlassPane.setCursor(getResizeCursor(), myListener);
|
||||
}
|
||||
myWasPressedOnMe = false;
|
||||
|
||||
@@ -45,5 +45,6 @@
|
||||
<orderEntry type="library" exported="" name="KotlinJavaRuntime" level="project" />
|
||||
<orderEntry type="library" scope="RUNTIME" name="Slf4j" level="project" />
|
||||
<orderEntry type="module" module-name="configuration-store-impl" scope="RUNTIME" />
|
||||
<orderEntry type="library" name="com.twelvemonkeys.imageio:imageio-tiff:3.2.1" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -172,8 +172,11 @@ public class AboutPopup {
|
||||
myLines.add(new AboutBoxLine(""));
|
||||
myLines.add(new AboutBoxLine(""));
|
||||
myLines.add(new AboutBoxLine("Powered by ").keepWithNext());
|
||||
myLines.add(new AboutBoxLine("open-source software", false, thirdParty).keepWithNext());
|
||||
myLines.add(new AboutBoxLine("open-source software", false, thirdParty));
|
||||
}
|
||||
|
||||
myLines.add(new AboutBoxLine(""));
|
||||
myLines.add(new AboutBoxLine(IdeBundle.message("about.box.copy.prompt", SystemInfo.isMac ? "Cmd+C" : "Ctrl+C")));
|
||||
|
||||
addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
|
||||
@@ -36,7 +36,6 @@ import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.startup.StartupActivity;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
@@ -208,11 +207,6 @@ public class StartupManagerImpl extends StartupManagerEx {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// otherwise will be stored - we must not create config files in tests
|
||||
if (!app.isUnitTestMode()) {
|
||||
Registry.get("ide.firstStartup").setValue(false);
|
||||
}
|
||||
}
|
||||
|
||||
public void scheduleInitialVfsRefresh() {
|
||||
@@ -262,10 +256,10 @@ public class StartupManagerImpl extends StartupManagerEx {
|
||||
path = PathUtil.getParentPath(path);
|
||||
}
|
||||
|
||||
boolean actual = FileUtil.isFileSystemCaseSensitive(path);
|
||||
LOG.info(path + " case-sensitivity: " + actual);
|
||||
if (actual != SystemInfo.isFileSystemCaseSensitive) {
|
||||
int prefix = SystemInfo.isFileSystemCaseSensitive ? 1 : 0; // IDE=true -> FS=false -> prefix='in'
|
||||
boolean expected = SystemInfo.isFileSystemCaseSensitive, actual = FileUtil.isFileSystemCaseSensitive(path);
|
||||
LOG.info(path + " case-sensitivity: expected=" + expected + " actual=" + actual);
|
||||
if (actual != expected) {
|
||||
int prefix = expected ? 1 : 0; // IDE=true -> FS=false -> prefix='in'
|
||||
String title = ApplicationBundle.message("fs.case.sensitivity.mismatch.title");
|
||||
String text = ApplicationBundle.message("fs.case.sensitivity.mismatch.message", prefix);
|
||||
Notifications.Bus.notify(
|
||||
|
||||
+1
-1
@@ -493,7 +493,7 @@ public class CustomizableActionsPanel {
|
||||
setText(((QuickList)userObject).getName());
|
||||
icon = AllIcons.Actions.QuickList;
|
||||
}
|
||||
else {
|
||||
else if (userObject != null) {
|
||||
throw new IllegalArgumentException("unknown userObject: " + userObject);
|
||||
}
|
||||
|
||||
|
||||
@@ -143,6 +143,7 @@ public final class SocketLock {
|
||||
myServer = BuiltInServer.start(workerCount, 6942, 50, false, handler);
|
||||
}
|
||||
catch (IllegalStateException e) {
|
||||
Logger.getInstance(SocketLock.class).warn(e);
|
||||
myServer = BuiltInServer.start(new OioEventLoopGroup(1, new BuiltInServer.BuiltInServerThreadFactory()), true, 6942, 50, false, handler);
|
||||
}
|
||||
|
||||
|
||||
+69
-86
@@ -18,12 +18,12 @@ package com.intellij.openapi.application;
|
||||
import com.intellij.ide.plugins.IdeaPluginDescriptorImpl;
|
||||
import com.intellij.ide.plugins.PluginManager;
|
||||
import com.intellij.ide.plugins.PluginManagerCore;
|
||||
import com.intellij.idea.Main;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.ui.AppUIUtil;
|
||||
import com.intellij.util.*;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -38,47 +38,63 @@ import java.util.PropertyResourceBundle;
|
||||
* @author max
|
||||
*/
|
||||
public class ConfigImportHelper {
|
||||
/**
|
||||
* Holds name of the system property that is supposed to hold <code>'true'</code> value when IDE settings have been
|
||||
* imported on the current startup
|
||||
*/
|
||||
@NonNls public static final String CONFIG_IMPORTED_IN_CURRENT_SESSION_KEY = "intellij.config.imported.in.current.session";
|
||||
|
||||
@NonNls private static final String BUILD_NUMBER_FILE = SystemInfo.isMac ? "/Resources/build.txt" : "build.txt";
|
||||
@NonNls private static final String PLUGINS_PATH = "plugins";
|
||||
@NonNls private static final String BIN_FOLDER = "bin";
|
||||
@NonNls private static final String CONFIG_RELATED_PATH = SystemInfo.isMac ? "" : "config/";
|
||||
@NonNls private static final String OPTIONS_XML = "options/options.xml";
|
||||
private static final String FIRST_SESSION_KEY = "intellij.first.ide.session";
|
||||
private static final String CONFIG_IMPORTED_IN_CURRENT_SESSION_KEY = "intellij.config.imported.in.current.session";
|
||||
|
||||
private ConfigImportHelper() {
|
||||
}
|
||||
private static final String BUILD_NUMBER_FILE = SystemInfo.isMac ? "/Resources/build.txt" : "build.txt";
|
||||
private static final String PLUGINS_PATH = "plugins";
|
||||
private static final String BIN_FOLDER = "bin";
|
||||
private static final String CONFIG_RELATED_PATH = SystemInfo.isMac ? "" : "config/";
|
||||
private static final String OPTIONS_XML = "options/options.xml";
|
||||
|
||||
private ConfigImportHelper() { }
|
||||
|
||||
public static void importConfigsTo(@NotNull String newConfigPath) {
|
||||
System.setProperty(FIRST_SESSION_KEY, Boolean.TRUE.toString());
|
||||
|
||||
ConfigImportSettings settings = getConfigImportSettings();
|
||||
|
||||
File newConfigDir = new File(newConfigPath);
|
||||
File oldConfigDir = findOldConfigDir(newConfigDir, settings.getCustomPathsSelector());
|
||||
do {
|
||||
|
||||
try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); }
|
||||
catch (Throwable ignore) { }
|
||||
|
||||
while (true) {
|
||||
ImportOldConfigsPanel dialog = new ImportOldConfigsPanel(oldConfigDir, settings);
|
||||
dialog.setModalityType(Dialog.ModalityType.TOOLKIT_MODAL);
|
||||
AppUIUtil.updateWindowIcon(dialog);
|
||||
dialog.setVisible(true);
|
||||
if (dialog.isImportEnabled()) {
|
||||
File installationHome = dialog.getSelectedFile();
|
||||
oldConfigDir = getOldConfigDir(installationHome, settings);
|
||||
if (!validateOldConfigDir(installationHome, oldConfigDir, settings)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
assert oldConfigDir != null;
|
||||
doImport(newConfigDir, oldConfigDir, settings, installationHome);
|
||||
settings.importFinished(newConfigPath);
|
||||
System.setProperty(CONFIG_IMPORTED_IN_CURRENT_SESSION_KEY, Boolean.TRUE.toString());
|
||||
if (!dialog.isImportEnabled()) {
|
||||
break;
|
||||
}
|
||||
|
||||
File installationHome = dialog.getSelectedFile();
|
||||
oldConfigDir = getOldConfigDir(installationHome, settings);
|
||||
if (!validateOldConfigDir(installationHome, oldConfigDir, settings)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
assert oldConfigDir != null;
|
||||
doImport(newConfigDir, oldConfigDir, settings, installationHome);
|
||||
settings.importFinished(newConfigPath);
|
||||
System.setProperty(CONFIG_IMPORTED_IN_CURRENT_SESSION_KEY, Boolean.TRUE.toString());
|
||||
break;
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} when the IDE is launched for the first time (i.e. there was no config directory).
|
||||
*/
|
||||
public static boolean isFirstSession() {
|
||||
return Boolean.getBoolean(FIRST_SESSION_KEY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} when the IDE is launched for the first time, and configs were imported from another installation.
|
||||
*/
|
||||
public static boolean isConfigImported() {
|
||||
return Boolean.getBoolean(CONFIG_IMPORTED_IN_CURRENT_SESSION_KEY);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -91,10 +107,8 @@ public class ConfigImportHelper {
|
||||
return ReflectionUtil.newInstance(customProviderClass);
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
catch (RuntimeException ignored) {
|
||||
}
|
||||
catch (ClassNotFoundException ignored) { }
|
||||
catch (RuntimeException ignored) { }
|
||||
return new ConfigImportSettings();
|
||||
}
|
||||
|
||||
@@ -141,28 +155,26 @@ public class ConfigImportHelper {
|
||||
copy(oldConfigDir, newConfigDir, settings, installationHome);
|
||||
}
|
||||
catch (IOException e) {
|
||||
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
|
||||
ApplicationBundle.message("error.unable.to.import.settings", e.getMessage()),
|
||||
ApplicationBundle.message("title.settings.import.failed"), JOptionPane.WARNING_MESSAGE);
|
||||
String message = ApplicationBundle.message("error.unable.to.import.settings", e.getMessage());
|
||||
Main.showMessage(ApplicationBundle.message("title.settings.import.failed"), message, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean validateOldConfigDir(@Nullable File installationHome, @Nullable File oldConfigDir, @NotNull ConfigImportSettings settings) {
|
||||
if (oldConfigDir == null) {
|
||||
if (installationHome != null) {
|
||||
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
|
||||
ApplicationBundle.message("error.invalid.installation.home", installationHome.getAbsolutePath(), settings.getProductName(ThreeState.YES)));
|
||||
String message = ApplicationBundle.message("error.invalid.installation.home", installationHome.getAbsolutePath(), settings.getProductName(ThreeState.YES));
|
||||
Main.showMessage(ApplicationBundle.message("title.settings.import.failed"), message, false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!oldConfigDir.exists()) {
|
||||
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
|
||||
ApplicationBundle.message("error.no.settings.path",
|
||||
oldConfigDir.getAbsolutePath()),
|
||||
ApplicationBundle.message("title.settings.import.failed"), JOptionPane.WARNING_MESSAGE);
|
||||
String message = ApplicationBundle.message("error.no.settings.path", oldConfigDir.getAbsolutePath());
|
||||
Main.showMessage(ApplicationBundle.message("title.settings.import.failed"), message, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -224,7 +236,7 @@ public class ConfigImportHelper {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static File getOldConfigDir(@Nullable File oldInstallHome, ConfigImportSettings settings) {
|
||||
private static File getOldConfigDir(@Nullable File oldInstallHome, ConfigImportSettings settings) {
|
||||
if (oldInstallHome == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -240,7 +252,6 @@ public class ConfigImportHelper {
|
||||
int oldBuildNumber = getBuildNumber(oldInstallHome);
|
||||
|
||||
if (oldBuildNumber != -1 && oldBuildNumber <= 600) { // Pandora
|
||||
//noinspection HardCodedStringLiteral
|
||||
return new File(oldInstallHome, "config");
|
||||
}
|
||||
|
||||
@@ -252,11 +263,8 @@ public class ConfigImportHelper {
|
||||
});
|
||||
}
|
||||
|
||||
private static File getSettingsPath(final File installHome,
|
||||
final ConfigImportSettings settings,
|
||||
final String propertyName,
|
||||
final Function<String, String> fromPathSelector) {
|
||||
final File[] launchFileCandidates = getLaunchFilesCandidates(installHome, settings);
|
||||
private static File getSettingsPath(File installHome, ConfigImportSettings settings, String propertyName, Function<String, String> fromPathSelector) {
|
||||
final List<File> launchFileCandidates = getLaunchFilesCandidates(installHome, settings);
|
||||
|
||||
// custom config folder
|
||||
for (File candidate : launchFileCandidates) {
|
||||
@@ -275,10 +283,9 @@ public class ConfigImportHelper {
|
||||
if (candidate.exists()) {
|
||||
final String pathsSelector = getPropertyFromLaxFile(candidate, PathManager.PROPERTY_PATHS_SELECTOR);
|
||||
if (pathsSelector != null) {
|
||||
final String configDir = fromPathSelector.fun(pathsSelector);
|
||||
final File probableConfig = new File(configDir);
|
||||
if (probableConfig.exists()) {
|
||||
return probableConfig;
|
||||
File candidateDir = new File(fromPathSelector.fun(pathsSelector));
|
||||
if (candidateDir.exists()) {
|
||||
return candidateDir;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -287,21 +294,18 @@ public class ConfigImportHelper {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"HardCodedStringLiteral"})
|
||||
private static File[] getLaunchFilesCandidates(@NotNull final File instHome, @NotNull final ConfigImportSettings settings) {
|
||||
private static List<File> getLaunchFilesCandidates(@NotNull File instHome, @NotNull ConfigImportSettings settings) {
|
||||
final File bin = new File(instHome, BIN_FOLDER);
|
||||
final List<File> files = new ArrayList<File>();
|
||||
if (SystemInfo.isMac) {
|
||||
// Info.plist
|
||||
files.add(new File(new File(instHome, "Contents"), "Info.plist"));
|
||||
|
||||
files.add(new File(new File(new File(bin, "idea.app"), "Contents"), "Info.plist"));
|
||||
files.add(new File(new File(new File(instHome, "idea.app"), "Contents"), "Info.plist"));
|
||||
}
|
||||
// idea.properties
|
||||
files.add(new File(bin, PathManager.PROPERTIES_FILE_NAME));
|
||||
|
||||
|
||||
// other binary scripts
|
||||
final String executableName = StringUtil.toLowerCase(settings.getExecutableName());
|
||||
// * defaults:
|
||||
@@ -313,21 +317,17 @@ public class ConfigImportHelper {
|
||||
// for compatibility with some platform-base IDEs with wrong executable names
|
||||
addLaunchExecutableScriptsCandidates(files, "idea", bin);
|
||||
}
|
||||
return files.toArray(new File[files.size()]);
|
||||
return files;
|
||||
}
|
||||
|
||||
private static void addLaunchExecutableScriptsCandidates(final List<File> files,
|
||||
final String executableName,
|
||||
final File binFolder) {
|
||||
private static void addLaunchExecutableScriptsCandidates(List<File> files, String executableName, File binFolder) {
|
||||
files.add(new File(binFolder, executableName + ".lax"));
|
||||
files.add(new File(binFolder, executableName + ".bat"));
|
||||
files.add(new File(binFolder, executableName + ".sh"));
|
||||
}
|
||||
|
||||
@SuppressWarnings({"HardCodedStringLiteral"})
|
||||
@Nullable
|
||||
public static String getPropertyFromLaxFile(@NotNull final File file,
|
||||
@NotNull final String propertyName) {
|
||||
private static String getPropertyFromLaxFile(@NotNull File file, @NotNull String propertyName) {
|
||||
if (file.getName().endsWith(".properties")) {
|
||||
try {
|
||||
PropertyResourceBundle bundle;
|
||||
@@ -360,8 +360,7 @@ public class ConfigImportHelper {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String findProperty(final String propertyName,
|
||||
final String fileContent) {
|
||||
private static String findProperty(String propertyName, String fileContent) {
|
||||
String param = propertyName + "=";
|
||||
int idx = fileContent.indexOf(param);
|
||||
if (idx == -1) {
|
||||
@@ -405,29 +404,14 @@ public class ConfigImportHelper {
|
||||
@Nullable
|
||||
private static String getContent(File file) {
|
||||
try {
|
||||
StringBuilder content = new StringBuilder();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
|
||||
try {
|
||||
do {
|
||||
String line = reader.readLine();
|
||||
if (line == null) break;
|
||||
content.append(line);
|
||||
content.append('\n');
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
finally {
|
||||
reader.close();
|
||||
}
|
||||
|
||||
return content.toString();
|
||||
return FileUtil.loadFile(file);
|
||||
}
|
||||
catch (Exception e) {
|
||||
catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String fixDirName(String dir, boolean replaceUserHome) {
|
||||
private static String fixDirName(String dir, boolean replaceUserHome) {
|
||||
if (StringUtil.startsWithChar(dir, '\"') && StringUtil.endsWithChar(dir, '\"')) {
|
||||
dir = dir.substring(1, dir.length() - 1);
|
||||
}
|
||||
@@ -437,7 +421,7 @@ public class ConfigImportHelper {
|
||||
return dir;
|
||||
}
|
||||
|
||||
public static boolean isInstallationHomeOrConfig(@NotNull final String installationHome, @NotNull final ConfigImportSettings settings) {
|
||||
public static boolean isInstallationHomeOrConfig(@NotNull String installationHome, @NotNull ConfigImportSettings settings) {
|
||||
if (new File(installationHome, OPTIONS_XML).exists()) return true;
|
||||
if (new File(installationHome, CONFIG_RELATED_PATH + OPTIONS_XML).exists()) return true;
|
||||
|
||||
@@ -450,7 +434,6 @@ public class ConfigImportHelper {
|
||||
String[] mainJarNames = settings.getMainJarNames();
|
||||
for (String name : mainJarNames) {
|
||||
String mainJarName = StringUtil.toLowerCase(name) + ".jar";
|
||||
//noinspection HardCodedStringLiteral
|
||||
if (new File(libFolder, mainJarName).exists()) {
|
||||
quickTest = true;
|
||||
break;
|
||||
@@ -458,7 +441,7 @@ public class ConfigImportHelper {
|
||||
}
|
||||
if (!quickTest) return false;
|
||||
|
||||
File[] files = getLaunchFilesCandidates(new File(installationHome), settings);
|
||||
List<File> files = getLaunchFilesCandidates(new File(installationHome), settings);
|
||||
for (File file : files) {
|
||||
if (file.exists()) return true;
|
||||
}
|
||||
@@ -493,4 +476,4 @@ public class ConfigImportHelper {
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
-5
@@ -104,7 +104,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
private final boolean myTestModeFlag;
|
||||
private final boolean myHeadlessMode;
|
||||
private final boolean myCommandLineMode;
|
||||
private final boolean myIsRunningFromSources;
|
||||
private static volatile Boolean ourIsRunningFromSources;
|
||||
|
||||
private final boolean myIsInternal;
|
||||
private final String myName;
|
||||
@@ -198,8 +198,6 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
myHeadlessMode = isHeadless;
|
||||
myCommandLineMode = isCommandLine;
|
||||
|
||||
myIsRunningFromSources = new File(PathManager.getHomePath(), ".idea").isDirectory();
|
||||
|
||||
myDoNotSave = isUnitTestMode || isHeadless;
|
||||
|
||||
if (myTestModeFlag) {
|
||||
@@ -358,8 +356,11 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
return myCommandLineMode;
|
||||
}
|
||||
|
||||
public boolean isRunningFromSources() {
|
||||
return myIsRunningFromSources;
|
||||
public static boolean isRunningFromSources() {
|
||||
if (ourIsRunningFromSources == null) {
|
||||
ourIsRunningFromSources = new File(PathManager.getHomePath(), ".idea").isDirectory();
|
||||
}
|
||||
return ourIsRunningFromSources;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -72,4 +72,6 @@ public abstract class EditorGutterComponentEx extends JComponent implements Edit
|
||||
public abstract void setGutterPopupGroup(@Nullable ActionGroup group);
|
||||
|
||||
public abstract void setPaintBackground(boolean value);
|
||||
|
||||
public abstract void setShowRightFreePaintersArea(boolean value);
|
||||
}
|
||||
|
||||
+3
-2
@@ -215,8 +215,9 @@ public class ComplementaryFontsRegistry {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static FontInfo doGetFontAbleToDisplay(int codePoint, int size, @JdkConstants.FontStyle int style, @NotNull String defaultFontFamily) {
|
||||
private static FontInfo doGetFontAbleToDisplay(int codePoint, int size, @JdkConstants.FontStyle int originalStyle, @NotNull String defaultFontFamily) {
|
||||
synchronized (lock) {
|
||||
@JdkConstants.FontStyle int style = originalStyle;
|
||||
if (Patches.JDK_MAC_FONT_STYLE_DETECTION_WORKAROUND && style > 0 && style < 4) {
|
||||
Pair<String, Integer>[] replacement = ourStyledFontMap.get(defaultFontFamily);
|
||||
if (replacement != null) {
|
||||
@@ -242,7 +243,7 @@ public class ComplementaryFontsRegistry {
|
||||
|
||||
FontInfo defaultFont = ourUsedFonts.get(ourSharedKeyInstance);
|
||||
if (defaultFont == null) {
|
||||
defaultFont = new FontInfo(defaultFontFamily, size, style);
|
||||
defaultFont = new FontInfo(defaultFontFamily, size, style, originalStyle);
|
||||
ourUsedFonts.put(ourSharedKeyInstance, defaultFont);
|
||||
ourSharedKeyInstance = new FontKey("", 0, 0);
|
||||
}
|
||||
|
||||
+29
-8
@@ -103,7 +103,7 @@ import java.util.List;
|
||||
* <ul>
|
||||
* <li>Left free painters</li>
|
||||
* <li>Icons</li>
|
||||
* <li>GAP_BETWEEN_AREAS</li>
|
||||
* <li>Debugger additional area</li>
|
||||
* <li>Free painters</li>
|
||||
* </ul>
|
||||
* </li>
|
||||
@@ -146,6 +146,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
private TIntObjectHashMap<Color> myTextFgColors = new TIntObjectHashMap<Color>();
|
||||
private boolean myPaintBackground = true;
|
||||
private boolean myLeftFreePaintersAreaShown;
|
||||
private boolean myRightFreePaintersAreaShown = true;
|
||||
private int myLastNonDumbModeIconAreaWidth = 0;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -884,8 +885,8 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
((LineMarkerRendererEx)renderer).getPosition() == LineMarkerRendererEx.Position.LEFT;
|
||||
|
||||
int height = endY - startY;
|
||||
int w = leftPosition ? FREE_PAINTERS_LEFT_AREA_WIDTH : FREE_PAINTERS_RIGHT_AREA_WIDTH;
|
||||
int x = leftPosition ? getLineMarkerAreaOffset() : getLineMarkerFreePaintersAreaOffset() - 1;
|
||||
int w = leftPosition ? getLeftFreePaintersAreaWidth() : getRightFreePaintersAreaWidth();
|
||||
int x = leftPosition ? getLeftFreePaintersAreaOffset() : getLineMarkerFreePaintersAreaOffset() - 1;
|
||||
return new Rectangle(x, startY, w, height);
|
||||
}
|
||||
|
||||
@@ -1184,9 +1185,8 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
}
|
||||
|
||||
public int getLineMarkerAreaWidth() {
|
||||
return isLineMarkersShown() ? ((myLeftFreePaintersAreaShown ? FREE_PAINTERS_LEFT_AREA_WIDTH : 0) +
|
||||
myIconsAreaWidth + GAP_BETWEEN_AREAS + FREE_PAINTERS_RIGHT_AREA_WIDTH) :
|
||||
0;
|
||||
return isLineMarkersShown() ? getLeftFreePaintersAreaWidth() + myIconsAreaWidth +
|
||||
getDebuggerAdditionalAreaWidth() + getRightFreePaintersAreaWidth() : 0;
|
||||
}
|
||||
|
||||
public void setLineNumberAreaWidthFunction(@NotNull TIntFunction calculator) {
|
||||
@@ -1267,12 +1267,24 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
|
||||
@Override
|
||||
public int getIconAreaOffset() {
|
||||
return getLineMarkerAreaOffset() + (myLeftFreePaintersAreaShown ? FREE_PAINTERS_LEFT_AREA_WIDTH : 0);
|
||||
return getLineMarkerAreaOffset() + getLeftFreePaintersAreaWidth();
|
||||
}
|
||||
|
||||
public int getLeftFreePaintersAreaOffset() {
|
||||
return getLineMarkerAreaOffset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLineMarkerFreePaintersAreaOffset() {
|
||||
return getIconAreaOffset() + myIconsAreaWidth + GAP_BETWEEN_AREAS;
|
||||
return getIconAreaOffset() + myIconsAreaWidth + getDebuggerAdditionalAreaWidth();
|
||||
}
|
||||
|
||||
public int getLeftFreePaintersAreaWidth() {
|
||||
return myLeftFreePaintersAreaShown ? FREE_PAINTERS_LEFT_AREA_WIDTH : 0;
|
||||
}
|
||||
|
||||
public int getRightFreePaintersAreaWidth() {
|
||||
return myRightFreePaintersAreaShown ? FREE_PAINTERS_RIGHT_AREA_WIDTH : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1280,6 +1292,10 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
return myIconsAreaWidth;
|
||||
}
|
||||
|
||||
public int getDebuggerAdditionalAreaWidth() {
|
||||
return isRealEditor() ? GAP_BETWEEN_AREAS : 0;
|
||||
}
|
||||
|
||||
private boolean isMirrored() {
|
||||
return myEditor.getVerticalScrollbarOrientation() != EditorEx.VERTICAL_SCROLLBAR_RIGHT;
|
||||
}
|
||||
@@ -1658,6 +1674,11 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse
|
||||
myPaintBackground = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setShowRightFreePaintersArea(boolean value) {
|
||||
myRightFreePaintersAreaShown = value;
|
||||
}
|
||||
|
||||
private void invokePopup(MouseEvent e) {
|
||||
final ActionManager actionManager = ActionManager.getInstance();
|
||||
if (myEditor.getMouseEventArea(e) == EditorMouseEventArea.ANNOTATIONS_AREA) {
|
||||
|
||||
@@ -15,14 +15,19 @@
|
||||
*/
|
||||
package com.intellij.openapi.editor.impl;
|
||||
|
||||
import com.intellij.Patches;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.ex.util.EditorUIUtil;
|
||||
import com.intellij.openapi.editor.impl.view.FontLayoutService;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import org.intellij.lang.annotations.JdkConstants;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.font.FontRenderContext;
|
||||
@@ -31,15 +36,15 @@ import java.awt.font.TextAttribute;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Locale;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class FontInfo {
|
||||
private static final Logger LOG = Logger.getInstance(FontInfo.class);
|
||||
|
||||
private static final boolean USE_ALTERNATIVE_CAN_DISPLAY_PROCEDURE = SystemInfo.isAppleJvm && Registry.is("ide.mac.fix.font.fallback");
|
||||
private static final FontRenderContext DUMMY_CONTEXT = new FontRenderContext(null, false, false);
|
||||
private static final boolean ENABLE_OPTIONAL_LIGATURES = Registry.is("editor.enable.optional.ligatures");
|
||||
@@ -55,50 +60,87 @@ public class FontInfo {
|
||||
private boolean myCheckedForProblemGlyphs;
|
||||
|
||||
public FontInfo(final String familyName, final int size, @JdkConstants.FontStyle int style) {
|
||||
this(familyName, size, style, style);
|
||||
}
|
||||
|
||||
FontInfo(final String familyName, final int size, @JdkConstants.FontStyle int style, @JdkConstants.FontStyle int realStyle) {
|
||||
mySize = size;
|
||||
myStyle = style;
|
||||
Font font = new Font(familyName, style, size);
|
||||
myFont = ENABLE_OPTIONAL_LIGATURES ? getFontWithLigaturesEnabled(font) : font;
|
||||
myFont = ENABLE_OPTIONAL_LIGATURES ? getFontWithLigaturesEnabled(font, realStyle) : font;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Font getFontWithLigaturesEnabled(Font font) {
|
||||
if (SystemInfo.isMac) {
|
||||
private static Font getFontWithLigaturesEnabled(Font font, @JdkConstants.FontStyle int fontStyle) {
|
||||
if (Patches.JDK_BUG_ID_7162125) {
|
||||
// Ligatures don't work on Mac for fonts loaded natively, so we need to locate and load font manually
|
||||
File fontFile = findFileForFont(font, true);
|
||||
if (fontFile == null && font.getStyle() != Font.PLAIN) fontFile = findFileForFont(font.deriveFont(Font.PLAIN), true);
|
||||
if (fontFile == null) fontFile = findFileForFont(font, false);
|
||||
if (fontFile == null) return font;
|
||||
String familyName = font.getFamily();
|
||||
File fontFile = findFileForFont(familyName, fontStyle);
|
||||
if (fontFile == null) {
|
||||
LOG.info(font + "(style=" + fontStyle + ") not located");
|
||||
return font;
|
||||
}
|
||||
LOG.info(font + "(style=" + fontStyle + ") located at " + fontFile);
|
||||
try {
|
||||
font = Font.createFont(Font.TRUETYPE_FONT, fontFile).deriveFont(font.getStyle(), font.getSize());
|
||||
font = Font.createFont(Font.TRUETYPE_FONT, fontFile).deriveFont(fontStyle, font.getSize());
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.warn("Couldn't load font", e);
|
||||
return font;
|
||||
}
|
||||
}
|
||||
return font.deriveFont(Collections.singletonMap(TextAttribute.LIGATURES, TextAttribute.LIGATURES_ON));
|
||||
}
|
||||
|
||||
private static File findFileForFont(Font font, final boolean matchStyle) {
|
||||
final String normalizedFamilyName = font.getFamily().toLowerCase(Locale.getDefault()).replace(" ", "");
|
||||
final int fontStyle = font.getStyle();
|
||||
File[] files = new File(System.getProperty("user.home"), "Library/Fonts").listFiles(new FilenameFilter() {
|
||||
private static final Comparator<File> BY_NAME = new Comparator<File>() {
|
||||
@Override
|
||||
public int compare(File file1, File file2) {
|
||||
return file1.getName().compareTo(file2.getName());
|
||||
}
|
||||
};
|
||||
|
||||
@Nullable
|
||||
private static File findFileForFont(@NotNull String familyName, int style) {
|
||||
File fontFile = doFindFileForFont(familyName, style);
|
||||
if (fontFile == null && style != Font.PLAIN) fontFile = doFindFileForFont(familyName, Font.PLAIN);
|
||||
if (fontFile == null) fontFile = doFindFileForFont(familyName, -1);
|
||||
return fontFile;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static File doFindFileForFont(@NotNull String familyName, final int style) {
|
||||
final String normalizedFamilyName = familyName.toLowerCase(Locale.getDefault()).replace(" ", "");
|
||||
FilenameFilter filter = new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File file, String name) {
|
||||
String normalizedName = name.toLowerCase(Locale.getDefault());
|
||||
return normalizedName.startsWith(normalizedFamilyName) &&
|
||||
(normalizedName.endsWith(".otf") || normalizedName.endsWith(".ttf")) &&
|
||||
(!matchStyle || fontStyle == ComplementaryFontsRegistry.getFontStyle(name));
|
||||
(style == -1 || style == ComplementaryFontsRegistry.getFontStyle(name));
|
||||
}
|
||||
});
|
||||
if (files == null || files.length == 0) return null;
|
||||
// to make sure results are predictable we return first file in alphabetical order
|
||||
return Collections.min(Arrays.asList(files), new Comparator<File>() {
|
||||
@Override
|
||||
public int compare(File file1, File file2) {
|
||||
return file1.getName().compareTo(file2.getName());
|
||||
}
|
||||
});
|
||||
};
|
||||
List<File> files = new ArrayList<File>();
|
||||
|
||||
File[] userFiles = new File(System.getProperty("user.home"), "Library/Fonts").listFiles(filter);
|
||||
if (userFiles != null) files.addAll(Arrays.asList(userFiles));
|
||||
|
||||
File[] localFiles = new File("/Library/Fonts").listFiles(filter);
|
||||
if (localFiles != null) files.addAll(Arrays.asList(localFiles));
|
||||
|
||||
if (files.isEmpty()) return null;
|
||||
|
||||
if (style == Font.PLAIN) {
|
||||
// prefer font containing 'regular' in its name
|
||||
List<File> regulars = ContainerUtil.filter(files, new Condition<File>() {
|
||||
@Override
|
||||
public boolean value(File file) {
|
||||
return file.getName().toLowerCase(Locale.getDefault()).contains("regular");
|
||||
}
|
||||
});
|
||||
if (!regulars.isEmpty()) return Collections.min(regulars, BY_NAME);
|
||||
}
|
||||
|
||||
return Collections.min(files, BY_NAME);
|
||||
}
|
||||
|
||||
private void parseProblemGlyphs() {
|
||||
|
||||
@@ -453,6 +453,7 @@ public class ActionsTreeUtil {
|
||||
node.add(childNode);
|
||||
}
|
||||
else {
|
||||
LOG.assertTrue(child != null);
|
||||
node.add(new DefaultMutableTreeNode(child));
|
||||
}
|
||||
}
|
||||
|
||||
+6
-4
@@ -77,12 +77,14 @@ public class UpdateCheckerComponent implements ApplicationComponent {
|
||||
if (eap && current != ChannelStatus.EAP && UpdateStrategyCustomization.getInstance().forceEapUpdateChannelForEapBuilds()) {
|
||||
mySettings.setSelectedChannelStatus(ChannelStatus.EAP);
|
||||
LOG.info("channel forced to 'eap'");
|
||||
String title = IdeBundle.message("update.notifications.title");
|
||||
String message = IdeBundle.message("update.channel.enforced", ChannelStatus.EAP);
|
||||
notify(app, UpdateChecker.NOTIFICATIONS.createNotification(title, message, NotificationType.INFORMATION, null));
|
||||
if (!ConfigImportHelper.isFirstSession()) {
|
||||
String title = IdeBundle.message("update.notifications.title");
|
||||
String message = IdeBundle.message("update.channel.enforced", ChannelStatus.EAP);
|
||||
notify(app, UpdateChecker.NOTIFICATIONS.createNotification(title, message, NotificationType.INFORMATION, null));
|
||||
}
|
||||
}
|
||||
|
||||
if (!eap && current == ChannelStatus.EAP && Boolean.getBoolean(ConfigImportHelper.CONFIG_IMPORTED_IN_CURRENT_SESSION_KEY)) {
|
||||
if (!eap && current == ChannelStatus.EAP && ConfigImportHelper.isConfigImported()) {
|
||||
mySettings.setSelectedChannelStatus(ChannelStatus.RELEASE);
|
||||
LOG.info("channel set to 'release'");
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user