diff --git a/.idea/modules.xml b/.idea/modules.xml
index 8baef1d3adc6..a20d716756d7 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -26,7 +26,6 @@
-
diff --git a/build/asm/4_textifier_transient_method.patch b/build/asm/4_textifier_transient_method.patch
deleted file mode 100644
index f02b3d8c92e2..000000000000
--- a/build/asm/4_textifier_transient_method.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-Index: org/objectweb/asm/util/Textifier.java
-===================================================================
---- org/objectweb/asm/util/Textifier.java
-+++ org/objectweb/asm/util/Textifier.java
-@@ -425,7 +425,7 @@
- }
-
- buf.append(tab);
-- appendAccess(access & ~Opcodes.ACC_VOLATILE);
-+ appendAccess(access & ~(Opcodes.ACC_VOLATILE|Opcodes.ACC_TRANSIENT)); //[JB: IDEA-166121]
- if ((access & Opcodes.ACC_NATIVE) != 0) {
- buf.append("native ");
- }
diff --git a/build/asm/repackage.xml b/build/asm/repackage.xml
index 0abbb9199442..b2ffa0cf52e4 100644
--- a/build/asm/repackage.xml
+++ b/build/asm/repackage.xml
@@ -15,7 +15,7 @@
-->
-
+
@@ -42,7 +42,6 @@
-
diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/PackagingElementPath.java b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/PackagingElementPath.java
index 689a5a088249..28b55b12e55c 100644
--- a/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/PackagingElementPath.java
+++ b/java/compiler/impl/src/com/intellij/packaging/impl/artifacts/PackagingElementPath.java
@@ -15,7 +15,6 @@
*/
package com.intellij.packaging.impl.artifacts;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.elements.*;
import com.intellij.packaging.impl.elements.ArtifactPackagingElement;
@@ -25,6 +24,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
+import java.util.stream.Collectors;
/**
* @author nik
@@ -60,7 +60,8 @@ public class PackagingElementPath {
@NotNull
public String getPathStringFrom(String separator, @Nullable CompositePackagingElement> ancestor) {
final List> parents = getParentsFrom(ancestor);
- return StringUtil.join(ContainerUtil.reverse(parents), RenameablePackagingElement::getName, separator);
+ // StringUtil.join ignores empty strings whereas this monstrosity doesn't
+ return ContainerUtil.reverse(parents).stream().map(RenameablePackagingElement::getName).collect(Collectors.joining("/"));
}
public List> getParents() {
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java
index d2af8760cf9f..a92fc8f3add7 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/JavaValue.java
@@ -157,14 +157,12 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
XValuePresentation presentation = new JavaValuePresentation(
value, myValueDescriptor.getIdLabel(), exception != null ? exception.getMessage() : null, myValueDescriptor);
- if (myValueDescriptor.getLastRenderer() instanceof FullValueEvaluatorProvider) {
- XFullValueEvaluator evaluator = ((FullValueEvaluatorProvider)myValueDescriptor.getLastRenderer())
- .getFullValueEvaluator(myEvaluationContext, myValueDescriptor);
- if (evaluator != null) {
- node.setFullValueEvaluator(evaluator);
- }
+ Renderer lastRenderer = myValueDescriptor.getLastRenderer();
+ boolean fullEvaluatorSet = setFullValueEvaluator(lastRenderer);
+ if (!fullEvaluatorSet && lastRenderer instanceof CompoundNodeRenderer) {
+ fullEvaluatorSet = setFullValueEvaluator(((CompoundNodeRenderer)lastRenderer).getLabelRenderer());
}
- else if (value.length() > XValueNode.MAX_VALUE_LENGTH) {
+ if (!fullEvaluatorSet && value.length() > XValueNode.MAX_VALUE_LENGTH) {
node.setFullValueEvaluator(new JavaFullValueEvaluator(myEvaluationContext) {
@Override
public void evaluate(@NotNull final XFullValueEvaluationCallback callback) {
@@ -180,6 +178,17 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
}
node.setPresentation(nodeIcon, presentation, myValueDescriptor.isExpandable());
}
+
+ private boolean setFullValueEvaluator(Renderer renderer) {
+ if (renderer instanceof FullValueEvaluatorProvider) {
+ XFullValueEvaluator evaluator = ((FullValueEvaluatorProvider)renderer).getFullValueEvaluator(myEvaluationContext, myValueDescriptor);
+ if (evaluator != null) {
+ node.setFullValueEvaluator(evaluator);
+ return true;
+ }
+ }
+ return false;
+ }
});
}
});
@@ -302,13 +311,20 @@ public class JavaValue extends XNamedValue implements NodeDescriptorProvider, XV
String value = truncateToMaxLength(myValue);
Renderer lastRenderer = myValueDescriptor.getLastRenderer();
+ if (lastRenderer instanceof OnDemandRenderer) {
+ OnDemandRenderer onDemandRenderer = (OnDemandRenderer)lastRenderer;
+ if (OnDemandRenderer.isCalculated(myValueDescriptor)) {
+ lastRenderer = onDemandRenderer.getRenderer();
+ }
+ else {
+ return;
+ }
+ }
+
if (lastRenderer instanceof CompoundTypeRenderer) {
lastRenderer = ((CompoundTypeRenderer)lastRenderer).getLabelRenderer();
}
if (lastRenderer instanceof ToStringRenderer) {
- if (lastRenderer instanceof LazyToStringRenderer && !((LazyToStringRenderer)lastRenderer).isCalculated(myValueDescriptor)) {
- return;
- }
value = StringUtil.wrapWithDoubleQuote(value);
}
renderer.renderValue(value);
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java
index f8b7afa03a57..d36f8718ef09 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 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.
@@ -59,6 +59,7 @@ class CompoundRendererConfigurable extends JPanel {
private final JRadioButton myRbDefaultLabel;
private final JRadioButton myRbExpressionLabel;
private final JBCheckBox myShowTypeCheckBox;
+ private final JBCheckBox myOnDemandCheckBox;
private final JRadioButton myRbDefaultChildrenRenderer;
private final JRadioButton myRbExpressionChildrenRenderer;
private final JRadioButton myRbListChildrenRenderer;
@@ -88,6 +89,7 @@ class CompoundRendererConfigurable extends JPanel {
labelButtonsGroup.add(myRbExpressionLabel);
myShowTypeCheckBox = new JBCheckBox(DebuggerBundle.message("label.compound.renderer.configurable.show.type"));
+ myOnDemandCheckBox = new JBCheckBox(DebuggerBundle.message("label.compound.renderer.configurable.ondemand"));
myRbDefaultChildrenRenderer = new JRadioButton(DebuggerBundle.message("label.compound.renderer.configurable.use.default.renderer"));
myRbExpressionChildrenRenderer = new JRadioButton(DebuggerBundle.message("label.compound.renderer.configurable.use.expression"));
@@ -156,6 +158,8 @@ class CompoundRendererConfigurable extends JPanel {
JBUI.insetsLeft(10), 0, 0));
panel.add(myLabelEditor.getComponent(), new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST,
GridBagConstraints.HORIZONTAL, JBUI.insetsLeft(30), 0, 0));
+ panel.add(myOnDemandCheckBox, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST,
+ GridBagConstraints.HORIZONTAL, JBUI.insetsLeft(30), 0, 0));
panel.add(new JLabel(DebuggerBundle.message("label.compound.renderer.configurable.when.expanding")),
new GridBagConstraints(0, GridBagConstraints.RELATIVE, 1, 1, 1.0, 0.0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
@@ -218,7 +222,9 @@ class CompoundRendererConfigurable extends JPanel {
}
private void updateEnabledState() {
- myLabelEditor.setEnabled(myRbExpressionLabel.isSelected());
+ boolean isLabelRenderer = myRbExpressionLabel.isSelected();
+ myLabelEditor.setEnabled(isLabelRenderer);
+ myOnDemandCheckBox.setEnabled(isLabelRenderer);
final boolean isChildrenExpression = myRbExpressionChildrenRenderer.isSelected();
myChildrenExpandedEditor.setEnabled(isChildrenExpression);
@@ -321,6 +327,7 @@ class CompoundRendererConfigurable extends JPanel {
if (myRbExpressionLabel.isSelected()) {
labelRenderer = new LabelRenderer();
labelRenderer.setLabelExpression(TextWithImportsImpl.fromXExpression(myLabelEditor.getExpression()));
+ labelRenderer.setOnDemand(myOnDemandCheckBox.isSelected());
}
renderer.setLabelRenderer(labelRenderer);
// children
@@ -362,7 +369,9 @@ class CompoundRendererConfigurable extends JPanel {
}
else {
myRbExpressionLabel.setSelected(true);
- myLabelEditor.setExpression(TextWithImportsImpl.toXExpression(((LabelRenderer)labelRenderer).getLabelExpression()));
+ LabelRenderer lr = (LabelRenderer)labelRenderer;
+ myLabelEditor.setExpression(TextWithImportsImpl.toXExpression(lr.getLabelExpression()));
+ myOnDemandCheckBox.setSelected(lr.isOnDemand());
}
getTableModel().clear();
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorImpl.java
index c05eff6c8fe2..3182f211bbb6 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/NodeDescriptorImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 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.
@@ -22,6 +22,7 @@ import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.ui.tree.NodeDescriptor;
import com.intellij.debugger.ui.tree.render.DescriptorLabelListener;
+import com.intellij.debugger.ui.tree.render.OnDemandRenderer;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Key;
import com.intellij.util.containers.HashMap;
@@ -115,6 +116,11 @@ public abstract class NodeDescriptorImpl implements NodeDescriptor {
myIsSelected = that.myIsSelected;
myIsVisible = that.myIsVisible;
myUserData = that.myUserData != null ? new HashMap<>(that.myUserData) : null;
+
+ // TODO introduce unified way to handle this
+ if (myUserData != null) {
+ myUserData.remove(OnDemandRenderer.ON_DEMAND_CALCULATED); // calculated flag should not be inherited
+ }
}
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java
index 6ac237b51544..a900f2206ca3 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/ValueDescriptorImpl.java
@@ -33,6 +33,7 @@ import com.intellij.debugger.ui.tree.render.*;
import com.intellij.debugger.ui.tree.render.Renderer;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
@@ -327,6 +328,16 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements
public PsiExpression getDescriptorEvaluation(DebuggerContext context) throws EvaluateException {
return null;
}
+
+ @Override
+ public NodeRenderer getRenderer(DebugProcessImpl debugProcess) {
+ return ValueDescriptorImpl.this.getRenderer(debugProcess);
+ }
+
+ @Override
+ public T getUserData(Key key) {
+ return ValueDescriptorImpl.this.getUserData(key);
+ }
};
descriptor.myFullValue = true;
return descriptor;
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/LabelRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/LabelRenderer.java
index 176803a04837..665d2dfbfdea 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/LabelRenderer.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/LabelRenderer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2016 JetBrains s.r.o.
+ * Copyright 2000-2017 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.
@@ -18,25 +18,25 @@ package com.intellij.debugger.ui.tree.render;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.engine.DebugProcess;
import com.intellij.debugger.engine.DebuggerUtils;
-import com.intellij.debugger.engine.evaluation.EvaluateException;
-import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
-import com.intellij.debugger.engine.evaluation.EvaluationContext;
-import com.intellij.debugger.engine.evaluation.TextWithImports;
+import com.intellij.debugger.engine.FullValueEvaluatorProvider;
+import com.intellij.debugger.engine.evaluation.*;
import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator;
+import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl;
import com.intellij.debugger.ui.tree.ValueDescriptor;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.DefaultJDOMExternalizer;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.xdebugger.frame.XFullValueEvaluator;
import com.sun.jdi.Value;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-public class LabelRenderer extends TypeRenderer implements ValueLabelRenderer{
+public class LabelRenderer extends TypeRenderer implements ValueLabelRenderer, FullValueEvaluatorProvider {
public static final @NonNls String UNIQUE_ID = "LabelRenderer";
- private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.ui.impl.watch.render.ClassLabelRenderer");
+ public boolean myOnDemand;
private CachedEvaluator myLabelExpression = createCachedEvaluator();
@@ -62,6 +62,10 @@ public class LabelRenderer extends TypeRenderer implements ValueLabelRenderer{
public String calcLabel(ValueDescriptor descriptor, EvaluationContext evaluationContext, DescriptorLabelListener labelListener)
throws EvaluateException {
+ if (myOnDemand && !OnDemandRenderer.isCalculated(descriptor)) {
+ return "";
+ }
+
final Value value = descriptor.getValue();
String result;
@@ -88,6 +92,15 @@ public class LabelRenderer extends TypeRenderer implements ValueLabelRenderer{
return result;
}
+ @Nullable
+ @Override
+ public XFullValueEvaluator getFullValueEvaluator(EvaluationContextImpl evaluationContext, ValueDescriptorImpl valueDescriptor) {
+ if (myOnDemand && !OnDemandRenderer.isCalculated(valueDescriptor)) {
+ return OnDemandRenderer.createFullValueEvaluator("… " + getLabelExpression().getText());
+ }
+ return null;
+ }
+
public void readExternal(Element element) throws InvalidDataException {
super.readExternal(element);
DefaultJDOMExternalizer.readExternal(this, element);
@@ -111,4 +124,11 @@ public class LabelRenderer extends TypeRenderer implements ValueLabelRenderer{
myLabelExpression.setReferenceExpression(expression);
}
+ public boolean isOnDemand() {
+ return myOnDemand;
+ }
+
+ public void setOnDemand(boolean value) {
+ myOnDemand = value;
+ }
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/LazyToStringRenderer.kt b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/OnDemandRenderer.kt
similarity index 51%
rename from java/debugger/impl/src/com/intellij/debugger/ui/tree/render/LazyToStringRenderer.kt
rename to java/debugger/impl/src/com/intellij/debugger/ui/tree/render/OnDemandRenderer.kt
index 588146149a9b..41fcf05e600f 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/LazyToStringRenderer.kt
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/OnDemandRenderer.kt
@@ -16,63 +16,105 @@
package com.intellij.debugger.ui.tree.render
import com.intellij.debugger.DebuggerBundle
+import com.intellij.debugger.DebuggerContext
import com.intellij.debugger.engine.FullValueEvaluatorProvider
+import com.intellij.debugger.engine.JavaValue
import com.intellij.debugger.engine.evaluation.EvaluateException
import com.intellij.debugger.engine.evaluation.EvaluationContext
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl
import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl
+import com.intellij.debugger.ui.tree.DebuggerTreeNode
+import com.intellij.debugger.ui.tree.NodeDescriptor
import com.intellij.debugger.ui.tree.ValueDescriptor
import com.intellij.openapi.util.Key
+import com.intellij.psi.PsiElement
import com.intellij.xdebugger.frame.XFullValueEvaluator
import com.intellij.xdebugger.frame.XValuePlace
import com.intellij.xdebugger.impl.ui.tree.nodes.HeadlessValueEvaluationCallback
+import com.sun.jdi.Type
+import com.sun.jdi.Value
+import javax.swing.Icon
/**
* @author egor
*/
-class LazyToStringRenderer : ToStringRenderer(), FullValueEvaluatorProvider {
+class OnDemandRenderer(val renderer: NodeRendererImpl) : NodeRendererImpl(), FullValueEvaluatorProvider {
init {
isEnabled = true
}
- override fun getFullValueEvaluator(evaluationContext: EvaluationContextImpl?, valueDescriptor: ValueDescriptorImpl): XFullValueEvaluator? {
- if (!isCalculated(valueDescriptor)) {
- return object : XFullValueEvaluator(DebuggerBundle.message("message.node.toString")) {
- override fun startEvaluation(callback: XFullValueEvaluator.XFullValueEvaluationCallback) {
- if (callback is HeadlessValueEvaluationCallback) {
- val node = callback.node
- node.clearFullValueEvaluator()
- valueDescriptor.putUserData(LAZY_CALCULATED, true)
- node.valueContainer.computePresentation(node, XValuePlace.TREE)
- }
- callback.evaluated("")
- }
- }.setShowValuePopup(false)
- }
- return null
- }
-
@Throws(EvaluateException::class)
override fun calcLabel(descriptor: ValueDescriptor, evaluationContext: EvaluationContext, listener: DescriptorLabelListener): String? {
if (!isCalculated(descriptor)) {
return ""
}
- return super.calcLabel(descriptor, evaluationContext, listener)
+ return renderer.calcLabel(descriptor, evaluationContext, listener)
}
- fun isCalculated(descriptor: ValueDescriptor): Boolean {
- return java.lang.Boolean.TRUE == descriptor.getUserData(LAZY_CALCULATED)
+ override fun getFullValueEvaluator(evaluationContext: EvaluationContextImpl?, valueDescriptor: ValueDescriptorImpl): XFullValueEvaluator? {
+ if (!isCalculated(valueDescriptor)) {
+ return createFullValueEvaluator(DebuggerBundle.message("message.node.toString"))
+ }
+ return null
+ }
+
+ override fun buildChildren(value: Value?, builder: ChildrenBuilder?, evaluationContext: EvaluationContext?) {
+ renderer.buildChildren(value, builder, evaluationContext)
+ }
+
+ override fun getChildValueExpression(node: DebuggerTreeNode?, context: DebuggerContext?): PsiElement {
+ return renderer.getChildValueExpression(node, context)
+ }
+
+ override fun isExpandable(value: Value?, evaluationContext: EvaluationContext?, parentDescriptor: NodeDescriptor?): Boolean {
+ return renderer.isExpandable(value, evaluationContext, parentDescriptor)
+ }
+
+ override fun calcValueIcon(descriptor: ValueDescriptor?,
+ evaluationContext: EvaluationContext?,
+ listener: DescriptorLabelListener?): Icon? {
+ return renderer.calcValueIcon(descriptor, evaluationContext, listener)
+ }
+
+ override fun isApplicable(type: Type?): Boolean {
+ return renderer.isApplicable(type)
}
override fun getName(): String {
- return "Lazy" + super.getName()
+ return "OnDemand" + renderer.getName()
}
override fun getUniqueId(): String {
- return "Lazy" + super.getUniqueId()
+ return "OnDemand" + renderer.getUniqueId()
}
companion object {
- private val LAZY_CALCULATED = Key.create("LAZY_CALCULATED")
+ @JvmStatic
+ fun createFullValueEvaluator(text: String): XFullValueEvaluator {
+ return object : XFullValueEvaluator(text) {
+ override fun startEvaluation(callback: XFullValueEvaluator.XFullValueEvaluationCallback) {
+ if (callback is HeadlessValueEvaluationCallback) {
+ val node = callback.node
+ node.clearFullValueEvaluator()
+ setCalculated((node.valueContainer as JavaValue).descriptor)
+ node.valueContainer.computePresentation(node, XValuePlace.TREE)
+ }
+ callback.evaluated("")
+ }
+ }.setShowValuePopup(false)
+ }
+
+ @JvmField
+ val ON_DEMAND_CALCULATED = Key.create("ON_DEMAND_CALCULATED")
+
+ @JvmStatic
+ fun isCalculated(descriptor: ValueDescriptor): Boolean {
+ return ON_DEMAND_CALCULATED.get(descriptor, false)
+ }
+
+ @JvmStatic
+ fun setCalculated(descriptor: ValueDescriptor) {
+ ON_DEMAND_CALCULATED.set(descriptor, true)
+ }
}
-}
+}
\ No newline at end of file
diff --git a/java/debugger/openapi/src/com/intellij/debugger/ui/tree/NodeDescriptor.java b/java/debugger/openapi/src/com/intellij/debugger/ui/tree/NodeDescriptor.java
index 4ed6de6d6f9e..9dadd8082e69 100644
--- a/java/debugger/openapi/src/com/intellij/debugger/ui/tree/NodeDescriptor.java
+++ b/java/debugger/openapi/src/com/intellij/debugger/ui/tree/NodeDescriptor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2017 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.
@@ -15,16 +15,13 @@
*/
package com.intellij.debugger.ui.tree;
-import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.UserDataHolder;
-public interface NodeDescriptor {
+public interface NodeDescriptor extends UserDataHolder {
String getName();
String getLabel();
- T getUserData(Key key);
- void putUserData(Key key, T value);
-
void displayAs(NodeDescriptor descriptor);
void setAncestor(NodeDescriptor oldDescriptor);
diff --git a/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefJavaModule.java b/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefJavaModule.java
index bd072f85f38d..5c5ffd7a1371 100644
--- a/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefJavaModule.java
+++ b/java/java-analysis-api/src/com/intellij/codeInspection/reference/RefJavaModule.java
@@ -35,9 +35,15 @@ public interface RefJavaModule extends RefElement {
@NotNull
Map> getExportedPackageNames();
+ @NotNull
+ Set getServiceInterfaces();
+
@NotNull
Set getServiceImplementations();
+ @NotNull
+ Set getUsedServices();
+
@NotNull
List getRequiredModules();
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/AnnotateMethodFix.java b/java/java-analysis-impl/src/com/intellij/codeInspection/AnnotateMethodFix.java
index dff4e5d182a8..88c679bfa509 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/AnnotateMethodFix.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/AnnotateMethodFix.java
@@ -19,7 +19,6 @@ import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.intention.AddAnnotationPsiFix;
import com.intellij.openapi.command.undo.UndoUtil;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
@@ -37,7 +36,6 @@ import java.util.List;
* @author cdr
*/
public class AnnotateMethodFix implements LocalQuickFix {
- private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.AnnotateMethodFix");
protected final String myAnnotation;
private final String[] myAnnotationsToRemove;
@@ -68,7 +66,8 @@ public class AnnotateMethodFix implements LocalQuickFix {
List superMethodSignatures = method.findSuperMethodSignaturesIncludingStatic(true);
for (MethodSignatureBackedByPsiMethod superMethodSignature : superMethodSignatures) {
PsiMethod superMethod = superMethodSignature.getMethod();
- if (!AnnotationUtil.isAnnotated(superMethod, myAnnotation, false, false) && superMethod.getManager().isInProject(superMethod)) {
+ if (!AnnotationUtil.isAnnotated(superMethod, myAnnotation, false, false, true) &&
+ superMethod.getManager().isInProject(superMethod)) {
int ret = shouldAnnotateBaseMethod(method, superMethod, project);
if (ret != 0 && ret != 1) return;
if (ret == 0) {
@@ -79,7 +78,9 @@ public class AnnotateMethodFix implements LocalQuickFix {
if (annotateOverriddenMethods()) {
PsiMethod[] methods = OverridingMethodsSearch.search(method).toArray(PsiMethod.EMPTY_ARRAY);
for (PsiMethod psiMethod : methods) {
- if (AnnotationUtil.isAnnotatingApplicable(psiMethod, myAnnotation) && !AnnotationUtil.isAnnotated(psiMethod, myAnnotation, false, false) && psiMethod.getManager().isInProject(psiMethod)) {
+ if (AnnotationUtil.isAnnotatingApplicable(psiMethod, myAnnotation) &&
+ !AnnotationUtil.isAnnotated(psiMethod, myAnnotation, false, false, true) &&
+ psiMethod.getManager().isInProject(psiMethod)) {
toAnnotate.add(psiMethod);
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/java19modules/Java9ModuleEntryPoint.java b/java/java-analysis-impl/src/com/intellij/codeInspection/java19modules/Java9ModuleEntryPoint.java
index 63be397acfaa..3329d6334d5f 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/java19modules/Java9ModuleEntryPoint.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/java19modules/Java9ModuleEntryPoint.java
@@ -16,8 +16,8 @@
package com.intellij.codeInspection.java19modules;
import com.intellij.codeInsight.daemon.impl.analysis.JavaModuleGraphUtil;
-import com.intellij.codeInspection.reference.EntryPoint;
-import com.intellij.codeInspection.reference.RefElement;
+import com.intellij.codeInspection.reference.*;
+import com.intellij.codeInspection.visibility.EntryPointWithVisibilityLevel;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.pom.java.LanguageLevel;
@@ -30,16 +30,20 @@ import com.intellij.util.xmlb.XmlSerializer;
import gnu.trove.THashSet;
import one.util.streamex.StreamEx;
import org.jdom.Element;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
import java.util.Set;
/**
* @author Pavel.Dolgov
*/
-public class Java9ModuleEntryPoint extends EntryPoint {
+public class Java9ModuleEntryPoint extends EntryPointWithVisibilityLevel {
+ public static final String ID = "moduleInfo";
public boolean ADD_EXPORTED_PACKAGES_AND_SERVICES_TO_ENTRIES = true;
@NotNull
@@ -56,54 +60,126 @@ public class Java9ModuleEntryPoint extends EntryPoint {
@Override
public boolean isEntryPoint(@NotNull PsiElement psiElement) {
if (psiElement instanceof PsiClass) {
- return isExported((PsiClass)psiElement);
+ return isServiceOrExported((PsiClass)psiElement);
}
if (psiElement instanceof PsiMethod) {
PsiMethod method = (PsiMethod)psiElement;
if (isDefaultConstructor(method) || isProviderMethod(method)) {
- return isExported(method.getContainingClass());
+ return isServiceOrExported(method.getContainingClass());
}
}
return false;
}
- private static boolean isDefaultConstructor(PsiMethod method) {
+ @Override
+ public int getMinVisibilityLevel(PsiMember member) {
+ if (member instanceof PsiClass) {
+ final PsiJavaModule javaModule = getJavaModule(member);
+ if (javaModule != null &&
+ !isServiceClass((PsiClass)member, javaModule) &&
+ isInExportedPackage((PsiClass)member, javaModule)) {
+ return PsiUtil.ACCESS_LEVEL_PACKAGE_LOCAL;
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public String getTitle() {
+ return "Suggest package-private visibility level for classes in exported packages (Java 9+)";
+ }
+
+ @Override
+ public String getId() {
+ return ID;
+ }
+
+ @Override
+ public boolean keepVisibilityLevel(boolean entryPointEnabled, RefJavaElement refJavaElement) {
+ if (refJavaElement instanceof RefClass) {
+ RefClass refClass = (RefClass)refJavaElement;
+ RefModule refModule = refClass.getModule();
+ if (refModule != null) {
+ RefJavaModule refJavaModule = RefJavaModule.JAVA_MODULE.get(refModule);
+ if (refJavaModule != null) {
+ return isServiceClass(refClass, refJavaModule) ||
+ !entryPointEnabled && isInExportedPackage(refClass, refJavaModule);
+ }
+ }
+ }
+ return false;
+ }
+
+ private static boolean isInExportedPackage(@Nullable RefClass refClass, @NotNull RefJavaModule refJavaModule) {
+ RefEntity refOwner = refClass;
+ while (refOwner instanceof RefClass) {
+ String modifier = ((RefClass)refOwner).getAccessModifier();
+ refOwner = PsiModifier.PUBLIC.equals(modifier) || PsiModifier.PROTECTED.equals(modifier) ? refOwner.getOwner() : null;
+ }
+ if (refOwner instanceof RefPackage) {
+ Map> exportedPackageNames = refJavaModule.getExportedPackageNames();
+ if (exportedPackageNames.containsKey(refOwner.getQualifiedName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean isServiceClass(@Nullable RefClass refClass, @NotNull RefJavaModule refJavaModule) {
+ return refJavaModule.getServiceInterfaces().contains(refClass) ||
+ refJavaModule.getServiceImplementations().contains(refClass) ||
+ refJavaModule.getUsedServices().contains(refClass);
+ }
+
+
+ private static boolean isDefaultConstructor(@NotNull PsiMethod method) {
return method.isConstructor() &&
method.getParameterList().getParametersCount() == 0 &&
method.hasModifierProperty(PsiModifier.PUBLIC);
}
- private static boolean isProviderMethod(PsiMethod method) {
+ private static boolean isProviderMethod(@NotNull PsiMethod method) {
return "provider".equals(method.getName()) &&
method.getParameterList().getParametersCount() == 0 &&
method.hasModifierProperty(PsiModifier.PUBLIC) &&
method.hasModifierProperty(PsiModifier.STATIC);
}
- private static boolean isExported(@Nullable PsiClass psiClass) {
- if (psiClass != null) {
- String className = psiClass.getQualifiedName();
- if (className != null) {
- final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(psiClass);
- if (languageLevel.isAtLeast(LanguageLevel.JDK_1_9)) {
- PsiJavaModule javaModule = JavaModuleGraphUtil.findDescriptorByElement(psiClass);
- if (javaModule != null) {
- String packageName = getPublicApiPackageName(psiClass);
- if (packageName != null) {
- Set exportedPackageNames = getExportedPackageNames(javaModule);
- if (exportedPackageNames.contains(packageName)) {
- return true;
- }
- }
- Set serviceImplementationNames = getServiceImplementationNames(javaModule);
- return serviceImplementationNames.contains(className);
- }
- }
+ private static boolean isServiceOrExported(@Nullable PsiClass psiClass) {
+ PsiJavaModule javaModule = getJavaModule(psiClass);
+ return javaModule != null && (isServiceClass(psiClass, javaModule) || isInExportedPackage(psiClass, javaModule));
+ }
+
+ private static boolean isInExportedPackage(@NotNull PsiClass psiClass, @NotNull PsiJavaModule javaModule) {
+ String packageName = getPublicApiPackageName(psiClass);
+ if (packageName != null) {
+ Set exportedPackageNames = getExportedPackageNames(javaModule);
+ if (exportedPackageNames.contains(packageName)) {
+ return true;
}
}
return false;
}
+ private static boolean isServiceClass(@NotNull PsiClass psiClass, @NotNull PsiJavaModule javaModule) {
+ Set serviceClassNames = CachedValuesManager.getCachedValue(
+ javaModule, () -> CachedValueProvider.Result.create(collectServiceClassNames(javaModule), javaModule));
+
+ return serviceClassNames.contains(psiClass.getQualifiedName());
+ }
+
+ @Contract("null -> null")
+ @Nullable
+ private static PsiJavaModule getJavaModule(@Nullable PsiElement element) {
+ if (element != null) {
+ final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(element);
+ if (languageLevel.isAtLeast(LanguageLevel.JDK_1_9)) {
+ return JavaModuleGraphUtil.findDescriptorByElement(element);
+ }
+ }
+ return null;
+ }
+
private static String getPublicApiPackageName(PsiClass psiClass) {
if (psiClass != null && (psiClass.hasModifierProperty(PsiModifier.PUBLIC) || psiClass.hasModifierProperty(PsiModifier.PROTECTED))) {
PsiElement parent = psiClass.getParent();
@@ -128,18 +204,25 @@ public class Java9ModuleEntryPoint extends EntryPoint {
}
@NotNull
- private static Set getServiceImplementationNames(@NotNull PsiJavaModule javaModule) {
- return CachedValuesManager.getCachedValue(javaModule, () -> {
- Set classes = StreamEx.of(javaModule.getProvides().iterator())
- .map(PsiProvidesStatement::getImplementationList)
- .nonNull()
- .map(PsiReferenceList::getReferenceElements)
- .flatMap(Arrays::stream)
- .map(PsiJavaCodeReferenceElement::getQualifiedName)
- .nonNull()
- .toCollection(THashSet::new);
- return CachedValueProvider.Result.create(classes, javaModule);
- });
+ private static Set collectServiceClassNames(@NotNull PsiJavaModule javaModule) {
+ Set classes = StreamEx.of(javaModule.getProvides().spliterator())
+ .map(PsiProvidesStatement::getImplementationList)
+ .nonNull()
+ .map(PsiReferenceList::getReferenceElements)
+ .flatMap(Arrays::stream)
+ .map(PsiJavaCodeReferenceElement::getQualifiedName)
+ .nonNull()
+ .toCollection(THashSet::new);
+
+ Set usages = StreamEx.of(javaModule.getUses().iterator())
+ .map(PsiUsesStatement::getClassReference)
+ .nonNull()
+ .map(PsiJavaCodeReferenceElement::getQualifiedName)
+ .nonNull()
+ .toCollection(THashSet::new);
+
+ classes.addAll(usages);
+ return classes;
}
@Override
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaModuleImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaModuleImpl.java
index 71efaf4daba5..16e81f8d8854 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaModuleImpl.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaModuleImpl.java
@@ -33,7 +33,9 @@ public class RefJavaModuleImpl extends RefElementImpl implements RefJavaModule {
private final RefModule myRefModule;
private Map> myExportedPackageNames;
+ private Set myServiceInterfaces;
private Set myServiceImplementations;
+ private Set myUsedServices;
private List myRequiredModules;
RefJavaModuleImpl(@NotNull PsiJavaModule javaModule, @NotNull RefManagerImpl manager) {
@@ -75,104 +77,152 @@ public class RefJavaModuleImpl extends RefElementImpl implements RefJavaModule {
return myExportedPackageNames != null ? myExportedPackageNames : Collections.emptyMap();
}
+ @NotNull
+ @Override
+ public Set getServiceInterfaces() {
+ return myServiceInterfaces != null ? myServiceInterfaces : Collections.emptySet();
+ }
+
@NotNull
@Override
public Set getServiceImplementations() {
return myServiceImplementations != null ? myServiceImplementations : Collections.emptySet();
}
+ @NotNull
+ @Override
+ public Set getUsedServices() {
+ return myUsedServices != null ? myUsedServices : Collections.emptySet();
+ }
+
@Override
@NotNull
public List getRequiredModules() {
return myRequiredModules != null ? myRequiredModules : Collections.emptyList();
}
- @Override
- public void buildReferences() {
- PsiJavaModule javaModule = getElement();
- if (javaModule != null) {
- for (PsiRequiresStatement statement : javaModule.getRequires()) {
- PsiJavaModuleReferenceElement referenceElement = statement.getReferenceElement();
+ private void buildRequiresReferences(PsiJavaModule javaModule) {
+ for (PsiRequiresStatement statement : javaModule.getRequires()) {
+ PsiJavaModuleReferenceElement referenceElement = statement.getReferenceElement();
+ if (referenceElement != null) {
+ PsiElement element = addReference(referenceElement.getReference());
+ if (element instanceof PsiJavaModule) {
+ PsiJavaModule requiredModule = (PsiJavaModule)element;
+ Map> packagesExportedByModule = getPackagesExportedByModule(requiredModule);
+ if (myRequiredModules == null) myRequiredModules = new ArrayList<>(1);
+ myRequiredModules.add(new RequiredModule(requiredModule.getName(), packagesExportedByModule, statement.hasModifierProperty(PsiModifier.TRANSITIVE)));
+ }
+ }
+ }
+ }
+
+ private void buildExportsReferences(PsiJavaModule javaModule) {
+ List emptyList = Collections.emptyList();
+ for (PsiPackageAccessibilityStatement statement : javaModule.getExports()) {
+ PsiElement element = addReference(statement.getPackageReference());
+ String packageName = null;
+ if (element instanceof PsiPackage) {
+ packageName = ((PsiPackage)element).getQualifiedName();
+ if (myExportedPackageNames == null) myExportedPackageNames = new THashMap<>(1);
+ myExportedPackageNames.put(packageName, emptyList);
+ }
+ for (PsiJavaModuleReferenceElement referenceElement : statement.getModuleReferences()) {
if (referenceElement != null) {
- PsiElement element = addReference(referenceElement.getReference());
- if (element instanceof PsiJavaModule) {
- PsiJavaModule requiredModule = (PsiJavaModule)element;
- Map> packagesExportedByModule = getPackagesExportedByModule(requiredModule);
- if (myRequiredModules == null) myRequiredModules = new ArrayList<>(1);
- myRequiredModules.add(new RequiredModule(requiredModule.getName(), packagesExportedByModule, statement.hasModifierProperty(PsiModifier.TRANSITIVE)));
+ PsiElement moduleElement = addReference(referenceElement.getReference());
+ if (packageName != null && moduleElement instanceof PsiJavaModule) {
+ List toModuleNames = myExportedPackageNames.get(packageName);
+ if (toModuleNames == emptyList) myExportedPackageNames.put(packageName, toModuleNames = new ArrayList<>(1));
+ toModuleNames.add(((PsiJavaModule)moduleElement).getName());
}
}
}
- List emptyList = Collections.emptyList();
- for (PsiPackageAccessibilityStatement statement : javaModule.getExports()) {
- PsiElement element = addReference(statement.getPackageReference());
- String packageName = null;
- if (element instanceof PsiPackage) {
- packageName = ((PsiPackage)element).getQualifiedName();
- if (myExportedPackageNames == null) myExportedPackageNames = new THashMap<>(1);
- myExportedPackageNames.put(packageName, emptyList);
- }
- for (PsiJavaModuleReferenceElement referenceElement : statement.getModuleReferences()) {
- if (referenceElement != null) {
- PsiElement moduleElement = addReference(referenceElement.getReference());
- if (packageName != null && moduleElement instanceof PsiJavaModule) {
- List toModuleNames = myExportedPackageNames.get(packageName);
- if (toModuleNames == emptyList) myExportedPackageNames.put(packageName, toModuleNames = new ArrayList<>(1));
- toModuleNames.add(((PsiJavaModule)moduleElement).getName());
- }
- }
- }
- }
- for (PsiProvidesStatement statement : javaModule.getProvides()) {
- final PsiJavaCodeReferenceElement interfaceReference = statement.getInterfaceReference();
- final PsiReferenceList implementationList = statement.getImplementationList();
- if (interfaceReference != null && implementationList != null) {
- final PsiElement providerInterface = interfaceReference.resolve();
- if (providerInterface instanceof PsiClass) {
- final RefElement refInterface = getRefManager().getReference(providerInterface);
- if (refInterface instanceof RefJavaElementImpl) {
- for (PsiJavaCodeReferenceElement implementationReference : implementationList.getReferenceElements()) {
- final PsiElement implementationClass = implementationReference.resolve();
- if (implementationClass instanceof PsiClass) {
- RefElement refTargetElement = null;
- PsiElement targetElement = getProviderMethod((PsiClass)implementationClass);
+ }
+ }
- if (targetElement == null) {
- final RefElement refClass = getRefManager().getReference(implementationClass);
- if (refClass instanceof RefClassImpl) {
- if (myServiceImplementations == null) myServiceImplementations = new THashSet<>();
- myServiceImplementations.add((RefClass)refClass);
+ private void buildProvidesReferences(PsiJavaModule javaModule) {
+ for (PsiProvidesStatement statement : javaModule.getProvides()) {
+ final PsiJavaCodeReferenceElement interfaceReference = statement.getInterfaceReference();
+ final PsiReferenceList implementationList = statement.getImplementationList();
+ if (interfaceReference != null && implementationList != null) {
+ final PsiElement providerInterface = interfaceReference.resolve();
+ if (providerInterface instanceof PsiClass) {
+ final RefElement refInterface = getRefManager().getReference(providerInterface);
+ if (refInterface instanceof RefClassImpl) {
+ if (myServiceInterfaces == null) myServiceInterfaces = new THashSet<>();
+ myServiceInterfaces.add((RefClass)refInterface);
- final RefMethod refConstructor = ((RefClassImpl)refClass).getDefaultConstructor();
- if (refConstructor != null) {
- final PsiModifierListOwner constructorElement = refConstructor.getElement();
- if (constructorElement != null && constructorElement.hasModifierProperty(PsiModifier.PUBLIC)) {
- refTargetElement = refConstructor;
- targetElement = constructorElement;
- }
+ for (PsiJavaCodeReferenceElement implementationReference : implementationList.getReferenceElements()) {
+ final PsiElement implementationClass = implementationReference.resolve();
+ if (implementationClass instanceof PsiClass) {
+ RefElement refTargetElement = null;
+ PsiElement targetElement = getProviderMethod((PsiClass)implementationClass);
+
+ if (targetElement == null) {
+ final RefElement refClass = getRefManager().getReference(implementationClass);
+ if (refClass instanceof RefClassImpl) {
+ if (myServiceImplementations == null) myServiceImplementations = new THashSet<>();
+ myServiceImplementations.add((RefClass)refClass);
+
+ final RefMethod refConstructor = ((RefClassImpl)refClass).getDefaultConstructor();
+ if (refConstructor != null) {
+ final PsiModifierListOwner constructorElement = refConstructor.getElement();
+ if (constructorElement != null && constructorElement.hasModifierProperty(PsiModifier.PUBLIC)) {
+ refTargetElement = refConstructor;
+ targetElement = constructorElement;
}
}
}
- if (targetElement == null) {
- targetElement = implementationClass;
- }
- if (refTargetElement == null) {
- refTargetElement = getRefManager().getReference(targetElement);
- }
- if (refTargetElement != null) {
- ((RefJavaElementImpl)refInterface)
- .addReference(refTargetElement, targetElement, providerInterface, false, true, null);
- }
+ }
+ if (targetElement == null) {
+ targetElement = implementationClass;
+ }
+ if (refTargetElement == null) {
+ refTargetElement = getRefManager().getReference(targetElement);
+ }
+ if (refTargetElement != null) {
+ ((RefClassImpl)refInterface)
+ .addReference(refTargetElement, targetElement, providerInterface, false, true, null);
}
}
}
}
}
}
+ }
+ }
+
+ private void buildUsesReferences(PsiJavaModule javaModule) {
+ for (PsiUsesStatement statement : javaModule.getUses()) {
+ final PsiJavaCodeReferenceElement reference = statement.getClassReference();
+ if (reference != null) {
+ final PsiElement usedInterface = reference.resolve();
+ if (usedInterface instanceof PsiClass) {
+ final RefElement refClass = getRefManager().getReference(usedInterface);
+ if (refClass instanceof RefClass) {
+ if (myUsedServices == null) myUsedServices = new THashSet<>();
+ myUsedServices.add((RefClass)refClass);
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void buildReferences() {
+ PsiJavaModule javaModule = getElement();
+ if (javaModule != null) {
+ buildRequiresReferences(javaModule);
+ buildExportsReferences(javaModule);
+ buildProvidesReferences(javaModule);
+ buildUsesReferences(javaModule);
+
getRefManager().fireBuildReferences(this);
}
}
+ /**
+ * For building references between modules
+ */
private PsiElement addReference(PsiPolyVariantReference reference) {
List resolvedElements = new ArrayList<>();
if (reference != null) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/EntryPointWithVisibilityLevel.java b/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/EntryPointWithVisibilityLevel.java
index 36a1e0ed4298..b57721487944 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/EntryPointWithVisibilityLevel.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/EntryPointWithVisibilityLevel.java
@@ -16,7 +16,7 @@
package com.intellij.codeInspection.visibility;
import com.intellij.codeInspection.reference.EntryPoint;
-import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.codeInspection.reference.RefJavaElement;
import com.intellij.psi.PsiMember;
import com.intellij.psi.util.PsiUtil;
@@ -39,4 +39,11 @@ public abstract class EntryPointWithVisibilityLevel extends EntryPoint {
* Id to serialize checkbox state in visibility inspection settings
*/
public abstract String getId();
+
+ /**
+ * Don't suggest decreasing visibility for the element, sometimes even if the entry point is disabled.
+ */
+ public boolean keepVisibilityLevel(boolean entryPointEnabled, @SuppressWarnings("unused") RefJavaElement refJavaElement) {
+ return false;
+ }
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java
index b64802ac94b2..6865cf828374 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java
@@ -23,6 +23,7 @@ import com.intellij.codeInsight.daemon.impl.IdentifierUtil;
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ex.EntryPointsManager;
import com.intellij.codeInspection.reference.*;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.ExtensionPoint;
import com.intellij.openapi.extensions.ExtensionPointName;
@@ -36,10 +37,12 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.ui.components.panels.VerticalBox;
import com.intellij.usageView.UsageViewTypeLocation;
import com.intellij.util.VisibilityUtil;
+import one.util.streamex.StreamEx;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import java.awt.*;
@@ -101,7 +104,7 @@ public class VisibilityInspection extends GlobalJavaBatchInspectionTool {
if (entryPoint instanceof EntryPointWithVisibilityLevel) {
gc.gridy++;
final JCheckBox checkBox = new JCheckBox(((EntryPointWithVisibilityLevel)entryPoint).getTitle());
- checkBox.setSelected(myExtensions.getOrDefault(((EntryPointWithVisibilityLevel)entryPoint).getId(), true));
+ checkBox.setSelected(isEntryPointEnabled((EntryPointWithVisibilityLevel)entryPoint));
checkBox.addActionListener(e -> myExtensions.put(((EntryPointWithVisibilityLevel)entryPoint).getId(), checkBox.isSelected()));
add(checkBox, gc);
}
@@ -181,11 +184,14 @@ public class VisibilityInspection extends GlobalJavaBatchInspectionTool {
//ignore anonymous classes. They do not have access modifiers.
if (refElement instanceof RefClass) {
RefClass refClass = (RefClass) refElement;
- if (refClass.isAnonymous() || refClass.isServlet() || refClass.isApplet() || refClass.isLocalClass() || isExported(refClass)) {
+ if (refClass.isAnonymous() || refClass.isServlet() || refClass.isApplet() || refClass.isLocalClass()) {
return null;
}
}
+ if (keepVisibilityLevel(refElement)) {
+ return null;
+ }
//ignore unreferenced code. They could be a potential entry points.
if (refElement.getInReferences().isEmpty()) {
@@ -215,30 +221,10 @@ public class VisibilityInspection extends GlobalJavaBatchInspectionTool {
return null;
}
- private static boolean isExported(RefClass refClass) {
- RefModule refModule = refClass.getModule();
- if (refModule != null) {
- RefJavaModule refJavaModule = RefJavaModule.JAVA_MODULE.get(refModule);
- if (refJavaModule != null) {
- Set serviceImplementations = refJavaModule.getServiceImplementations();
- if (serviceImplementations.contains(refClass)) {
- return true;
- }
-
- RefEntity refOwner = refClass;
- while (refOwner instanceof RefClass) {
- String modifier = ((RefClass)refOwner).getAccessModifier();
- refOwner = PsiModifier.PUBLIC.equals(modifier) || PsiModifier.PROTECTED.equals(modifier) ? refOwner.getOwner() : null;
- }
- if (refOwner instanceof RefPackage) {
- Map> exportedPackageNames = refJavaModule.getExportedPackageNames();
- if (exportedPackageNames.containsKey(refOwner.getQualifiedName())) {
- return true;
- }
- }
- }
- }
- return false;
+ private boolean keepVisibilityLevel(RefJavaElement refElement) {
+ return StreamEx.of(ExtensionPointName.create(ToolExtensionPoints.DEAD_CODE_TOOL).getExtensions())
+ .select(EntryPointWithVisibilityLevel.class)
+ .anyMatch(point -> point.keepVisibilityLevel(isEntryPointEnabled(point), refElement));
}
@NotNull
@@ -273,13 +259,17 @@ public class VisibilityInspection extends GlobalJavaBatchInspectionTool {
}
int getMinVisibilityLevel(PsiMember member) {
- return Arrays.stream(ExtensionPointName.create(ToolExtensionPoints.DEAD_CODE_TOOL).getExtensions())
- .filter(point -> point instanceof EntryPointWithVisibilityLevel &&
- myExtensions.getOrDefault(((EntryPointWithVisibilityLevel)point).getId(), true))
- .mapToInt(point -> ((EntryPointWithVisibilityLevel)point).getMinVisibilityLevel(member))
+ return StreamEx.of(ExtensionPointName.create(ToolExtensionPoints.DEAD_CODE_TOOL).getExtensions())
+ .select(EntryPointWithVisibilityLevel.class)
+ .filter(point -> isEntryPointEnabled(point))
+ .mapToInt(point -> point.getMinVisibilityLevel(member))
.max().orElse(-1);
}
+ private boolean isEntryPointEnabled(EntryPointWithVisibilityLevel point) {
+ return myExtensions.getOrDefault(point.getId(), true);
+ }
+
private int getMinVisibilityLevel(RefJavaElement refElement) {
PsiElement element = refElement.getElement();
if (element instanceof PsiMember) {
@@ -627,6 +617,12 @@ public class VisibilityInspection extends GlobalJavaBatchInspectionTool {
}
}
+ @TestOnly
+ public void setEntryPointEnabled(@NotNull String entryPointId, boolean enabled) {
+ LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode());
+ myExtensions.put(entryPointId, enabled);
+ }
+
private static class AcceptSuggestedAccess implements LocalQuickFix{
private final RefManager myManager;
@PsiModifier.ModifierConstant private final String myHint;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/wrongPackageStatement/WrongPackageStatementInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/wrongPackageStatement/WrongPackageStatementInspectionBase.java
index 33a38f8bf6d2..ec0a9bd8ba4b 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/wrongPackageStatement/WrongPackageStatementInspectionBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/wrongPackageStatement/WrongPackageStatementInspectionBase.java
@@ -57,7 +57,7 @@ public class WrongPackageStatementInspectionBase extends BaseJavaBatchLocalInspe
String description = JavaErrorMessages.message("missing.package.statement", packageName);
return new ProblemDescriptor[]{manager.createProblemDescriptor(classes[0].getNameIdentifier(), description,
- new AdjustPackageNameFix(packageName),
+ isValidPackageName(packageName, file.getProject()) ? new AdjustPackageNameFix(packageName) : null,
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly)};
}
if (packageStatement != null) {
diff --git a/java/java-impl/src/com/intellij/refactoring/actions/RenameFileActionImpl.java b/java/java-impl/src/com/intellij/refactoring/actions/RenameFileActionImpl.java
new file mode 100644
index 000000000000..95e7b3bfd292
--- /dev/null
+++ b/java/java-impl/src/com/intellij/refactoring/actions/RenameFileActionImpl.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2017 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.refactoring.actions;
+
+import com.intellij.psi.PsiClassOwner;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NotNull;
+
+public class RenameFileActionImpl extends RenameFileAction {
+ @Override
+ protected boolean enabledInProjectView(@NotNull PsiFile file) {
+ return file instanceof PsiClassOwner;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/slicer/SliceLeafAnalyzer.java b/java/java-impl/src/com/intellij/slicer/SliceLeafAnalyzer.java
index 38370ba676f9..519661672530 100644
--- a/java/java-impl/src/com/intellij/slicer/SliceLeafAnalyzer.java
+++ b/java/java-impl/src/com/intellij/slicer/SliceLeafAnalyzer.java
@@ -172,6 +172,7 @@ public class SliceLeafAnalyzer {
public static Map> createMap() {
return new FactoryMap>() {
+ @NotNull
@Override
protected Map> createMap() {
return ContainerUtil.newConcurrentMap(ContainerUtil.identityStrategy());
diff --git a/java/java-impl/src/com/intellij/slicer/SliceNullnessAnalyzer.java b/java/java-impl/src/com/intellij/slicer/SliceNullnessAnalyzer.java
index cd9e1535f00e..e0a6856c972b 100644
--- a/java/java-impl/src/com/intellij/slicer/SliceNullnessAnalyzer.java
+++ b/java/java-impl/src/com/intellij/slicer/SliceNullnessAnalyzer.java
@@ -137,6 +137,7 @@ public class SliceNullnessAnalyzer {
return new NullAnalysisResult();
}
+ @NotNull
@Override
protected Map createMap() {
return ContainerUtil.newIdentityTroveMap();
diff --git a/java/java-impl/src/com/intellij/testIntegration/TestRunLineMarkerProvider.java b/java/java-impl/src/com/intellij/testIntegration/TestRunLineMarkerProvider.java
index 81968ea62ab5..06d160c09092 100644
--- a/java/java-impl/src/com/intellij/testIntegration/TestRunLineMarkerProvider.java
+++ b/java/java-impl/src/com/intellij/testIntegration/TestRunLineMarkerProvider.java
@@ -16,12 +16,8 @@
package com.intellij.testIntegration;
import com.intellij.codeInsight.TestFrameworks;
-import com.intellij.execution.TestStateStorage;
import com.intellij.execution.lineMarker.ExecutorAction;
import com.intellij.execution.lineMarker.RunLineMarkerContributor;
-import com.intellij.execution.testframework.TestIconMapper;
-import com.intellij.execution.testframework.sm.runner.states.TestStateInfo;
-import com.intellij.icons.AllIcons;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
@@ -73,23 +69,4 @@ public class TestRunLineMarkerProvider extends RunLineMarkerContributor {
protected boolean isIdentifier(PsiElement e) {
return e instanceof PsiIdentifier;
}
-
- private static Icon getTestStateIcon(String url, Project project, boolean isClass) {
- TestStateStorage.Record state = TestStateStorage.getInstance(project).getState(url);
- if (state != null) {
- TestStateInfo.Magnitude magnitude = TestIconMapper.getMagnitude(state.magnitude);
- if (magnitude != null) {
- switch (magnitude) {
- case ERROR_INDEX:
- case FAILED_INDEX:
- return AllIcons.RunConfigurations.TestState.Red2;
- case PASSED_INDEX:
- case COMPLETE_INDEX:
- return AllIcons.RunConfigurations.TestState.Green2;
- default:
- }
- }
- }
- return isClass ? AllIcons.RunConfigurations.TestState.Run_run : AllIcons.RunConfigurations.TestState.Run;
- }
}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearchHelper.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearchHelper.java
index a1c32a4793f7..30d6a624d5fb 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearchHelper.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/ConstructorReferencesSearchHelper.java
@@ -18,6 +18,7 @@ package com.intellij.psi.impl.search;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.UnfairTextRange;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.light.LightMemberReference;
@@ -258,6 +259,9 @@ class ConstructorReferencesSearchHelper {
if (startOffsetInParent >= 0) { // -1 for light elements generated e.g. by lombok
return TextRange.from(startOffsetInParent, identifier.getTextLength());
}
+ else {
+ return new UnfairTextRange(-1, -1);
+ }
}
}
return super.getRangeInElement();
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaOverridingMethodsSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaOverridingMethodsSearcher.java
index 6a1200c75ba7..04d9123f57d6 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaOverridingMethodsSearcher.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaOverridingMethodsSearcher.java
@@ -53,9 +53,11 @@ public class JavaOverridingMethodsSearcher implements QueryExecutor file.getFileType() == JavaFileType.INSTANCE)) {
- return processLocalScope((LocalSearchScope)searchScope, method, project, consumer);
+ if (searchScope instanceof LocalSearchScope) {
+ VirtualFile[] files = ((LocalSearchScope)searchScope).getVirtualFiles();
+ if (isJavaOnlyScope(files)) {
+ return processLocalScope((LocalSearchScope)searchScope, method, project, consumer);
+ }
}
Iterable cached = HighlightingCaches.getInstance(project).OVERRIDING_METHODS.get(method);
@@ -79,6 +81,10 @@ public class JavaOverridingMethodsSearcher implements QueryExecutor file.getFileType() == JavaFileType.INSTANCE);
+ }
+
private static boolean processLocalScope(@NotNull LocalSearchScope searchScope,
@NotNull PsiMethod method,
@NotNull Project project,
diff --git a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java
index d84ff358f983..041a8f5036b4 100644
--- a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java
+++ b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java
@@ -86,13 +86,10 @@ public class AnnotationUtil {
}
private static PsiAnnotation findOwnAnnotation(final PsiModifierListOwner listOwner, Collection annotationNames) {
- ConcurrentFactoryMap, PsiAnnotation> map = CachedValuesManager.getCachedValue(
+ Map, PsiAnnotation> map = CachedValuesManager.getCachedValue(
listOwner,
() -> {
- ConcurrentFactoryMap, PsiAnnotation> value = new ConcurrentFactoryMap, PsiAnnotation>() {
- @Nullable
- @Override
- protected PsiAnnotation create(Collection annotationNames1) {
+ Map, PsiAnnotation> value = ConcurrentFactoryMap.createConcurrentMap(annotationNames1-> {
final PsiModifierList list = listOwner.getModifierList();
if (list == null) return null;
for (PsiAnnotation annotation : list.getAnnotations()) {
@@ -102,20 +99,17 @@ public class AnnotationUtil {
}
return null;
}
- };
+ );
return CachedValueProvider.Result.create(value, PsiModificationTracker.MODIFICATION_COUNT);
});
return map.get(annotationNames);
}
private static PsiAnnotation findNonCodeAnnotation(final PsiModifierListOwner listOwner, Collection annotationNames) {
- ConcurrentFactoryMap, PsiAnnotation> map = CachedValuesManager.getCachedValue(
+ Map, PsiAnnotation> map = CachedValuesManager.getCachedValue(
listOwner,
() -> {
- ConcurrentFactoryMap, PsiAnnotation> value = new ConcurrentFactoryMap, PsiAnnotation>() {
- @Nullable
- @Override
- protected PsiAnnotation create(Collection annotationNames1) {
+ Map, PsiAnnotation> value = ConcurrentFactoryMap.createConcurrentMap(annotationNames1-> {
final Project project = listOwner.getProject();
final ExternalAnnotationsManager annotationsManager = ExternalAnnotationsManager.getInstance(project);
for (String annotationName : annotationNames1) {
@@ -134,7 +128,7 @@ public class AnnotationUtil {
return null;
}
- };
+ );
return CachedValueProvider.Result.create(value, PsiModificationTracker.MODIFICATION_COUNT);
});
return map.get(annotationNames);
@@ -184,13 +178,11 @@ public class AnnotationUtil {
PsiAnnotation directAnnotation = findAnnotation(listOwner, annotationNames);
if (directAnnotation != null) return directAnnotation;
- ConcurrentFactoryMap, PsiAnnotation> map = CachedValuesManager.getCachedValue(
+ Map, PsiAnnotation> map = CachedValuesManager.getCachedValue(
listOwner,
() -> {
- ConcurrentFactoryMap, PsiAnnotation> value = new ConcurrentFactoryMap, PsiAnnotation>() {
- @Nullable
- @Override
- protected PsiAnnotation create(Set annotationNames1) {
+ Map, PsiAnnotation> value = ConcurrentFactoryMap.createConcurrentMap(annotationNames1->
+ {
for (PsiModifierListOwner superOwner : getSuperAnnotationOwners(listOwner)) {
PsiAnnotation annotation = findAnnotation(superOwner, annotationNames1);
if (annotation != null) {
@@ -199,7 +191,7 @@ public class AnnotationUtil {
}
return null;
}
- };
+ );
return CachedValueProvider.Result.create(value, PsiModificationTracker.MODIFICATION_COUNT);
});
return map.get(annotationNames);
@@ -265,21 +257,30 @@ public class AnnotationUtil {
}
public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner, @NotNull String annotationFQN, boolean checkHierarchy) {
- return isAnnotated(listOwner, annotationFQN, checkHierarchy, true, null);
+ return isAnnotated(listOwner, annotationFQN, checkHierarchy, true, true, null);
}
public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner,
@NotNull String annotationFQN,
boolean checkHierarchy,
boolean skipExternal) {
- return isAnnotated(listOwner, annotationFQN, checkHierarchy, skipExternal, null);
+ return isAnnotated(listOwner, annotationFQN, checkHierarchy, skipExternal, skipExternal);
+ }
+
+ public static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner,
+ @NotNull String annotationFQN,
+ boolean checkHierarchy,
+ boolean skipExternal,
+ boolean skipInferred) {
+ return isAnnotated(listOwner, annotationFQN, checkHierarchy, skipExternal, skipInferred, null);
}
private static boolean isAnnotated(@NotNull PsiModifierListOwner listOwner,
- @NotNull String annotationFQN,
- boolean checkHierarchy,
- boolean skipExternal,
- @Nullable Set processed) {
+ @NotNull String annotationFQN,
+ boolean checkHierarchy,
+ boolean skipExternal,
+ boolean skipInferred,
+ @Nullable Set processed) {
if (!listOwner.isValid()) return false;
PsiModifierList modifierList = listOwner.getModifierList();
@@ -289,14 +290,23 @@ public class AnnotationUtil {
if (annotation != null) return true;
PsiType type = null;
- if (listOwner instanceof PsiMethod) type = ((PsiMethod)listOwner).getReturnType();
- else if (listOwner instanceof PsiVariable) type = ((PsiVariable)listOwner).getType();
+ if (listOwner instanceof PsiMethod) {
+ type = ((PsiMethod)listOwner).getReturnType();
+ }
+ else if (listOwner instanceof PsiVariable) {
+ type = ((PsiVariable)listOwner).getType();
+ }
if (type != null && type.findAnnotation(annotationFQN) != null) return true;
if (!skipExternal) {
final Project project = listOwner.getProject();
- if (ExternalAnnotationsManager.getInstance(project).findExternalAnnotation(listOwner, annotationFQN) != null ||
- InferredAnnotationsManager.getInstance(project).findInferredAnnotation(listOwner, annotationFQN) != null) {
+ if (ExternalAnnotationsManager.getInstance(project).findExternalAnnotation(listOwner, annotationFQN) != null) {
+ return true;
+ }
+ }
+ if (!skipInferred) {
+ final Project project = listOwner.getProject();
+ if (InferredAnnotationsManager.getInstance(project).findInferredAnnotation(listOwner, annotationFQN) != null) {
return true;
}
}
@@ -308,7 +318,7 @@ public class AnnotationUtil {
if (!processed.add(method)) return false;
final PsiMethod[] superMethods = method.findSuperMethods();
for (PsiMethod superMethod : superMethods) {
- if (isAnnotated(superMethod, annotationFQN, true, skipExternal, processed)) return true;
+ if (isAnnotated(superMethod, annotationFQN, true, skipExternal, skipInferred, processed)) return true;
}
}
else if (listOwner instanceof PsiClass) {
@@ -317,7 +327,7 @@ public class AnnotationUtil {
if (!processed.add(clazz)) return false;
final PsiClass[] superClasses = clazz.getSupers();
for (PsiClass superClass : superClasses) {
- if (isAnnotated(superClass, annotationFQN, true, skipExternal, processed)) return true;
+ if (isAnnotated(superClass, annotationFQN, true, skipExternal, skipInferred, processed)) return true;
}
}
}
@@ -536,7 +546,7 @@ public class AnnotationUtil {
if (a == null) {
return b == null;
}
- else if (b == null) {
+ if (b == null) {
return false;
}
final String name = a.getQualifiedName();
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/annotateMethod/afterOverriddenWithInferred.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/annotateMethod/afterOverriddenWithInferred.java
new file mode 100644
index 000000000000..14a463bb4b07
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/annotateMethod/afterOverriddenWithInferred.java
@@ -0,0 +1,18 @@
+// "Annotate overridden methods as '@NotNull'" "true"
+
+import org.jetbrains.annotations.NotNull;
+
+abstract class P2 {
+ @NotNull
+ String foo(@NotNull String p) {
+ return p;
+ }
+
+ Object o = new P2() {
+ @NotNull
+ @Override
+ String foo(String p) {
+ return "";
+ }
+ };
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/annotateMethod/beforeOverriddenWithInferred.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/annotateMethod/beforeOverriddenWithInferred.java
new file mode 100644
index 000000000000..343fc019c121
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/annotateMethod/beforeOverriddenWithInferred.java
@@ -0,0 +1,17 @@
+// "Annotate overridden methods as '@NotNull'" "true"
+
+import org.jetbrains.annotations.NotNull;
+
+abstract class P2 {
+ @NotNull
+ String foo(@NotNull String p) {
+ return p;
+ }
+
+ Object o = new P2() {
+ @Override
+ String foo(String p) {
+ return "";
+ }
+ };
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/java9Visibility/reduceVisibilityInExportedPackages/Public.java b/java/java-tests/testData/inspection/java9Visibility/reduceVisibilityInExportedPackages/Public.java
new file mode 100644
index 000000000000..69dda4039633
--- /dev/null
+++ b/java/java-tests/testData/inspection/java9Visibility/reduceVisibilityInExportedPackages/Public.java
@@ -0,0 +1,3 @@
+package foo.bar;
+
+public class Public {}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/java9Visibility/reduceVisibilityInExportedPackages/ServiceApi.java b/java/java-tests/testData/inspection/java9Visibility/reduceVisibilityInExportedPackages/ServiceApi.java
new file mode 100644
index 000000000000..7fd656840fcc
--- /dev/null
+++ b/java/java-tests/testData/inspection/java9Visibility/reduceVisibilityInExportedPackages/ServiceApi.java
@@ -0,0 +1,3 @@
+package foo.bar;
+
+public class ServiceApi {}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/java9Visibility/reduceVisibilityInExportedPackages/ServiceImpl.java b/java/java-tests/testData/inspection/java9Visibility/reduceVisibilityInExportedPackages/ServiceImpl.java
new file mode 100644
index 000000000000..16a1a3626aec
--- /dev/null
+++ b/java/java-tests/testData/inspection/java9Visibility/reduceVisibilityInExportedPackages/ServiceImpl.java
@@ -0,0 +1,3 @@
+package foo.bar;
+
+public class ServiceImpl extends ServiceApi {}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/java9Visibility/reduceVisibilityInExportedPackages/UsedService.java b/java/java-tests/testData/inspection/java9Visibility/reduceVisibilityInExportedPackages/UsedService.java
new file mode 100644
index 000000000000..e737a4be4fd0
--- /dev/null
+++ b/java/java-tests/testData/inspection/java9Visibility/reduceVisibilityInExportedPackages/UsedService.java
@@ -0,0 +1,3 @@
+package foo.bar;
+
+public class UsedService {}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/java9Visibility/reduceVisibilityInExportedPackages/expected.xml b/java/java-tests/testData/inspection/java9Visibility/reduceVisibilityInExportedPackages/expected.xml
new file mode 100644
index 000000000000..8e068179635c
--- /dev/null
+++ b/java/java-tests/testData/inspection/java9Visibility/reduceVisibilityInExportedPackages/expected.xml
@@ -0,0 +1,10 @@
+
+
+
+ Public.java
+ 3
+
+ Declaration access can be weaker
+ Can be package-private
+
+
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/java9Visibility/usedService/Api.java b/java/java-tests/testData/inspection/java9Visibility/usedService/Api.java
new file mode 100644
index 000000000000..417e6f7a08f1
--- /dev/null
+++ b/java/java-tests/testData/inspection/java9Visibility/usedService/Api.java
@@ -0,0 +1,3 @@
+package foo.bar;
+
+public class Api {}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/java9Visibility/usedService/Impl.java b/java/java-tests/testData/inspection/java9Visibility/usedService/Impl.java
new file mode 100644
index 000000000000..a700ddc5ed2c
--- /dev/null
+++ b/java/java-tests/testData/inspection/java9Visibility/usedService/Impl.java
@@ -0,0 +1,4 @@
+package foo.bar.impl;
+import foo.bar Api;
+
+public class Impl extends Api {}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/java9Visibility/usedService/Other.java b/java/java-tests/testData/inspection/java9Visibility/usedService/Other.java
new file mode 100644
index 000000000000..5e7f2d1881ce
--- /dev/null
+++ b/java/java-tests/testData/inspection/java9Visibility/usedService/Other.java
@@ -0,0 +1,4 @@
+package foo.bar.impl;
+import foo.bar Api;
+
+public class Other extends Api {}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/java9Visibility/usedService/expected.xml b/java/java-tests/testData/inspection/java9Visibility/usedService/expected.xml
new file mode 100644
index 000000000000..161b0b37a534
--- /dev/null
+++ b/java/java-tests/testData/inspection/java9Visibility/usedService/expected.xml
@@ -0,0 +1,10 @@
+
+
+
+ Other.java
+ 4
+
+ Declaration access can be weaker
+ Can be package-private
+
+
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/AnnotateMethodTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/AnnotateMethodTest.java
index f49118c787f5..9ffde57cf7fe 100644
--- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/AnnotateMethodTest.java
+++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/AnnotateMethodTest.java
@@ -67,3 +67,16 @@ public class AnnotateMethodTest extends LightQuickFixTestCase {
return LanguageLevel.JDK_1_5;
}
}
+abstract class P2 {
+ @NotNull
+ String foo(@NotNull String p) {
+ return p;
+ }
+
+ Object o = new P2() {
+ @Override
+ String foo(String p) {
+ return "";
+ }
+ };
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/folding/JavaFoldingTest.groovy b/java/java-tests/testSrc/com/intellij/java/codeInsight/folding/JavaFoldingTest.groovy
index c4965f48891d..ce287323f6a5 100644
--- a/java/java-tests/testSrc/com/intellij/java/codeInsight/folding/JavaFoldingTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/folding/JavaFoldingTest.groovy
@@ -27,10 +27,10 @@ import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.editor.FoldRegion
import com.intellij.openapi.editor.ex.DocumentEx
import com.intellij.openapi.editor.ex.EditorEx
+import com.intellij.openapi.editor.ex.FoldingListener
import com.intellij.openapi.editor.ex.FoldingModelEx
import com.intellij.openapi.editor.impl.FoldingModelImpl
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider
-import com.intellij.openapi.util.registry.Registry
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiMethod
@@ -841,36 +841,6 @@ class Foo {
assertEquals 3, expandedFoldRegionsCount
}
- public void "test single line closure unfolds when converted to multiline"() {
- boolean oldValue = Registry.is("editor.durable.folding.state")
- try {
- Registry.get("editor.durable.folding.state").setValue(false)
-
- @Language("JAVA")
- def text = """
- class Foo {
- void m() {
- SwingUtilities.invokeLater(new Runnable() {
- @Override
- public void run() {
- System.out.println();
- }
- });
- }
- }
- """
- configure text
- assert myFixture.editor.foldingModel.getCollapsedRegionAtOffset(text.indexOf("new Runnable"))
- myFixture.editor.caretModel.moveToOffset(text.indexOf("System"))
- myFixture.performEditorAction(IdeActions.ACTION_EDITOR_ENTER)
- myFixture.doHighlighting()
- assert myFixture.editor.foldingModel.getCollapsedRegionAtOffset(text.indexOf("new Runnable")) == null
- }
- finally {
- Registry.get("editor.durable.folding.state").setValue(oldValue)
- }
- }
-
public void "test folding state is preserved for unchanged text in bulk mode"() {
@Language("JAVA")
def text = """
@@ -1083,6 +1053,37 @@ class Foo {
}
}
+ public void testGroupedFoldingsAreNotUpdatedOnUnrelatedDocumentChange() throws Exception {
+ configure """\
+class Foo {
+ void m() {
+ SwingUtilities.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ System.out.println();
+ }
+ });
+ }
+}
+"""
+ assertTopLevelFoldRegionsState "[FoldRegion +(56:143), placeholder='(Runnable) () → { ', FoldRegion +(164:188), placeholder=' }']"
+
+ (myFixture.editor.foldingModel as FoldingModelEx).addListener(new FoldingListener() {
+ @Override
+ void onFoldRegionStateChange(@NotNull FoldRegion region) {
+ fail "Unexpected fold region change"
+ }
+
+ @Override
+ void onFoldProcessingEnd() {
+ fail "Unexpected fold regions change"
+ }
+ }, myFixture.testRootDisposable)
+ myFixture.editor.caretModel.moveToOffset(myFixture.editor.document.text.indexOf("SwingUtilities"))
+ myFixture.type(' ')
+ myFixture.doHighlighting()
+ }
+
private void assertTopLevelFoldRegionsState(String expectedState) {
assertEquals(expectedState, myFixture.editor.foldingModel.toString())
}
diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/Java9VisibilityTest.kt b/java/java-tests/testSrc/com/intellij/java/codeInspection/Java9VisibilityTest.kt
index 3ff360804f72..ecd67d3e589d 100644
--- a/java/java-tests/testSrc/com/intellij/java/codeInspection/Java9VisibilityTest.kt
+++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/Java9VisibilityTest.kt
@@ -16,6 +16,7 @@
package com.intellij.java.codeInspection
import com.intellij.codeInspection.ex.GlobalInspectionToolWrapper
+import com.intellij.codeInspection.java19modules.Java9ModuleEntryPoint
import com.intellij.codeInspection.visibility.VisibilityInspection
import com.intellij.java.testFramework.fixtures.LightJava9ModulesCodeInsightFixtureTestCase
import com.intellij.openapi.application.ex.PathManagerEx
@@ -33,6 +34,21 @@ class Java9VisibilityTest : LightJava9ModulesCodeInsightFixtureTestCase() {
fun testInheritedService() = doTestService()
fun testProvidedService() = doTestService()
+ fun testUsedService() {
+ moduleInfo("module foo.bar { exports foo.bar; uses foo.bar.Api; uses foo.bar.impl.Impl; }")
+ doTest("foo.bar.Api", "foo.bar.impl.Impl", "foo.bar.impl.Other")
+ }
+
+ fun testReduceVisibilityInExportedPackages() {
+ moduleInfo("""module foo.bar {
+ exports foo.bar;
+ provides foo.bar.ServiceApi with foo.bar.ServiceImpl;
+ uses foo.bar.UsedService;
+}""")
+ doTest("foo.bar.Public", "foo.bar.ServiceApi", "foo.bar.ServiceImpl", "foo.bar.UsedService",
+ reduceVisibilityInExportedPackages = true)
+ }
+
private fun doTestClass() {
moduleInfo("module foo.bar { exports foo.bar; }")
doTest("foo.bar.Api", "foo.bar.impl.Impl")
@@ -43,11 +59,14 @@ class Java9VisibilityTest : LightJava9ModulesCodeInsightFixtureTestCase() {
doTest("foo.bar.Api", "foo.bar.impl.Impl", "foo.bar.impl.Other")
}
- private fun doTest(vararg classNames: String) {
+ private fun doTest(vararg classNames: String, reduceVisibilityInExportedPackages: Boolean = false) {
val testPath = testDataPath + getTestName(true)
addJavaFiles(testPath, classNames)
- val toolWrapper = GlobalInspectionToolWrapper(VisibilityInspection())
+ val inspection = VisibilityInspection()
+ inspection.setEntryPointEnabled(Java9ModuleEntryPoint.ID, reduceVisibilityInExportedPackages)
+
+ val toolWrapper = GlobalInspectionToolWrapper(inspection)
doGlobalInspectionTest(testPath, toolWrapper)
}
}
diff --git a/java/java-tests/testSrc/com/intellij/java/propertyBased/PsiIndexConsistencyTest.kt b/java/java-tests/testSrc/com/intellij/java/propertyBased/PsiIndexConsistencyTest.kt
index c6403e603d38..6d4249e42810 100644
--- a/java/java-tests/testSrc/com/intellij/java/propertyBased/PsiIndexConsistencyTest.kt
+++ b/java/java-tests/testSrc/com/intellij/java/propertyBased/PsiIndexConsistencyTest.kt
@@ -16,6 +16,7 @@
package com.intellij.java.propertyBased
import com.intellij.java.propertyBased.PsiIndexConsistencyTest.Action.*
+import com.intellij.lang.java.lexer.JavaLexer
import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.vfs.VfsUtil
@@ -55,7 +56,7 @@ class PsiIndexConsistencyTest: LightCodeInsightFixtureTestCase() {
10 to Generator.sampledFrom(*RefKind.values()).map { LoadRef(it) },
10 to Generator.sampledFrom(*RefKind.values()).map { ClearRef(it) },
5 to Generator.booleans().map { ChangeLanguageLevel(if (it) LanguageLevel.HIGHEST else LanguageLevel.JDK_1_3) },
- 5 to Generator.from { data -> TextChange(Generator.asciiIdentifiers().generateValue(data),
+ 5 to Generator.from { data -> TextChange(Generator.asciiIdentifiers().suchThat { !JavaLexer.isKeyword(it, LanguageLevel.HIGHEST) }.generateValue(data),
Generator.booleans().generateValue(data),
Generator.booleans().generateValue(data)) }
))
diff --git a/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/JavacReferenceCollectorListener.java b/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/JavacReferenceCollectorListener.java
index 5388f718a37e..4bf7a9ca4b11 100644
--- a/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/JavacReferenceCollectorListener.java
+++ b/jps/jps-builders-6/src/org/jetbrains/jps/javac/ast/JavacReferenceCollectorListener.java
@@ -34,6 +34,7 @@ import javax.lang.model.type.TypeMirror;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.*;
+import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -116,7 +117,7 @@ final class JavacReferenceCollectorListener implements TaskListener {
if (e.getKind() == TaskEvent.Kind.ANALYZE) {
// javac creates an event on each processed top level declared class not file
final CompilationUnitTree unit = e.getCompilationUnit();
- final String fileName = e.getSourceFile().toUri().getPath();
+ final String fileName = new File(e.getSourceFile().toUri().getPath()).getPath();
Tree declarationToProcess = myTreeUtility.getTree(e.getTypeElement());
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/internal/AssertionMethodImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/internal/AssertionMethodImpl.java
index ac8ca5eab391..c3e39f8c2106 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/internal/AssertionMethodImpl.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/internal/AssertionMethodImpl.java
@@ -16,14 +16,13 @@
package org.jetbrains.jps.incremental.instrumentation.internal;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.SystemInfo;
/*
A template for the synthetic method embedded by the bytecode instrumentation.
*/
class AssertionMethodImpl {
private static void assertArgumentIsSystemIndependent(String className, String methodName, String parameterName, String argument) {
- if (SystemInfo.isWindows && argument != null && argument.contains("\\")) {
+ if (argument != null && argument.indexOf('\\') > -1) {
String message = String.format("Argument for @SystemIndependent parameter '%s' of %s.%s must be system-independent: %s",
parameterName, className, methodName, argument);
diff --git a/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaAnnotatorChecker.java b/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaAnnotatorChecker.java
index 799ea2508ed9..0d9cfdaf76d9 100644
--- a/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaAnnotatorChecker.java
+++ b/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaAnnotatorChecker.java
@@ -26,6 +26,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.util.ObjectUtils;
import com.intellij.util.SmartList;
import com.intellij.util.ThreeState;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.jetbrains.jsonSchema.extension.JsonLikePsiWalker;
import com.jetbrains.jsonSchema.extension.adapters.JsonArrayValueAdapter;
@@ -43,6 +44,8 @@ import java.util.stream.Collectors;
* @author Irina.Chernushina on 4/25/2017.
*/
class JsonSchemaAnnotatorChecker {
+ private static final Set PRIMITIVE_TYPES =
+ ContainerUtil.set(JsonSchemaType._integer, JsonSchemaType._number, JsonSchemaType._boolean, JsonSchemaType._string, JsonSchemaType._null);
private final Map myErrors;
private boolean myHadTypeError;
@@ -351,13 +354,12 @@ class JsonSchemaAnnotatorChecker {
}
private static boolean areSchemaTypesCompatible(@NotNull final JsonSchemaObject schema, @NotNull final JsonSchemaType type) {
- if (getMatchingSchemaType(schema, type) != null) return true;
- if (schema.getEnum() != null && (JsonSchemaType._integer.equals(type) ||
- JsonSchemaType._number.equals(type) || JsonSchemaType._boolean.equals(type) ||
- JsonSchemaType._string.equals(type))) {
- return true;
+ if (schema.getEnum() != null) {
+ return PRIMITIVE_TYPES.contains(type);
}
- return false;
+ final JsonSchemaType matchingSchemaType = getMatchingSchemaType(schema, type);
+ if (matchingSchemaType != null) return matchingSchemaType.equals(type);
+ return true;
}
@Nullable
@@ -550,7 +552,7 @@ class JsonSchemaAnnotatorChecker {
private JsonSchemaObject processOneOf(@NotNull JsonValueAdapter value, List oneOf) {
final Map errors = new HashMap<>();
boolean wasTypeError = false;
- int cntCorrect = 0;
+ final List correct = new SmartList<>();
JsonSchemaObject current = null;
for (JsonSchemaObject object : oneOf) {
// skip it if something JS awaited, we do not process it currently
@@ -562,7 +564,7 @@ class JsonSchemaAnnotatorChecker {
if (checker.isCorrect()) {
current = object;
errors.clear();
- ++cntCorrect;
+ correct.add(object);
}
else {
if (errors.isEmpty() || wasTypeError && !checker.isHadTypeError() || errors.size() > checker.getErrors().size()) {
@@ -573,10 +575,15 @@ class JsonSchemaAnnotatorChecker {
}
}
}
- if (cntCorrect == 1) return current;
- if (cntCorrect > 0) {
+ if (correct.size() == 1) return current;
+ if (correct.size() > 0) {
final JsonSchemaType type = JsonSchemaType.getType(value);
- if (type != null) error("Validates to more than one variant", value.getDelegate());
+ if (type != null) {
+ // also check maybe some currently not checked properties like format are different with schemes
+ if (!schemesDifferWithNotCheckedProperties(correct)) {
+ error("Validates to more than one variant", value.getDelegate());
+ }
+ }
}
else {
if (!errors.isEmpty()) {
@@ -588,6 +595,10 @@ class JsonSchemaAnnotatorChecker {
return current;
}
+ private static boolean schemesDifferWithNotCheckedProperties(@NotNull final List list) {
+ return list.stream().anyMatch(s -> !StringUtil.isEmptyOrSpaces(s.getFormat()));
+ }
+
// returns the schema, selected for annotation
private JsonSchemaObject processAnyOf(@NotNull JsonValueAdapter value, List anyOf) {
final Map errors = new HashMap<>();
diff --git a/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaCompletionContributor.java b/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaCompletionContributor.java
index 749064ab01a6..8b0a752eef7e 100644
--- a/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaCompletionContributor.java
+++ b/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaCompletionContributor.java
@@ -22,6 +22,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.Consumer;
+import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.jsonSchema.extension.JsonLikePsiWalker;
import com.jetbrains.jsonSchema.extension.JsonSchemaFileProvider;
@@ -210,13 +211,13 @@ public class JsonSchemaCompletionContributor extends CompletionContributor {
}
private void addPropertyVariant(@NotNull String key, @NotNull JsonSchemaObject jsonSchemaObject, boolean hasValue, boolean insertComma) {
- final String description = jsonSchemaObject.getDescription();
- final String title = jsonSchemaObject.getTitle();
+ jsonSchemaObject = ObjectUtils.coalesce(ContainerUtil.getFirstItem(new JsonSchemaResolver(jsonSchemaObject).resolve()),
+ jsonSchemaObject);
key = !myWrapInQuotes ? key : StringUtil.wrapWithDoubleQuote(key);
LookupElementBuilder builder = LookupElementBuilder.create(key);
- String typeText = StringUtil.isEmpty(title) ? description : title;
- if (!StringUtil.isEmpty(typeText)) {
+ final String typeText = StringUtil.escapeXml(jsonSchemaObject.getDocumentation(true));
+ if (!StringUtil.isEmptyOrSpaces(typeText)) {
builder = builder.withTypeText(typeText, true);
}
diff --git a/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaDocumentationProvider.java b/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaDocumentationProvider.java
index c866e1e02346..b399cd843109 100644
--- a/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaDocumentationProvider.java
+++ b/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaDocumentationProvider.java
@@ -1,15 +1,11 @@
package com.jetbrains.jsonSchema.impl;
-import com.intellij.json.psi.JsonObject;
-import com.intellij.json.psi.JsonProperty;
-import com.intellij.json.psi.JsonStringLiteral;
-import com.intellij.json.psi.JsonValue;
import com.intellij.lang.documentation.DocumentationProvider;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
-import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.ObjectUtils;
import com.jetbrains.jsonSchema.extension.JsonLikePsiWalker;
import com.jetbrains.jsonSchema.ide.JsonSchemaService;
import org.jetbrains.annotations.NotNull;
@@ -23,7 +19,7 @@ public class JsonSchemaDocumentationProvider implements DocumentationProvider {
@Nullable
@Override
public String getQuickNavigateInfo(PsiElement element, PsiElement originalElement) {
- return null;
+ return findSchemaAndGenerateDoc(element, originalElement, true);
}
@Nullable
@@ -35,21 +31,24 @@ public class JsonSchemaDocumentationProvider implements DocumentationProvider {
@Nullable
@Override
public String generateDoc(PsiElement element, @Nullable PsiElement originalElement) {
+ return findSchemaAndGenerateDoc(element, originalElement, false);
+ }
+
+ @Nullable
+ private static String findSchemaAndGenerateDoc(PsiElement element, @Nullable PsiElement originalElement, final boolean preferShort) {
+ element = ObjectUtils.coalesce(originalElement, element);
final PsiFile containingFile = element.getContainingFile();
if (containingFile == null) return null;
final JsonSchemaService service = JsonSchemaService.Impl.get(element.getProject());
final JsonSchemaObject rootSchema = service.getSchemaObject(containingFile.getViewProvider().getVirtualFile());
if (rootSchema == null) return null;
- if (JsonSchemaService.isSchemaFile(containingFile)) {
- return generateForJsonSchemaFileType(element);
- }
- return generateDoc(element, rootSchema);
+ return generateDoc(element, rootSchema, preferShort);
}
@Nullable
public static String generateDoc(@NotNull final PsiElement element,
- @NotNull final JsonSchemaObject rootSchema) {
+ @NotNull final JsonSchemaObject rootSchema, final boolean preferShort) {
final JsonLikePsiWalker walker = JsonLikePsiWalker.getWalker(element, rootSchema);
if (walker == null) return null;
@@ -59,24 +58,8 @@ public class JsonSchemaDocumentationProvider implements DocumentationProvider {
final Collection schemas = new JsonSchemaResolver(rootSchema, true, position).resolve();
- return schemas.stream().filter(schema -> !StringUtil.isEmptyOrSpaces(schema.getDescription()))
- .findFirst().map(JsonSchemaObject::getDescription).orElse(null);
- }
-
- @Nullable
- private static String generateForJsonSchemaFileType(@NotNull PsiElement element) {
- final JsonProperty jsonProperty =
- element instanceof JsonProperty ? (JsonProperty)element : PsiTreeUtil.getParentOfType(element, JsonProperty.class);
- if (jsonProperty != null) {
- final JsonValue value = jsonProperty.getValue();
- if (value instanceof JsonObject) {
- final JsonProperty description = ((JsonObject)value).findProperty("description");
- if (description != null && description.getValue() instanceof JsonStringLiteral) {
- return StringUtil.escapeXml(StringUtil.unquoteString(description.getValue().getText()));
- }
- }
- }
- return null;
+ return StringUtil.escapeXml(schemas.stream().filter(schema -> !StringUtil.isEmptyOrSpaces(schema.getDocumentation(preferShort)))
+ .findFirst().map(schema -> schema.getDocumentation(preferShort)).orElse(null));
}
@Nullable
diff --git a/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaObject.java b/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaObject.java
index 6a413de23d00..b531bfe4a3e0 100644
--- a/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaObject.java
+++ b/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaObject.java
@@ -87,7 +87,7 @@ public class JsonSchemaObject {
// peer pointer is not merged!
public void mergeValues(JsonSchemaObject other) {
- // we do not copy id, schema, title and description
+ // we do not copy id, schema
myProperties.putAll(other.myProperties);
myDefinitionsMap = copyMap(myDefinitionsMap, other.myDefinitionsMap);
@@ -95,6 +95,9 @@ public class JsonSchemaObject {
other.myPatternProperties == null ? null : other.myPatternProperties.mySchemasMap);
myPatternProperties = map == null ? null : new PatternProperties(map);
+ if (!StringUtil.isEmptyOrSpaces(other.myTitle)) {
+ myTitle = other.myTitle;
+ }
if (!StringUtil.isEmptyOrSpaces(other.myDescription)) {
myDescription = other.myDescription;
}
@@ -548,6 +551,12 @@ public class JsonSchemaObject {
return current;
}
+ @Nullable
+ public String getDocumentation(final boolean preferShort) {
+ if (preferShort) return StringUtil.isEmptyOrSpaces(myTitle) ? myDescription : myTitle;
+ return StringUtil.isEmptyOrSpaces(myDescription) ? myTitle : myDescription;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaResolver.java b/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaResolver.java
index 169821a805cb..2f635c73dc09 100644
--- a/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaResolver.java
+++ b/json/src/com/jetbrains/jsonSchema/impl/JsonSchemaResolver.java
@@ -54,6 +54,7 @@ public class JsonSchemaResolver {
return MatchResult.create(node);
}
+ @NotNull
public Collection resolve() {
return resolve(false, false, false);
}
diff --git a/json/tests/test/com/jetbrains/jsonSchema/JsonBySchemaDocumentationBaseTest.java b/json/tests/test/com/jetbrains/jsonSchema/JsonBySchemaDocumentationBaseTest.java
index 191fa9ba56e2..1cd2dea2fa74 100644
--- a/json/tests/test/com/jetbrains/jsonSchema/JsonBySchemaDocumentationBaseTest.java
+++ b/json/tests/test/com/jetbrains/jsonSchema/JsonBySchemaDocumentationBaseTest.java
@@ -20,8 +20,10 @@ import com.intellij.json.JsonLanguage;
import com.intellij.lang.LanguageDocumentation;
import com.intellij.lang.documentation.DocumentationProvider;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.PsiUtilBase;
import com.jetbrains.jsonSchema.impl.JsonSchemaDocumentationProvider;
import org.jetbrains.annotations.NotNull;
+import org.junit.Assert;
import java.util.ArrayList;
@@ -52,7 +54,8 @@ public abstract class JsonBySchemaDocumentationBaseTest extends JsonSchemaHeavyA
@Override
public void doCheck() {
- PsiElement psiElement = DocumentationManager.getInstance(getProject()).findTargetElement(myEditor, myFile);
+ final PsiElement psiElement = PsiUtilBase.getElementAtCaret(myEditor);
+ Assert.assertNotNull(psiElement);
assertDocumentation(psiElement, psiElement, hasDoc);
}
});
@@ -65,6 +68,12 @@ public abstract class JsonBySchemaDocumentationBaseTest extends JsonSchemaHeavyA
protected void assertDocumentation(@NotNull PsiElement docElement, @NotNull PsiElement context, boolean shouldHaveDoc) {
DocumentationProvider documentationProvider = DocumentationManager.getProviderFromElement(context);
String inlineDoc = documentationProvider.generateDoc(docElement, context);
+ String quickNavigate = documentationProvider.getQuickNavigateInfo(docElement, context);
+ checkExpectedDoc(shouldHaveDoc, inlineDoc, false);
+ checkExpectedDoc(shouldHaveDoc, quickNavigate, true);
+ }
+
+ private void checkExpectedDoc(boolean shouldHaveDoc, String inlineDoc, boolean preferShort) {
if (shouldHaveDoc) {
assertNotNull("inline help is null", inlineDoc);
}
@@ -72,7 +81,7 @@ public abstract class JsonBySchemaDocumentationBaseTest extends JsonSchemaHeavyA
assertNull("inline help is not null", inlineDoc);
}
if (shouldHaveDoc) {
- assertSameLinesWithFile(getTestDataPath() + "/" + getTestName(true) + ".html", inlineDoc);
+ assertSameLinesWithFile(getTestDataPath() + "/" + getTestName(true) + (preferShort ? "_short.html" : ".html"), inlineDoc);
}
}
}
diff --git a/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaDocumentationTest.java b/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaDocumentationTest.java
index b7f47cb68571..88e69f8823ba 100644
--- a/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaDocumentationTest.java
+++ b/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaDocumentationTest.java
@@ -32,4 +32,12 @@ public class JsonSchemaDocumentationTest extends JsonBySchemaDocumentationBaseTe
public void testCheckEscaping() throws Exception {
doTest(true, "json");
}
+
+ public void testWithDefinition() throws Exception {
+ doTest(true, "json");
+ }
+
+ public void testWithTitleInDefinition() throws Exception {
+ doTest(true, "json");
+ }
}
diff --git a/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaHighlightingTest.java b/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaHighlightingTest.java
index 7ff84fa0126f..62763ba31810 100644
--- a/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaHighlightingTest.java
+++ b/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaHighlightingTest.java
@@ -305,8 +305,8 @@ public class JsonSchemaHighlightingTest extends DaemonAnalyzerTestCase {
final String subSchema1 = "{\"enum\": [1,2,3,4,5]}";
final String subSchema2 = "{\"type\": \"array\", \"items\": {\"properties\": {\"kilo\": {}}, \"additionalProperties\": false}}";
final String schema = "{\"properties\": {\"prop\": {\"oneOf\": [" + subSchema1 + ", " + subSchema2 + "]}}}";
- doTest(schema, "{\"prop\": [{\"kilo\": 20}]}");
- doTest(schema, "{\"prop\": 5}");
+ //doTest(schema, "{\"prop\": [{\"kilo\": 20}]}");
+ //doTest(schema, "{\"prop\": 5}");
doTest(schema, "{\"prop\": [{\"foxtrot\": 15, \"kilo\": 20}]}");
}
@@ -512,6 +512,45 @@ public class JsonSchemaHighlightingTest extends DaemonAnalyzerTestCase {
doTest(schema, "{\"not_type\": \"4a4\"}");
}
+ public void testDoNotMarkOneOfThatDiffersWithFormat() throws Exception {
+ final String schema = "{\n" +
+ "\n" +
+ " \"properties\": {\n" +
+ " \"withFormat\": {\n" +
+ " \"type\": \"string\"," +
+ " \"oneOf\": [\n" +
+ " {\n" +
+ " \"format\":\"hostname\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"format\": \"ip4\"\n" +
+ " }\n" +
+ " ]\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+ doTest(schema, "{\"withFormat\": \"localhost\"}");
+ }
+
+ public void testAcceptSchemaWithoutType() throws Exception {
+ final String schema = "{\n" +
+ "\n" +
+ " \"properties\": {\n" +
+ " \"withFormat\": {\n" +
+ " \"oneOf\": [\n" +
+ " {\n" +
+ " \"format\":\"hostname\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"format\": \"ip4\"\n" +
+ " }\n" +
+ " ]\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+ doTest(schema, "{\"withFormat\": \"localhost\"}");
+ }
+
public static String rootObjectRedefinedSchema() {
return "{\n" +
" \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n" +
diff --git a/json/tests/test/com/jetbrains/jsonSchema/impl/JsonBySchemaCompletionTest.java b/json/tests/test/com/jetbrains/jsonSchema/impl/JsonBySchemaCompletionTest.java
index fe2072a64959..631165f20686 100644
--- a/json/tests/test/com/jetbrains/jsonSchema/impl/JsonBySchemaCompletionTest.java
+++ b/json/tests/test/com/jetbrains/jsonSchema/impl/JsonBySchemaCompletionTest.java
@@ -1,7 +1,9 @@
package com.jetbrains.jsonSchema.impl;
+import com.intellij.codeInsight.lookup.LookupElementPresentation;
import com.jetbrains.jsonSchema.JsonSchemaHighlightingTest;
import org.jetbrains.annotations.NotNull;
+import org.junit.Assert;
/**
* @author Irina.Chernushina on 10/1/2015.
@@ -157,6 +159,47 @@ public class JsonBySchemaCompletionTest extends JsonBySchemaCompletionBaseTest {
testImpl(schema, "{\"null\": }", "false", "null", "true");
}
+ public void testDescriptionFromDefinitionInCompletion() throws Exception {
+ final String schema = "{\n" +
+ " \"definitions\": {\n" +
+ " \"target\": {\n" +
+ " \"description\": \"Target description\"\n" +
+ " }\n" +
+ " },\n" +
+ " \"properties\": {\n" +
+ " \"source\": {\n" +
+ " \"$ref\": \"#/definitions/target\"\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+ testImpl(schema, "{}", "\"source\"");
+ Assert.assertEquals(1, myItems.length);
+ final LookupElementPresentation presentation = new LookupElementPresentation();
+ myItems[0].renderElement(presentation);
+ Assert.assertEquals("Target description", presentation.getTypeText());
+ }
+
+ public void testDescriptionFromTitleInCompletion() throws Exception {
+ final String schema = "{\n" +
+ " \"definitions\": {\n" +
+ " \"target\": {\n" +
+ " \"title\": \"Target title\",\n" +
+ " \"description\": \"Target description\"\n" +
+ " }\n" +
+ " },\n" +
+ " \"properties\": {\n" +
+ " \"source\": {\n" +
+ " \"$ref\": \"#/definitions/target\"\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+ testImpl(schema, "{}", "\"source\"");
+ Assert.assertEquals(1, myItems.length);
+ final LookupElementPresentation presentation = new LookupElementPresentation();
+ myItems[0].renderElement(presentation);
+ Assert.assertEquals("Target title", presentation.getTypeText());
+ }
+
@NotNull
private static String parcelShopSchema() {
return "{\n" +
diff --git a/json/tests/testData/jsonSchema/documentation/checkEscaping_short.html b/json/tests/testData/jsonSchema/documentation/checkEscaping_short.html
new file mode 100644
index 000000000000..c73fc4ac3bd3
--- /dev/null
+++ b/json/tests/testData/jsonSchema/documentation/checkEscaping_short.html
@@ -0,0 +1 @@
+Disallows /// <reference path=> imports (use ES6-style imports instead)
\ No newline at end of file
diff --git a/json/tests/testData/jsonSchema/documentation/secondLevel_short.html b/json/tests/testData/jsonSchema/documentation/secondLevel_short.html
new file mode 100644
index 000000000000..888aa3fb0ae8
--- /dev/null
+++ b/json/tests/testData/jsonSchema/documentation/secondLevel_short.html
@@ -0,0 +1 @@
+my second level property description 1
\ No newline at end of file
diff --git a/json/tests/testData/jsonSchema/documentation/simple_short.html b/json/tests/testData/jsonSchema/documentation/simple_short.html
new file mode 100644
index 000000000000..c4941ce9e4db
--- /dev/null
+++ b/json/tests/testData/jsonSchema/documentation/simple_short.html
@@ -0,0 +1 @@
+my property description 1
\ No newline at end of file
diff --git a/json/tests/testData/jsonSchema/documentation/withDefinition.html b/json/tests/testData/jsonSchema/documentation/withDefinition.html
new file mode 100644
index 000000000000..d4bcb21909aa
--- /dev/null
+++ b/json/tests/testData/jsonSchema/documentation/withDefinition.html
@@ -0,0 +1 @@
+Description found through definition
\ No newline at end of file
diff --git a/json/tests/testData/jsonSchema/documentation/withDefinition.json b/json/tests/testData/jsonSchema/documentation/withDefinition.json
new file mode 100644
index 000000000000..67cd5bfb5990
--- /dev/null
+++ b/json/tests/testData/jsonSchema/documentation/withDefinition.json
@@ -0,0 +1,3 @@
+{
+ "source": {}
+}
\ No newline at end of file
diff --git a/json/tests/testData/jsonSchema/documentation/withDefinitionSchema.json b/json/tests/testData/jsonSchema/documentation/withDefinitionSchema.json
new file mode 100644
index 000000000000..12ca74daad47
--- /dev/null
+++ b/json/tests/testData/jsonSchema/documentation/withDefinitionSchema.json
@@ -0,0 +1,12 @@
+{
+ "definitions": {
+ "target": {
+ "description": "Description found through definition"
+ }
+ },
+ "properties": {
+ "source": {
+ "$ref": "#/definitions/target"
+ }
+ }
+}
\ No newline at end of file
diff --git a/json/tests/testData/jsonSchema/documentation/withDefinition_short.html b/json/tests/testData/jsonSchema/documentation/withDefinition_short.html
new file mode 100644
index 000000000000..d4bcb21909aa
--- /dev/null
+++ b/json/tests/testData/jsonSchema/documentation/withDefinition_short.html
@@ -0,0 +1 @@
+Description found through definition
\ No newline at end of file
diff --git a/json/tests/testData/jsonSchema/documentation/withTitleInDefinition.html b/json/tests/testData/jsonSchema/documentation/withTitleInDefinition.html
new file mode 100644
index 000000000000..d4bcb21909aa
--- /dev/null
+++ b/json/tests/testData/jsonSchema/documentation/withTitleInDefinition.html
@@ -0,0 +1 @@
+Description found through definition
\ No newline at end of file
diff --git a/json/tests/testData/jsonSchema/documentation/withTitleInDefinition.json b/json/tests/testData/jsonSchema/documentation/withTitleInDefinition.json
new file mode 100644
index 000000000000..67cd5bfb5990
--- /dev/null
+++ b/json/tests/testData/jsonSchema/documentation/withTitleInDefinition.json
@@ -0,0 +1,3 @@
+{
+ "source": {}
+}
\ No newline at end of file
diff --git a/json/tests/testData/jsonSchema/documentation/withTitleInDefinitionSchema.json b/json/tests/testData/jsonSchema/documentation/withTitleInDefinitionSchema.json
new file mode 100644
index 000000000000..7995bfeb9710
--- /dev/null
+++ b/json/tests/testData/jsonSchema/documentation/withTitleInDefinitionSchema.json
@@ -0,0 +1,13 @@
+{
+ "definitions": {
+ "target": {
+ "title": "Title found through definition",
+ "description": "Description found through definition"
+ }
+ },
+ "properties": {
+ "source": {
+ "$ref": "#/definitions/target"
+ }
+ }
+}
\ No newline at end of file
diff --git a/json/tests/testData/jsonSchema/documentation/withTitleInDefinition_short.html b/json/tests/testData/jsonSchema/documentation/withTitleInDefinition_short.html
new file mode 100644
index 000000000000..3fc51fb08d52
--- /dev/null
+++ b/json/tests/testData/jsonSchema/documentation/withTitleInDefinition_short.html
@@ -0,0 +1 @@
+Title found through definition
\ No newline at end of file
diff --git a/lib/asm-all.jar b/lib/asm-all.jar
index a64a5929acec..6680557b43c8 100644
Binary files a/lib/asm-all.jar and b/lib/asm-all.jar differ
diff --git a/lib/src/asm-src.zip b/lib/src/asm-src.zip
index 427668e85d24..60b1005fcfb4 100644
Binary files a/lib/src/asm-src.zip and b/lib/src/asm-src.zip differ
diff --git a/platform/annotations/internal/annotations-internal.iml b/platform/annotations/internal/annotations-internal.iml
deleted file mode 100644
index c90834f2d607..000000000000
--- a/platform/annotations/internal/annotations-internal.iml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/TestingTasks.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/TestingTasks.groovy
index 114eb6daadac..30a8df45a371 100644
--- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/TestingTasks.groovy
+++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/TestingTasks.groovy
@@ -17,6 +17,9 @@ package org.jetbrains.intellij.build
import groovy.transform.CompileStatic
import org.jetbrains.intellij.build.impl.TestingTasksImpl
+
+import java.util.function.Predicate
+
/**
* @author nik
*/
@@ -26,7 +29,7 @@ abstract class TestingTasks {
* @param defaultMainModule main module to be used instead of {@link TestingOptions#mainModule} if it isn't specified
* @param excludedSourceDirectory if not {@code null} tests from modules which sources are located under this directory will be skipped
*/
- abstract void runTests(List additionalJvmOptions, String defaultMainModule, String excludedSourceDirectory)
+ abstract void runTests(List additionalJvmOptions, String defaultMainModule, Predicate rootExcludeCondition)
static TestingTasks create(CompilationContext context, TestingOptions options = new TestingOptions()) {
return new TestingTasksImpl(context, options)
diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.groovy
index 1ff5f96b5e7a..296b77d38c8b 100644
--- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.groovy
+++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/DistributionJARsBuilder.groovy
@@ -111,7 +111,6 @@ class DistributionJARsBuilder {
}
withModule("util")
withModule("util-rt", "util.jar")
- withModule("annotations-internal", "util.jar")
withModule("annotations")
withModule("annotations-common", "annotations.jar")
withModule("extensions")
diff --git a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/TestingTasksImpl.groovy b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/TestingTasksImpl.groovy
index c5ccb8cce72f..dbe1b35f56d4 100644
--- a/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/TestingTasksImpl.groovy
+++ b/platform/build-scripts/groovy/org/jetbrains/intellij/build/impl/TestingTasksImpl.groovy
@@ -15,7 +15,6 @@
*/
package org.jetbrains.intellij.build.impl
-import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.FileUtilRt
import groovy.transform.CompileDynamic
import groovy.transform.CompileStatic
@@ -28,6 +27,7 @@ import org.jetbrains.intellij.build.TestingTasks
import org.jetbrains.jps.model.module.JpsModule
import org.jetbrains.jps.util.JpsPathUtil
+import java.util.function.Predicate
/**
* @author nik
*/
@@ -42,7 +42,7 @@ class TestingTasksImpl extends TestingTasks {
}
@Override
- void runTests(List additionalJvmOptions, String defaultMainModule, String excludedSourceDirectory) {
+ void runTests(List additionalJvmOptions, String defaultMainModule, Predicate rootExcludeCondition) {
def compilationTasks = CompilationTasks.create(context)
if (options.mainModule != null) {
compilationTasks.compileModules(["tests_bootstrap"], [options.mainModule])
@@ -108,11 +108,11 @@ class TestingTasksImpl extends TestingTasks {
systemProperties[key.substring("pass.".length())] = value
}
}
-
- if (excludedSourceDirectory != null) {
+
+ if (rootExcludeCondition != null) {
List excludedModules = context.project.modules.findAll {
List contentRoots = it.contentRootsList.urls
- !contentRoots.isEmpty() && FileUtil.isAncestor(new File(excludedSourceDirectory), JpsPathUtil.urlToFile(contentRoots.first()), false)
+ !contentRoots.isEmpty() && rootExcludeCondition.test(JpsPathUtil.urlToFile(contentRoots.first()))
}
List excludedRoots = excludedModules.collectMany {
[context.projectBuilder.moduleOutput(it), context.projectBuilder.moduleTestsOutput(it)]
diff --git a/platform/configuration-store-impl/src/ModuleStateStorageManager.kt b/platform/configuration-store-impl/src/ModuleStateStorageManager.kt
index 4ad610170681..ab0ef074018f 100644
--- a/platform/configuration-store-impl/src/ModuleStateStorageManager.kt
+++ b/platform/configuration-store-impl/src/ModuleStateStorageManager.kt
@@ -25,7 +25,6 @@ import com.intellij.openapi.project.ProjectBundle
import com.intellij.openapi.project.isExternalStorageEnabled
import com.intellij.openapi.vfs.newvfs.events.VFileEvent
import com.intellij.util.LineSeparator
-import com.intellij.util.io.systemIndependentPath
import com.intellij.util.loadElement
import org.jdom.Element
import java.io.FileNotFoundException
@@ -87,7 +86,7 @@ internal class ModuleStateStorageManager(macroSubstitutor: TrackingPathMacroSubs
override fun createFileBasedStorage(path: String, collapsedPath: String, roamingType: RoamingType, rootTagName: String?): StateStorage
= ModuleFileStorage(this, Paths.get(path), collapsedPath, rootTagName, roamingType, getMacroSubstitutor(collapsedPath), if (roamingType == RoamingType.DISABLED) null else compoundStreamProvider)
- private class ModuleFileStorage(storageManager: StateStorageManagerImpl,
+ private class ModuleFileStorage(storageManager: ModuleStateStorageManager,
file: Path,
fileSpec: String,
rootElementName: String?,
@@ -100,8 +99,8 @@ internal class ModuleStateStorageManager(macroSubstitutor: TrackingPathMacroSubs
val virtualFile = virtualFile
if (virtualFile == null || !virtualFile.exists()) {
// only on first load
- if (storageDataRef.get() == null) {
- throw FileNotFoundException(ProjectBundle.message("module.file.does.not.exist.error", file.systemIndependentPath))
+ if (storageDataRef.get() == null && !storageManager.isExternalSystemStorageEnabled) {
+ throw FileNotFoundException(ProjectBundle.message("module.file.does.not.exist.error", file.toString()))
}
else {
return null
diff --git a/platform/configuration-store-impl/src/StateStorageManagerImpl.kt b/platform/configuration-store-impl/src/StateStorageManagerImpl.kt
index 288b7307a6ff..aa1e617e8547 100644
--- a/platform/configuration-store-impl/src/StateStorageManagerImpl.kt
+++ b/platform/configuration-store-impl/src/StateStorageManagerImpl.kt
@@ -318,7 +318,7 @@ open class StateStorageManagerImpl(private val rootTagName: String,
}
}
- protected open val isExternalSystemStorageEnabled: Boolean
+ open val isExternalSystemStorageEnabled: Boolean
get() = false
protected open fun beforeElementSaved(element: Element) {
diff --git a/platform/core-api/src/com/intellij/openapi/vfs/VirtualFileVisitor.java b/platform/core-api/src/com/intellij/openapi/vfs/VirtualFileVisitor.java
index 686404162c83..2ac10887d7f5 100644
--- a/platform/core-api/src/com/intellij/openapi/vfs/VirtualFileVisitor.java
+++ b/platform/core-api/src/com/intellij/openapi/vfs/VirtualFileVisitor.java
@@ -82,13 +82,13 @@ public abstract class VirtualFileVisitor {
private boolean myFollowSymLinks = true;
- private boolean mySkipRoot = false;
+ private boolean mySkipRoot;
private int myDepthLimit = -1;
private Map> myVisitedTargets;
- private int myLevel = 0;
- private Stack myValueStack = null;
- private T myValue = null;
+ private int myLevel;
+ private Stack myValueStack;
+ private T myValue;
protected VirtualFileVisitor(@NotNull Option... options) {
for (Option option : options) {
diff --git a/platform/core-api/src/com/intellij/util/AbstractQuery.java b/platform/core-api/src/com/intellij/util/AbstractQuery.java
index 8f55163dcb6a..1589ceaae4e7 100644
--- a/platform/core-api/src/com/intellij/util/AbstractQuery.java
+++ b/platform/core-api/src/com/intellij/util/AbstractQuery.java
@@ -42,6 +42,7 @@ public abstract class AbstractQuery implements Query {
return result;
}
+ @NotNull
@Override
public Iterator iterator() {
assertNotProcessing();
diff --git a/platform/core-api/src/com/intellij/util/ExecutorsQuery.java b/platform/core-api/src/com/intellij/util/ExecutorsQuery.java
index fda929cc77ab..91ee040fb5d8 100644
--- a/platform/core-api/src/com/intellij/util/ExecutorsQuery.java
+++ b/platform/core-api/src/com/intellij/util/ExecutorsQuery.java
@@ -46,10 +46,7 @@ public final class ExecutorsQuery extends AbstractQuery extends Iterable {
/**
- * Get all of the results in the {@link java.util.Collection}
+ * Get all of the results in the {@link Collection}
* @return results in a collection or empty collection if no results found.
*/
@NotNull
diff --git a/platform/annotations/internal/src/org/jetbrains/annotations/SystemDependent.java b/platform/core-api/src/org/jetbrains/annotations/SystemDependent.java
similarity index 100%
rename from platform/annotations/internal/src/org/jetbrains/annotations/SystemDependent.java
rename to platform/core-api/src/org/jetbrains/annotations/SystemDependent.java
diff --git a/platform/annotations/internal/src/org/jetbrains/annotations/SystemIndependent.java b/platform/core-api/src/org/jetbrains/annotations/SystemIndependent.java
similarity index 100%
rename from platform/annotations/internal/src/org/jetbrains/annotations/SystemIndependent.java
rename to platform/core-api/src/org/jetbrains/annotations/SystemIndependent.java
diff --git a/platform/core-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorBase.java b/platform/core-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorBase.java
index d74c7c2b50ba..10bca4f54152 100644
--- a/platform/core-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorBase.java
+++ b/platform/core-impl/src/com/intellij/openapi/progress/util/AbstractProgressIndicatorBase.java
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.progress.util;
+import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.TransactionGuard;
@@ -25,13 +26,16 @@ import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.impl.CoreProgressManager;
+import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.ui.mac.foundation.MacUtil;
+import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.DoubleArrayList;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.Set;
@@ -127,15 +131,23 @@ public class AbstractProgressIndicatorBase extends UserDataHolderBase implements
@Override
public void checkCanceled() {
if (isCanceled() && isCancelable()) {
- throw new ProcessCanceledException();
+ throw new ProcessCanceledException(getDisposeTrace());
}
if (CoreProgressManager.runCheckCanceledHooks(this)) {
if (isCanceled() && isCancelable()) {
- throw new ProcessCanceledException();
+ throw new ProcessCanceledException(getDisposeTrace());
}
}
}
+ @Nullable
+ private Throwable getDisposeTrace() {
+ if (this instanceof Disposable) {
+ return ObjectUtils.tryCast(Disposer.getTree().getDisposalInfo((Disposable)this), Throwable.class);
+ }
+ return null;
+ }
+
@Override
public void setText(final String text) {
myText = text;
diff --git a/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFileManagerImpl.java b/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFileManagerImpl.java
index e05d8fbe0f09..38d8da323df6 100644
--- a/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFileManagerImpl.java
+++ b/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFileManagerImpl.java
@@ -85,8 +85,11 @@ public class VirtualFileManagerImpl extends VirtualFileManagerEx {
public VirtualFileSystem getFileSystem(@Nullable String protocol) {
if (protocol == null) return null;
List systems = myCollector.forKey(protocol);
- if (systems.isEmpty()) return null;
- LOG.assertTrue(systems.size() == 1);
+ int size = systems.size();
+ if (size == 0) return null;
+ if (size > 1) {
+ LOG.error(protocol + ": " + systems);
+ }
return systems.get(0);
}
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/ExternalSystemModulePropertyManager.kt b/platform/external-system-api/src/com/intellij/openapi/externalSystem/ExternalSystemModulePropertyManager.kt
index 1d530169b7f2..20405cf42062 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/ExternalSystemModulePropertyManager.kt
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/ExternalSystemModulePropertyManager.kt
@@ -15,95 +15,166 @@
*/
package com.intellij.openapi.externalSystem
+import com.intellij.openapi.components.PersistentStateComponent
+import com.intellij.openapi.components.State
import com.intellij.openapi.externalSystem.model.ProjectSystemId
import com.intellij.openapi.externalSystem.model.project.ModuleData
import com.intellij.openapi.externalSystem.model.project.ProjectData
-import com.intellij.openapi.externalSystem.util.ExternalSystemConstants
-import com.intellij.openapi.externalSystem.util.ExternalSystemConstants.EXTERNAL_SYSTEM_ID_KEY
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleServiceManager
+import com.intellij.openapi.project.isExternalStorageEnabled
import com.intellij.openapi.roots.ExternalProjectSystemRegistry
-
-private const val EXTERNAL_SYSTEM_MODULE_GROUP_KEY = "external.system.module.group"
-private const val LINKED_PROJECT_PATH_KEY = "external.linked.project.path"
-private const val LINKED_PROJECT_ID_KEY = "external.linked.project.id"
-private const val EXTERNAL_SYSTEM_MODULE_TYPE_KEY = "external.system.module.type"
-private const val EXTERNAL_SYSTEM_MODULE_VERSION_KEY = "external.system.module.version"
-private const val ROOT_PROJECT_PATH_KEY = "external.root.project.path"
+import com.intellij.openapi.roots.ProjectModelElement
+import com.intellij.util.xmlb.annotations.Attribute
+import com.intellij.util.xmlb.annotations.Transient
+import kotlin.properties.ReadWriteProperty
+import kotlin.reflect.KProperty
@Suppress("DEPRECATION")
-class ExternalSystemModulePropertyManager(private val module: Module) {
+@State(name = "ExternalSystem")
+class ExternalSystemModulePropertyManager(module: Module) : PersistentStateComponent, ProjectModelElement {
+ override fun getExternalSource() = store.externalSystem?.let { ExternalProjectSystemRegistry.getInstance().getSourceById(it) }
+
+ private var store = if (module.project.isExternalStorageEnabled) ExternalOptionStateComponent() else ExternalOptionStateModule(module)
+
+ override fun getState() = store as? ExternalOptionStateComponent
+
+ override fun loadState(state: ExternalOptionStateComponent) {
+ store = state
+ }
+
companion object {
@JvmStatic
fun getInstance(module: Module) = ModuleServiceManager.getService(module, ExternalSystemModulePropertyManager::class.java)!!
}
@Suppress("DEPRECATION")
- fun getExternalSystemId() = module.getOptionValue(EXTERNAL_SYSTEM_ID_KEY)
+ fun getExternalSystemId() = store.externalSystem
- fun getExternalModuleType() = module.getOptionValue(EXTERNAL_SYSTEM_MODULE_TYPE_KEY)
+ fun getExternalModuleType() = store.externalSystemModuleType
- fun getExternalModuleVersion() = module.getOptionValue(EXTERNAL_SYSTEM_MODULE_VERSION_KEY)
+ fun getExternalModuleVersion() = store.externalSystemModuleVersion
- fun getExternalModuleGroup() = module.getOptionValue(EXTERNAL_SYSTEM_MODULE_GROUP_KEY)
+ fun getExternalModuleGroup() = store.externalSystemModuleGroup
- fun getLinkedProjectId() = module.getOptionValue(LINKED_PROJECT_ID_KEY)
+ fun getLinkedProjectId() = store.linkedProjectId
- fun getRootProjectPath() = module.getOptionValue(ROOT_PROJECT_PATH_KEY)
+ fun getRootProjectPath() = store.rootProjectPath
- fun getLinkedProjectPath() = module.getOptionValue(LINKED_PROJECT_PATH_KEY)
+ fun getLinkedProjectPath() = store.linkedProjectPath
@Suppress("DEPRECATION")
- fun isMavenized() = "true" == module.getOptionValue(ExternalProjectSystemRegistry.IS_MAVEN_MODULE_KEY)
+ fun isMavenized() = store.isMavenized
@Suppress("DEPRECATION")
fun setMavenized(mavenized: Boolean) {
- module.setOption(ExternalProjectSystemRegistry.IS_MAVEN_MODULE_KEY, if (mavenized) "true" else null)
-
- if (!mavenized) {
- return
+ if (mavenized) {
+ // clear external system API options
+ // see com.intellij.openapi.externalSystem.service.project.manage.ModuleDataService#setModuleOptions
+ unlinkExternalOptions()
}
-
- // clear external system API options
- // see com.intellij.openapi.externalSystem.service.project.manage.ModuleDataService#setModuleOptions
- module.setOption(EXTERNAL_SYSTEM_ID_KEY, null)
- module.setOption(LINKED_PROJECT_PATH_KEY, null)
- module.setOption(ROOT_PROJECT_PATH_KEY, null)
- module.setOption(EXTERNAL_SYSTEM_MODULE_GROUP_KEY, null)
- module.setOption(EXTERNAL_SYSTEM_MODULE_VERSION_KEY, null)
+ // must be after unlinkExternalOptions
+ store.isMavenized = mavenized
}
fun unlinkExternalOptions() {
- module.setOption(ExternalSystemConstants.EXTERNAL_SYSTEM_ID_KEY, null)
- module.setOption(LINKED_PROJECT_ID_KEY, null)
- module.setOption(LINKED_PROJECT_PATH_KEY, null)
- module.setOption(ROOT_PROJECT_PATH_KEY, null)
- module.setOption(EXTERNAL_SYSTEM_MODULE_GROUP_KEY, null)
- module.setOption(EXTERNAL_SYSTEM_MODULE_VERSION_KEY, null)
+ store.externalSystem = null
+ store.linkedProjectId = null
+ store.linkedProjectPath = null
+ store.rootProjectPath = null
+ store.externalSystemModuleGroup = null
+ store.externalSystemModuleVersion = null
}
fun setExternalOptions(id: ProjectSystemId, moduleData: ModuleData, projectData: ProjectData?) {
- module.setOption(ExternalSystemConstants.EXTERNAL_SYSTEM_ID_KEY, id.toString())
- module.setOption(LINKED_PROJECT_ID_KEY, moduleData.id)
- module.setOption(LINKED_PROJECT_PATH_KEY, moduleData.linkedExternalProjectPath)
- module.setOption(ROOT_PROJECT_PATH_KEY, projectData?.linkedExternalProjectPath ?: "")
+ // clear maven option, must be first
+ store.isMavenized = false
- module.setOption(EXTERNAL_SYSTEM_MODULE_GROUP_KEY, moduleData.group)
- module.setOption(EXTERNAL_SYSTEM_MODULE_VERSION_KEY, moduleData.version)
+ store.externalSystem = id.toString()
+ store.linkedProjectId = moduleData.id
+ store.linkedProjectPath = moduleData.linkedExternalProjectPath
+ store.rootProjectPath = projectData?.linkedExternalProjectPath ?: ""
- // clear maven option
- module.setOption(ExternalProjectSystemRegistry.IS_MAVEN_MODULE_KEY, null)
+ store.externalSystemModuleGroup = moduleData.group
+ store.externalSystemModuleVersion = moduleData.version
}
fun setExternalId(id: ProjectSystemId) {
- module.setOption(EXTERNAL_SYSTEM_ID_KEY, id.id)
+ store.externalSystem = id.id
}
fun setExternalModuleType(type: String?) {
- module.setOption(EXTERNAL_SYSTEM_MODULE_TYPE_KEY, type)
+ store.externalSystemModuleType = type
}
fun setLinkedProjectId(projectId: String) {
- module.setOption(LINKED_PROJECT_ID_KEY, projectId)
+ store.linkedProjectId = projectId
}
+}
+
+private interface ExternalOptionState {
+ var externalSystem: String?
+ var externalSystemModuleVersion: String?
+
+ var linkedProjectPath: String?
+ var linkedProjectId: String?
+ var rootProjectPath: String?
+
+ var externalSystemModuleGroup: String?
+ var externalSystemModuleType: String?
+
+ var isMavenized: Boolean
+}
+
+@Suppress("DEPRECATION")
+private class ModuleOptionDelegate(private val key: String) : ReadWriteProperty {
+ override operator fun getValue(thisRef: ExternalOptionStateModule, property: KProperty<*>) = thisRef.module.getOptionValue(key)
+
+ override operator fun setValue(thisRef: ExternalOptionStateModule, property: KProperty<*>, value: String?) {
+ thisRef.module.setOption(key, value)
+ }
+}
+
+@Suppress("DEPRECATION")
+private class ExternalOptionStateModule(internal val module: Module) : ExternalOptionState {
+ override var externalSystem by ModuleOptionDelegate(ExternalProjectSystemRegistry.EXTERNAL_SYSTEM_ID_KEY)
+ override var externalSystemModuleVersion by ModuleOptionDelegate("external.system.module.version")
+ override var externalSystemModuleGroup by ModuleOptionDelegate("external.system.module.group")
+ override var externalSystemModuleType by ModuleOptionDelegate("external.system.module.type")
+
+ override var linkedProjectPath by ModuleOptionDelegate("external.linked.project.path")
+ override var linkedProjectId by ModuleOptionDelegate("external.linked.project.id")
+
+ override var rootProjectPath by ModuleOptionDelegate("external.root.project.path")
+
+ override var isMavenized: Boolean
+ get() = "true" == module.getOptionValue(ExternalProjectSystemRegistry.IS_MAVEN_MODULE_KEY)
+ set(value) {
+ module.setOption(ExternalProjectSystemRegistry.IS_MAVEN_MODULE_KEY, if (value) "true" else null)
+ }
+}
+
+class ExternalOptionStateComponent : ExternalOptionState {
+ @get:Attribute
+ override var externalSystem: String? = null
+ @get:Attribute
+ override var externalSystemModuleVersion: String? = null
+ @get:Attribute
+ override var externalSystemModuleGroup: String? = null
+ @get:Attribute
+ override var externalSystemModuleType: String? = null
+
+ @get:Attribute
+ override var linkedProjectPath: String? = null
+ @get:Attribute
+ override var linkedProjectId: String? = null
+ @get:Attribute
+ override var rootProjectPath: String? = null
+
+ @get:Transient
+ override var isMavenized: Boolean
+ get() = externalSystem == ExternalProjectSystemRegistry.MAVEN_EXTERNAL_SOURCE_ID
+ set(value) {
+ externalSystem = if (value) ExternalProjectSystemRegistry.MAVEN_EXTERNAL_SOURCE_ID else null
+ }
}
\ No newline at end of file
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/configurationStore/ExternalSystemStorage.kt b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/configurationStore/ExternalSystemStorage.kt
index f87802fe7072..e4cb512a9f3c 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/configurationStore/ExternalSystemStorage.kt
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/configurationStore/ExternalSystemStorage.kt
@@ -22,7 +22,6 @@ import com.intellij.configurationStore.XmlElementStorage
import com.intellij.openapi.components.RoamingType
import com.intellij.openapi.components.StateSplitterEx
import com.intellij.openapi.components.StoragePathMacros
-import com.intellij.openapi.externalSystem.ExternalSystemModulePropertyManager
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.JDOMUtil
@@ -36,16 +35,11 @@ internal class ExternalModuleStorage(private val module: Module, storageManager:
override fun createSaveSession(states: StateMap) = object : XmlElementStorageSaveSession(states, this) {
override fun saveLocally(element: Element?) {
// our customizeStorageSpecs on write will not return our storage for not applicable module, so, we don't need to check it here
- var name = module.name
- if (ExternalSystemModulePropertyManager.getInstance(module).isMavenized()) {
- // to distinguish because one project can contain modules from different external systems
- name += "@maven"
- }
if (element == null) {
- manager.moduleStorage.remove(name)
+ manager.moduleStorage.remove(module.name)
}
else {
- manager.moduleStorage.write(name, element)
+ manager.moduleStorage.write(module.name, element)
}
}
}
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/model/internal/InternalExternalProjectInfo.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/model/internal/InternalExternalProjectInfo.java
index 3d2a1cf3f87c..e7f7ca9b23b7 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/model/internal/InternalExternalProjectInfo.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/model/internal/InternalExternalProjectInfo.java
@@ -61,6 +61,11 @@ public class InternalExternalProjectInfo implements ExternalProjectInfo, Seriali
return myExternalProjectPath;
}
+ @Nullable
+ public String getNullSafeExternalProjectPath() {
+ return myExternalProjectPath;
+ }
+
@Override
@Nullable
public DataNode getExternalProjectStructure() {
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsDataStorage.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsDataStorage.java
index 97bcc853f59b..17456ace75f4 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsDataStorage.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsDataStorage.java
@@ -104,7 +104,10 @@ public class ExternalProjectsDataStorage implements SettingsSavingComponent, Per
}
}
else {
- markDirty(projectInfo.getExternalProjectPath());
+ String projectPath = projectInfo.getNullSafeExternalProjectPath();
+ if (projectPath != null) {
+ markDirty(projectPath);
+ }
}
}
}
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManagerImpl.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManagerImpl.java
index bb768b947438..993995985eb7 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManagerImpl.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsManagerImpl.java
@@ -18,6 +18,7 @@ package com.intellij.openapi.externalSystem.service.project.manage;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.*;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.ExternalSystemManager;
import com.intellij.openapi.externalSystem.importing.ImportSpec;
import com.intellij.openapi.externalSystem.model.DataNode;
@@ -33,8 +34,12 @@ import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
import com.intellij.openapi.externalSystem.view.ExternalProjectsView;
import com.intellij.openapi.externalSystem.view.ExternalProjectsViewImpl;
import com.intellij.openapi.externalSystem.view.ExternalProjectsViewState;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectFileStoreOptionManager;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.impl.ModuleRootManagerImpl;
import com.intellij.openapi.util.Disposer;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
@@ -57,6 +62,8 @@ import static com.intellij.openapi.externalSystem.model.ProjectKeys.TASK;
*/
@State(name = "ExternalProjectsManager", storages = {@Storage(StoragePathMacros.WORKSPACE_FILE)})
public class ExternalProjectsManagerImpl implements ExternalProjectsManager, PersistentStateComponent, Disposable, ProjectFileStoreOptionManager {
+ private static final Logger LOG = Logger.getInstance(ExternalProjectsManager.class);
+
private final AtomicBoolean isInitializationFinished = new AtomicBoolean();
private final AtomicBoolean isInitializationStarted = new AtomicBoolean();
private final CompositeRunnable myPostInitializationActivities = new CompositeRunnable();
@@ -91,6 +98,17 @@ public class ExternalProjectsManagerImpl implements ExternalProjectsManager, Per
public void setStoreExternally(boolean value) {
myState.storeExternally = value;
+ // force re-save
+ try {
+ for (Module module : ModuleManager.getInstance(myProject).getModules()) {
+ if (!module.isDisposed()) {
+ ((ModuleRootManagerImpl)ModuleRootManager.getInstance(module)).stateChanged();
+ }
+ }
+ }
+ catch (Exception e) {
+ LOG.warn(e);
+ }
}
@NotNull
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsState.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsState.java
index c1ef849a637e..867f93f6c67a 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsState.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ExternalProjectsState.java
@@ -64,6 +64,7 @@ public class ExternalProjectsState {
return new TaskActivationState();
}
+ @NotNull
@Override
protected Map createMap() {
return new LinkedHashMap<>();
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalProjectSettingsControl.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalProjectSettingsControl.java
index b87b035e3615..b02342dd32bb 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalProjectSettingsControl.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalProjectSettingsControl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2017 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.
@@ -80,6 +80,7 @@ public abstract class AbstractExternalProjectSettingsControl settings = ContainerUtilRt.newArrayList(s.getLinkedProjectsSettings());
myProjectsList.setVisibleRowCount(Math.max(3, Math.min(5, settings.size())));
- ContainerUtil.sort(settings,
- (s1, s2) -> getProjectName(s1.getExternalProjectPath()).compareTo(getProjectName(s2.getExternalProjectPath())));
+ ContainerUtil.sort(settings, Comparator.comparing(s2 -> getProjectName(s2.getExternalProjectPath())));
myProjectSettingsControls.clear();
for (ProjectSettings setting : settings) {
diff --git a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/configurationStore/ExternalSystemStorageTest.kt b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/configurationStore/ExternalSystemStorageTest.kt
index 4d322f3339ff..b7986315ead1 100644
--- a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/configurationStore/ExternalSystemStorageTest.kt
+++ b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/configurationStore/ExternalSystemStorageTest.kt
@@ -16,12 +16,15 @@
package com.intellij.openapi.externalSystem.configurationStore
import com.intellij.configurationStore.ESCAPED_MODULE_DIR
-import com.intellij.configurationStore.IS_EXTERNAL_STORAGE_ENABLED
import com.intellij.configurationStore.createModule
import com.intellij.configurationStore.useAndDispose
import com.intellij.openapi.externalSystem.ExternalSystemModulePropertyManager
import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsDataStorage
+import com.intellij.openapi.externalSystem.service.project.manage.ExternalProjectsManagerImpl
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.ModuleRootModificationUtil
+import com.intellij.openapi.roots.impl.ModuleRootManagerImpl
import com.intellij.testFramework.*
import com.intellij.testFramework.assertions.Assertions.assertThat
import com.intellij.util.io.delete
@@ -47,7 +50,7 @@ class ExternalSystemStorageTest {
@Suppress("unused")
@JvmField
@Rule
- val ruleChain = RuleChain(tempDirManager, EdtRule(), ActiveStoreRule(projectRule), DisposeModulesRule(projectRule), ExternalStorageRule())
+ val ruleChain = RuleChain(tempDirManager, EdtRule(), ActiveStoreRule(projectRule), DisposeModulesRule(projectRule), ExternalStorageRule(projectRule.project))
@Test
fun `must be empty if external system storage`() {
@@ -74,16 +77,19 @@ class ExternalSystemStorageTest {
""")
ExternalSystemModulePropertyManager.getInstance(this).setMavenized(true)
+ // force re-save: this call not in the setMavenized because ExternalSystemModulePropertyManager in the API (since in production we have the only usage, it is ok for now)
+ (ModuleRootManager.getInstance(this) as ModuleRootManagerImpl).stateChanged()
assertThat(cacheDir).doesNotExist()
saveStore()
assertThat(cacheDir).isDirectory
assertThat(moduleFile).isEqualTo("""
- """)
+ """)
- assertThat(cacheDir.resolve("test@maven.xml")).isEqualTo("""
+ assertThat(cacheDir.resolve("test.xml")).isEqualTo("""
+
@@ -94,15 +100,16 @@ class ExternalSystemStorageTest {
}
}
-private class ExternalStorageRule : TestRule {
+private class ExternalStorageRule(private val project: Project) : TestRule {
override fun apply(base: Statement, description: Description): Statement {
return statement {
+ val manager = ExternalProjectsManagerImpl.getInstance(project)
try {
- IS_EXTERNAL_STORAGE_ENABLED = true
+ manager.setStoreExternally(true)
base.evaluate()
}
finally {
- IS_EXTERNAL_STORAGE_ENABLED = false
+ manager.setStoreExternally(false)
}
}
}
diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java b/platform/indexing-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java
index 0b1d597c67a8..d4e1ac91aa26 100644
--- a/platform/indexing-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java
+++ b/platform/indexing-impl/src/com/intellij/psi/impl/file/impl/ResolveScopeManagerImpl.java
@@ -49,6 +49,7 @@ public class ResolveScopeManagerImpl extends ResolveScopeManager {
private final Map myDefaultResolveScopesCache = new FactoryMap() {
+ @NotNull
@Override
protected Map createMap() {
return ContainerUtil.createConcurrentWeakKeySoftValueMap();
diff --git a/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java b/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java
index 827cce9db74d..1052ba973f20 100644
--- a/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java
+++ b/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java
@@ -39,13 +39,12 @@ import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import javax.swing.*;
import java.awt.*;
import java.util.Comparator;
public class PsiUtilBase extends PsiUtilCore implements PsiEditorUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.util.PsiUtilBase");
- public static final Comparator LANGUAGE_COMPARATOR = (o1, o2) -> o1.getID().compareTo(o2.getID());
+ public static final Comparator LANGUAGE_COMPARATOR = Comparator.comparing(Language::getID);
public static boolean isUnderPsiRoot(PsiFile root, PsiElement element) {
PsiFile containingFile = element.getContainingFile();
@@ -74,10 +73,7 @@ public class PsiUtilBase extends PsiUtilCore implements PsiEditorUtil {
Language lang = findLanguageFromElement(elt);
if (caret.hasSelection()) {
- final Language rangeLanguage = evaluateLanguageInRange(caret.getSelectionStart(), caret.getSelectionEnd(), file);
- if (rangeLanguage == null) return file.getLanguage();
-
- lang = rangeLanguage;
+ lang = evaluateLanguageInRange(caret.getSelectionStart(), caret.getSelectionEnd(), file);
}
return narrowLanguage(lang, file.getLanguage());
@@ -152,8 +148,8 @@ public class PsiUtilBase extends PsiUtilCore implements PsiEditorUtil {
return narrowLanguage(lang, file.getLanguage());
}
- @Nullable
- public static Language evaluateLanguageInRange(final int start, final int end, @NotNull PsiFile file) {
+ @NotNull
+ private static Language evaluateLanguageInRange(final int start, final int end, @NotNull PsiFile file) {
PsiElement elt = getElementAtOffset(file, start);
TextRange selectionRange = new TextRange(start, end);
@@ -195,7 +191,7 @@ public class PsiUtilBase extends PsiUtilCore implements PsiEditorUtil {
*
*
* Please don't use this method for finding an editor for quick fix.
- * @see {@link com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement}
+ * @see com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement
*
* @param element target element
* @return editor that works with a given element if the one is found; {@code null} otherwise
@@ -221,17 +217,15 @@ public class PsiUtilBase extends PsiUtilCore implements PsiEditorUtil {
}
}
}
- if (SwingUtilities.isEventDispatchThread()) {
- // We assume that data context from focus-based retrieval should success if performed from EDT.
- AsyncResult asyncResult = DataManager.getInstance().getDataContextFromFocus();
- if (asyncResult.isDone()) {
- Editor editor = CommonDataKeys.EDITOR.getData(asyncResult.getResult());
- if (editor != null) {
- Document cachedDocument = PsiDocumentManager.getInstance(project).getCachedDocument(psiFile);
- // Ensure that target editor is found by checking its document against the one from given PSI element.
- if (cachedDocument == editor.getDocument()) {
- return editor;
- }
+ // We assume that data context from focus-based retrieval should success if performed from EDT.
+ AsyncResult asyncResult = DataManager.getInstance().getDataContextFromFocus();
+ if (asyncResult.isDone()) {
+ Editor editor = CommonDataKeys.EDITOR.getData(asyncResult.getResult());
+ if (editor != null) {
+ Document cachedDocument = PsiDocumentManager.getInstance(project).getCachedDocument(psiFile);
+ // Ensure that target editor is found by checking its document against the one from given PSI element.
+ if (cachedDocument == editor.getDocument()) {
+ return editor;
}
}
}
diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/fonts/AppEditorFontConfigurable.java b/platform/lang-impl/src/com/intellij/application/options/editor/fonts/AppEditorFontConfigurable.java
index 399cc8f7212f..2ebc48203cde 100644
--- a/platform/lang-impl/src/com/intellij/application/options/editor/fonts/AppEditorFontConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/application/options/editor/fonts/AppEditorFontConfigurable.java
@@ -21,6 +21,7 @@ import com.intellij.openapi.editor.colors.EditorFontCache;
import com.intellij.openapi.editor.colors.FontPreferences;
import com.intellij.openapi.editor.colors.impl.AppEditorFontOptions;
import com.intellij.openapi.editor.colors.impl.EditorColorsManagerImpl;
+import com.intellij.openapi.options.Configurable.NoScroll;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.util.Disposer;
@@ -31,7 +32,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-public class AppEditorFontConfigurable implements SearchableConfigurable {
+public class AppEditorFontConfigurable implements SearchableConfigurable, NoScroll {
public static final String ID = "editor.preferences.fonts.default";
private LazyInstance myFontPanelInstance = new LazyInstance() {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java
index 8ffd4276239e..7b7bc8753c1e 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/UpdateFoldRegionsOperation.java
@@ -29,8 +29,8 @@ import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
-import com.intellij.openapi.util.registry.Registry;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.SmartPointerManager;
@@ -62,6 +62,7 @@ class UpdateFoldRegionsOperation implements Runnable {
private final ApplyDefaultStateMode myApplyDefaultState;
private final FoldingMap myElementsToFoldMap = new FoldingMap();
private final Set myRegionInfos = new LinkedHashSet<>();
+ private final MultiMap myGroupedRegionInfos = new MultiMap<>();
private final boolean myKeepCollapsedRegions;
private final boolean myForInjected;
@@ -81,6 +82,8 @@ class UpdateFoldRegionsOperation implements Runnable {
for (FoldingUpdate.RegionInfo regionInfo : elementsToFold) {
myElementsToFoldMap.putValue(regionInfo.element, regionInfo);
myRegionInfos.add(regionInfo);
+ FoldingGroup group = regionInfo.descriptor.getGroup();
+ if (group != null) myGroupedRegionInfos.putValue(group, regionInfo);
}
}
@@ -192,62 +195,60 @@ class UpdateFoldRegionsOperation implements Runnable {
@NotNull FoldingModelEx foldingModel,
@NotNull Map rangeToExpandStatusMap) {
List toRemove = new ArrayList<>();
- InjectedLanguageManager injectedManager = InjectedLanguageManager.getInstance(myProject);
+ Ref infoRef = Ref.create();
+ Set processedGroups = new HashSet<>();
+ List matchedInfos = new ArrayList<>();
for (FoldRegion region : foldingModel.getAllFoldRegions()) {
- boolean forceKeepRegion = myKeepCollapsedRegions && region.isValid() && !region.isExpanded() &&
- !regionOrGroupCanBeRemovedWhenCollapsed(region);
- Boolean storedCollapsedByDefault = region.getUserData(COLLAPSED_BY_DEFAULT);
- PsiElement element = info.getPsiElement(region);
- if (element != null) {
- PsiFile containingFile = element.getContainingFile();
- boolean isInjected = injectedManager.isInjectedFragment(containingFile);
- if (isInjected != myForInjected) continue;
+ FoldingGroup group = region.getGroup();
+ if (group != null && !processedGroups.add(group)) continue;
+
+ List regionsToProcess = group == null ? Collections.singletonList(region) : foldingModel.getGroupedRegions(group);
+ matchedInfos.clear();
+ boolean shouldRemove = false;
+ for (FoldRegion regionToProcess : regionsToProcess) {
+ if (shouldRemoveRegion(regionToProcess, info, rangeToExpandStatusMap, infoRef)) {
+ shouldRemove = true;
+ }
+ FoldingUpdate.RegionInfo regionInfo = infoRef.get();
+ matchedInfos.add(regionInfo);
}
- final Collection regionInfos;
- if (element != null && !(regionInfos = myElementsToFoldMap.get(element)).isEmpty()) {
- boolean matchingDescriptorFound = false;
- FoldingUpdate.RegionInfo[] array = regionInfos.toArray(new FoldingUpdate.RegionInfo[regionInfos.size()]);
- for (FoldingUpdate.RegionInfo regionInfo : array) {
- FoldingDescriptor descriptor = regionInfo.descriptor;
- TextRange range = descriptor.getRange();
- if (TextRange.areSegmentsEqual(region, range)) {
- matchingDescriptorFound = true;
- if (!forceKeepRegion && (!region.isValid() ||
- region.getGroup() != null ||
- descriptor.getGroup() != null ||
- !region.getPlaceholderText().equals(descriptor.getPlaceholderText()) ||
- range.getLength() < 2)
- ) {
- rangeToExpandStatusMap.put(range, region.isExpanded());
- toRemove.add(region);
- break;
- }
- else if (storedCollapsedByDefault != null && storedCollapsedByDefault != regionInfo.collapsedByDefault) {
- rangeToExpandStatusMap.put(range, !regionInfo.collapsedByDefault);
- toRemove.add(region);
- break;
- }
- else {
- myElementsToFoldMap.remove(element, regionInfo);
- myRegionInfos.remove(regionInfo);
- }
+ if (!shouldRemove && group != null) {
+ FoldingGroup requestedGroup = null;
+ for (FoldingUpdate.RegionInfo matchedInfo : matchedInfos) {
+ if (matchedInfo == null) {
+ shouldRemove = true;
+ break;
+ }
+ FoldingGroup g = matchedInfo.descriptor.getGroup();
+ if (g == null) {
+ shouldRemove = true;
+ break;
+ }
+ if (requestedGroup == null) {
+ requestedGroup = g;
+ }
+ else if (!requestedGroup.equals(g)) {
+ shouldRemove = true;
+ break;
}
}
- if (!matchingDescriptorFound && !forceKeepRegion) {
- if (Registry.is("editor.durable.folding.state")) {
- for (FoldingUpdate.RegionInfo regionInfo : regionInfos) {
- rangeToExpandStatusMap.put(regionInfo.descriptor.getRange(), region.isExpanded());
- }
- }
- toRemove.add(region);
+ if (myGroupedRegionInfos.get(requestedGroup).size() != matchedInfos.size()) {
+ shouldRemove = true;
+ }
+ }
+ if (shouldRemove) {
+ for (FoldRegion r : regionsToProcess) {
+ rangeToExpandStatusMap.putIfAbsent(TextRange.create(r), r.isExpanded());
}
+ toRemove.addAll(regionsToProcess);
}
- else if (region.isValid() && info.isLightRegion(region)) {
- boolean isExpanded = region.isExpanded();
- rangeToExpandStatusMap.put(TextRange.create(region), isExpanded);
- }
- else if (!forceKeepRegion) {
- toRemove.add(region);
+ else {
+ for (FoldingUpdate.RegionInfo matchedInfo : matchedInfos) {
+ if (matchedInfo != null) {
+ myElementsToFoldMap.remove(matchedInfo.element, matchedInfo);
+ myRegionInfos.remove(matchedInfo);
+ }
+ }
}
}
@@ -257,6 +258,54 @@ class UpdateFoldRegionsOperation implements Runnable {
}
}
+ private boolean shouldRemoveRegion(FoldRegion region, EditorFoldingInfo info,
+ Map rangeToExpandStatusMap, Ref matchingInfo) {
+ matchingInfo.set(null);
+ PsiElement element = info.getPsiElement(region);
+ if (element != null) {
+ PsiFile containingFile = element.getContainingFile();
+ boolean isInjected = InjectedLanguageManager.getInstance(myProject).isInjectedFragment(containingFile);
+ if (isInjected != myForInjected) return false;
+ }
+ boolean forceKeepRegion = myKeepCollapsedRegions && region.isValid() && !region.isExpanded() &&
+ !regionOrGroupCanBeRemovedWhenCollapsed(region);
+ Boolean storedCollapsedByDefault = region.getUserData(COLLAPSED_BY_DEFAULT);
+ final Collection regionInfos;
+ if (element != null && !(regionInfos = myElementsToFoldMap.get(element)).isEmpty()) {
+ FoldingUpdate.RegionInfo[] array = regionInfos.toArray(new FoldingUpdate.RegionInfo[regionInfos.size()]);
+ for (FoldingUpdate.RegionInfo regionInfo : array) {
+ FoldingDescriptor descriptor = regionInfo.descriptor;
+ TextRange range = descriptor.getRange();
+ if (TextRange.areSegmentsEqual(region, range)) {
+ if (!forceKeepRegion && (!region.isValid() ||
+ !region.getPlaceholderText().equals(descriptor.getPlaceholderText()) ||
+ range.getLength() < 2)
+ ) {
+ return true;
+ }
+ else if (storedCollapsedByDefault != null && storedCollapsedByDefault != regionInfo.collapsedByDefault) {
+ rangeToExpandStatusMap.put(range, !regionInfo.collapsedByDefault);
+ return true;
+ }
+ else {
+ matchingInfo.set(regionInfo);
+ return false;
+ }
+ }
+ }
+ if (!forceKeepRegion) {
+ for (FoldingUpdate.RegionInfo regionInfo : regionInfos) {
+ rangeToExpandStatusMap.put(regionInfo.descriptor.getRange(), region.isExpanded());
+ }
+ return true;
+ }
+ }
+ else if (!forceKeepRegion && !(region.isValid() && info.isLightRegion(region))) {
+ return true;
+ }
+ return false;
+ }
+
private boolean regionOrGroupCanBeRemovedWhenCollapsed(FoldRegion region) {
FoldingGroup group = region.getGroup();
List affectedRegions = group != null && myEditor instanceof EditorEx
diff --git a/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java
index 90ada3845f1c..750c51f9d1df 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java
@@ -82,6 +82,7 @@ public class ConsoleHistoryController {
/** @noinspection MismatchedQueryAndUpdateOfCollection*/
private final static FactoryMap ourModels = new FactoryMap() {
+ @NotNull
@Override
protected Map createMap() {
return ContainerUtil.createConcurrentWeakValueMap();
diff --git a/platform/lang-impl/src/com/intellij/execution/lineMarker/RunLineMarkerContributor.java b/platform/lang-impl/src/com/intellij/execution/lineMarker/RunLineMarkerContributor.java
index c85a98b1ec94..ba804cfbe6bd 100644
--- a/platform/lang-impl/src/com/intellij/execution/lineMarker/RunLineMarkerContributor.java
+++ b/platform/lang-impl/src/com/intellij/execution/lineMarker/RunLineMarkerContributor.java
@@ -15,10 +15,15 @@
*/
package com.intellij.execution.lineMarker;
+import com.intellij.execution.TestStateStorage;
+import com.intellij.execution.testframework.TestIconMapper;
+import com.intellij.execution.testframework.sm.runner.states.TestStateInfo;
+import com.intellij.icons.AllIcons;
import com.intellij.ide.DataManager;
import com.intellij.lang.LanguageExtension;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.impl.SimpleDataContext;
+import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -74,4 +79,22 @@ public abstract class RunLineMarkerContributor {
return presentation.isEnabled() && presentation.isVisible() ? presentation.getText() : null;
}
+ protected static Icon getTestStateIcon(String url, Project project, boolean isClass) {
+ TestStateStorage.Record state = TestStateStorage.getInstance(project).getState(url);
+ if (state != null) {
+ TestStateInfo.Magnitude magnitude = TestIconMapper.getMagnitude(state.magnitude);
+ if (magnitude != null) {
+ switch (magnitude) {
+ case ERROR_INDEX:
+ case FAILED_INDEX:
+ return AllIcons.RunConfigurations.TestState.Red2;
+ case PASSED_INDEX:
+ case COMPLETE_INDEX:
+ return AllIcons.RunConfigurations.TestState.Green2;
+ default:
+ }
+ }
+ }
+ return isClass ? AllIcons.RunConfigurations.TestState.Run_run : AllIcons.RunConfigurations.TestState.Run;
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java b/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java
index c0fe923f9e4c..e0ef589cd2ef 100644
--- a/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java
+++ b/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java
@@ -58,7 +58,6 @@ import com.intellij.usages.rules.UsageInFile;
import com.intellij.util.AdapterProcessor;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.*;
@@ -491,8 +490,8 @@ public class ReplaceInProjectManager {
return true;
}
- private void replaceUsagesUnderCommand(@NotNull final ReplaceContext replaceContext, @Nullable final Set usagesSet) {
- if (usagesSet == null) {
+ private void replaceUsagesUnderCommand(@NotNull final ReplaceContext replaceContext, @NotNull final Set usagesSet) {
+ if (usagesSet.isEmpty()) {
return;
}
diff --git a/platform/lang-impl/src/com/intellij/ide/hierarchy/ExporterToTextFileHierarchy.java b/platform/lang-impl/src/com/intellij/ide/hierarchy/ExporterToTextFileHierarchy.java
index 85a50b10e060..5095aa645704 100644
--- a/platform/lang-impl/src/com/intellij/ide/hierarchy/ExporterToTextFileHierarchy.java
+++ b/platform/lang-impl/src/com/intellij/ide/hierarchy/ExporterToTextFileHierarchy.java
@@ -58,13 +58,12 @@ class ExporterToTextFileHierarchy implements ExporterToTextFile {
}
private void appendNode(StringBuilder buf, DefaultMutableTreeNode node, String lineSeparator, String indent) {
- buf.append(indent);
final String childIndent;
if (node.getParent() != null) {
childIndent = indent + " ";
final HierarchyNodeDescriptor descriptor = myHierarchyBrowserBase.getDescriptor(node);
if (descriptor != null) {
- buf.append(descriptor.getHighlightedText().getText()).append(lineSeparator);
+ buf.append(indent).append(descriptor.getHighlightedText().getText()).append(lineSeparator);
}
}
else {
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java
index 5ccdd2e85c2b..5c678abaef17 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java
@@ -106,6 +106,8 @@ import java.awt.*;
import java.util.*;
import java.util.List;
+import static com.intellij.ide.projectView.impl.StatisticsKt.triggerProjectViewPane;
+
@State(name = "ProjectView", storages = @Storage(StoragePathMacros.WORKSPACE_FILE))
public class ProjectViewImpl extends ProjectView implements PersistentStateComponent, Disposable, QuickActionProvider, BusyObject {
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.projectView.impl.ProjectViewImpl");
@@ -546,7 +548,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
@Override
public void selectionChanged(ContentManagerEvent event) {
if (event.getOperation() == ContentManagerEvent.ContentOperation.add) {
- viewSelectionChanged();
+ viewSelectionChanged(true);
}
}
});
@@ -575,6 +577,10 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
private boolean viewSelectionChanged() {
+ return viewSelectionChanged(false);
+ }
+
+ private boolean viewSelectionChanged(boolean fromContentManager) {
Content content = getContentManager().getSelectedContent();
if (content == null) return false;
final String id = content.getUserData(ID_KEY);
@@ -584,6 +590,9 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
if (newPane == null) return false;
newPane.setSubId(subId);
showPane(newPane);
+ if (fromContentManager) {
+ triggerProjectViewPane(myCurrentViewId, myCurrentViewSubId);
+ }
ProjectViewSelectInTarget target = getProjectViewSelectInTarget(newPane);
if (target != null) target.setSubId(subId);
if (isAutoscrollFromSource(id)) {
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/statistics.kt b/platform/lang-impl/src/com/intellij/ide/projectView/impl/statistics.kt
new file mode 100644
index 000000000000..bb42b146c88b
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/statistics.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2017 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.ide.projectView.impl
+
+import com.intellij.internal.statistic.UsageTrigger
+import com.intellij.internal.statistic.beans.ConvertUsagesUtil.ensureProperKey
+
+private val prefix = "project.view.pane"
+
+internal fun triggerProjectViewPane(id: String?, subId: String?) {
+ if (id == null) return
+ val featureString = if (subId == null) "$prefix.$id" else "$prefix.$id.$subId"
+ val key = ensureProperKey(featureString)
+ UsageTrigger.trigger(key)
+}
diff --git a/platform/lang-impl/src/com/intellij/mock/MockFileManager.java b/platform/lang-impl/src/com/intellij/mock/MockFileManager.java
index 04848c280611..f293f7d2f160 100644
--- a/platform/lang-impl/src/com/intellij/mock/MockFileManager.java
+++ b/platform/lang-impl/src/com/intellij/mock/MockFileManager.java
@@ -39,6 +39,7 @@ public class MockFileManager implements FileManager {
// in mock tests it's LightVirtualFile, they're only alive when they're referenced,
// and there can not be several instances representing the same file
private final FactoryMap myViewProviders = new ConcurrentWeakFactoryMap() {
+ @NotNull
@Override
protected Map createMap() {
return ContainerUtil.createConcurrentWeakKeyWeakValueMap();
diff --git a/java/java-impl/src/com/intellij/refactoring/actions/RenameFileAction.java b/platform/lang-impl/src/com/intellij/refactoring/actions/RenameFileAction.java
similarity index 86%
rename from java/java-impl/src/com/intellij/refactoring/actions/RenameFileAction.java
rename to platform/lang-impl/src/com/intellij/refactoring/actions/RenameFileAction.java
index 56d07e1985a5..c7c04f4d0ae9 100644
--- a/java/java-impl/src/com/intellij/refactoring/actions/RenameFileAction.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/actions/RenameFileAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2017 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.
@@ -19,9 +19,9 @@ import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiClassOwner;
import com.intellij.psi.PsiFile;
import com.intellij.refactoring.rename.PsiElementRenameHandler;
+import org.jetbrains.annotations.NotNull;
/**
* @author ven
@@ -48,8 +48,8 @@ public class RenameFileAction extends AnAction implements DumbAware {
PsiFile file = e.getData(CommonDataKeys.PSI_FILE);
Presentation presentation = e.getPresentation();
String place = e.getPlace();
- boolean enabled = file != null &&
- (file instanceof PsiClassOwner || !ActionPlaces.PROJECT_VIEW_POPUP.equals(place)) &&
+ boolean enabled = file != null &&
+ (enabledInProjectView(file) || !ActionPlaces.PROJECT_VIEW_POPUP.equals(place)) &&
place != ActionPlaces.EDITOR_POPUP && e.getData(CommonDataKeys.PROJECT) != null;
presentation.setEnabled(enabled);
presentation.setVisible(enabled);
@@ -58,4 +58,8 @@ public class RenameFileAction extends AnAction implements DumbAware {
presentation.setDescription("Rename selected file");
}
}
+
+ protected boolean enabledInProjectView(@NotNull PsiFile file) {
+ return true;
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
index 69ab2b03a203..32673635d193 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
@@ -318,6 +318,12 @@ public class FileBasedIndexImpl extends FileBasedIndex implements BaseComponent,
started = System.nanoTime();
myStateFuture = IndexInfrastructure.submitGenesisTask(new FileIndexDataInitialization(extensions));
+ IndexInfrastructure.submitGenesisTask(() -> {
+ if (!myShutdownPerformed.get()) {
+ myChangedFilesCollector.ensureUpToDateAsync();
+ }
+ return null;
+ });
LOG.info("Index scheduled:" + (System.nanoTime() - started) / 1000000);
if (!IndexInfrastructure.ourDoAsyncIndicesInitialization) {
waitUntilIndicesAreInitialized();
@@ -2381,8 +2387,6 @@ public class FileBasedIndexImpl extends FileBasedIndex implements BaseComponent,
}
});
myInitialized = true; // this will ensure that all changes to component's state will be visible to other threads
-
- myChangedFilesCollector.ensureUpToDateAsync();
}
}
}
diff --git a/platform/platform-api/src/com/intellij/ui/UI.java b/platform/platform-api/src/com/intellij/ui/UI.java
index 1aaba6a8b35a..731022af83df 100644
--- a/platform/platform-api/src/com/intellij/ui/UI.java
+++ b/platform/platform-api/src/com/intellij/ui/UI.java
@@ -40,6 +40,7 @@ public class UI {
ourColors.put("panel.custom.background", new Color(250, 249, 245));
ourColors.put("link.foreground", new Color(82, 99, 155));
+ ourColors.put("link.hover.foreground", new JBColor(new Color(82, 99, 155), new Color(82, 99, 155)));
ourColors.put("link.pressed.foreground", new JBColor(new Color(240, 0, 0), new Color(186, 111, 37)));
ourColors.put("link.visited.foreground", new JBColor(new Color(128, 0, 128), new Color(151, 118, 169)));
@@ -73,7 +74,7 @@ public class UI {
}
public static Color getColor(@NonNls String id) {
- if (UIUtil.isUnderDarcula()) {
+ if (UIUtil.isUnderDarcula() || UIUtil.isUnderWin10LookAndFeel()) {
final Color color = UIManager.getColor(id);
if (color != null) {
return color;
diff --git a/platform/platform-api/src/com/intellij/ui/components/labels/LinkLabel.java b/platform/platform-api/src/com/intellij/ui/components/labels/LinkLabel.java
index f7bc0a94b7c4..d6f116895dc7 100644
--- a/platform/platform-api/src/com/intellij/ui/components/labels/LinkLabel.java
+++ b/platform/platform-api/src/com/intellij/ui/components/labels/LinkLabel.java
@@ -216,7 +216,9 @@ public class LinkLabel extends JLabel {
}
protected Color getTextColor() {
- return myIsLinkActive ? getActive() : isVisited() ? getVisited() : getNormal();
+ return myIsLinkActive ? getActive() :
+ myUnderline ? getHover() :
+ isVisited() ? getVisited() : getNormal();
}
public void setPaintUnderline(boolean paintUnderline) {
@@ -317,6 +319,10 @@ public class LinkLabel extends JLabel {
return UI.getColor("link.foreground");
}
+ protected Color getHover() {
+ return UI.getColor("link.hover.foreground");
+ }
+
public void entered(MouseEvent e) {
enableUnderline();
}
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJComboBoxUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJComboBoxUI.java
index 95c5cc2cf76e..436f44021293 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJComboBoxUI.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJComboBoxUI.java
@@ -19,7 +19,6 @@ import com.intellij.ide.ui.laf.darcula.DarculaUIUtil;
import com.intellij.ide.ui.laf.darcula.ui.DarculaComboBoxUI;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.registry.Registry;
-import com.intellij.ui.ComboBoxCompositeEditor;
import com.intellij.ui.EditorTextField;
import com.intellij.ui.PopupMenuListenerAdapter;
import com.intellij.util.ui.JBDimension;
@@ -116,11 +115,13 @@ public class WinIntelliJComboBoxUI extends DarculaComboBoxUI {
}
}
- g2.setColor(getComboBackground(editor != null && editor.isOpaque()));
+ boolean isOpaque = editor != null && editor.isOpaque();
+ g2.setColor(getComboBackground(isOpaque));
JBInsets.removeFrom(r, JBUI.insets(2));
- if (!comboBox.isEnabled()) {
- g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.47f));
+ if (!comboBox.isEnabled() && !isOpaque) {
+ float alpha = comboBox.isEditable() ? 0.35f : 0.47f;
+ g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
}
g2.fill(r);
@@ -256,10 +257,6 @@ public class WinIntelliJComboBoxUI extends DarculaComboBoxUI {
}
}
- if (!comboBox.isEnabled()) {
- g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
- }
-
Icon icon = MacIntelliJIconCache.getIcon("comboDropTriangle", false, false, isEnabled());
int x = JBUI.scale(5);
int y = (getHeight() - icon.getIconHeight()) / 2;
@@ -392,8 +389,7 @@ public class WinIntelliJComboBoxUI extends DarculaComboBoxUI {
etf.addMouseListener(editorHoverListener);
etf.setBackground(getComboBackground(true));
- int topBorderWidth = editor instanceof ComboBoxCompositeEditor ? 1 : 2;
- jEditor.setBorder(JBUI.Borders.emptyTop(topBorderWidth));
+ jEditor.setBorder(JBUI.Borders.emptyTop(1));
}
}
}
@@ -460,7 +456,9 @@ public class WinIntelliJComboBoxUI extends DarculaComboBoxUI {
}
} else {
g2.setColor(UIManager.getColor("Button.intellij.native.borderColor"));
- g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.47f));
+
+ float alpha = comboBox.isEditable() ? 0.35f : 0.47f;
+ g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha));
}
Path2D border = new Path2D.Double(Path2D.WIND_EVEN_ODD);
@@ -505,7 +503,7 @@ public class WinIntelliJComboBoxUI extends DarculaComboBoxUI {
@Override
public Insets getBorderInsets(Component c) {
return c.getComponentOrientation().isLeftToRight() ?
- JBUI.insets(2, 6, 2, 2).asUIResource() : JBUI.insets(2, 2, 2, 6).asUIResource();
+ JBUI.insets(2, 5, 2, 2).asUIResource() : JBUI.insets(2, 2, 2, 5).asUIResource();
}
private Dimension getSizeWithButton(Dimension d) {
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJSpinnerUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJSpinnerUI.java
index 8954d331542a..1a3cb580f858 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJSpinnerUI.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJSpinnerUI.java
@@ -225,7 +225,7 @@ public class WinIntelliJSpinnerUI extends DarculaSpinnerUI {
Dimension prevButtonSize = prevButton.getPreferredSize();
prevButton.setBounds(bounds.width - prevButtonSize.width, nextButtonSize.height - JBUI.scale(1),
- prevButtonSize.width, prevButtonSize.height);
+ prevButtonSize.width, bounds.height - nextButtonSize.height + JBUI.scale(1));
JComponent editor = spinner.getEditor();
if (editor != null) {
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJTextBorder.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJTextBorder.java
index 62e0dc290e3e..c29c6447050b 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJTextBorder.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJTextBorder.java
@@ -44,7 +44,7 @@ public class WinIntelliJTextBorder extends DarculaTextBorder {
} else if (c instanceof JTextField && c.getParent() instanceof ColorPanel) {
return JBUI.insets(3, 3, 2, 2).asUIResource();
} else {
- return JBUI.insets(4, 6).asUIResource();
+ return JBUI.insets(4, 5).asUIResource();
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJTextFieldUI.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJTextFieldUI.java
index ced1625d5a3d..41d3c89364c0 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJTextFieldUI.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellij/WinIntelliJTextFieldUI.java
@@ -85,7 +85,7 @@ public class WinIntelliJTextFieldUI extends DarculaTextFieldUI {
}
static void paintTextFieldBackground(JComponent c, Graphics2D g2) {
- g2.setColor(c.isEnabled() ? c.getBackground() : UIManager.getColor("TextField.inactiveBackground"));
+ g2.setColor(c.isEnabled() ? c.getBackground() : UIManager.getColor("Button.background"));
if (!c.isEnabled()) {
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.47f));
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_native.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_native.properties
index 496aa1c1c0be..abc6ed280be5 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_native.properties
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/intellijlaf_native.properties
@@ -33,7 +33,10 @@ Menu.border=com.intellij.ide.ui.laf.darcula.ui.DarculaMenuItemBorder
EditorPaneUI=com.intellij.ide.ui.laf.darcula.ui.DarculaEditorPaneUI
control=f2f2f2
-link.foreground=589df6
+link.foreground=016cc1
+link.pressed.foreground=006064
+link.hover.foreground=00bcd4
+link.visited.foreground=016cc1
ScrollBarUI=com.intellij.ui.components.JBScrollBar
TableHeaderUI=com.intellij.ide.ui.laf.darcula.DarculaTableHeaderUI
Table.gridColor=dddddd
diff --git a/platform/platform-impl/src/com/intellij/ide/util/GotoLineNumberDialog.java b/platform/platform-impl/src/com/intellij/ide/util/GotoLineNumberDialog.java
index 6b322715a20d..9866caddad74 100644
--- a/platform/platform-impl/src/com/intellij/ide/util/GotoLineNumberDialog.java
+++ b/platform/platform-impl/src/com/intellij/ide/util/GotoLineNumberDialog.java
@@ -28,6 +28,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import java.awt.*;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -80,6 +82,14 @@ public abstract class GotoLineNumberDialog extends DialogWrapper {
class MyTextField extends JTextField {
public MyTextField() {
super("");
+ addFocusListener(new FocusAdapter() {
+ @Override
+ public void focusGained(FocusEvent e) {
+ if (!e.isTemporary()) {
+ selectAll();
+ }
+ }
+ });
}
public Dimension getPreferredSize() {
diff --git a/platform/platform-impl/src/com/intellij/ui/FinderRecursivePanel.java b/platform/platform-impl/src/com/intellij/ui/FinderRecursivePanel.java
index dd15dd1bd930..2db9101370fd 100644
--- a/platform/platform-impl/src/com/intellij/ui/FinderRecursivePanel.java
+++ b/platform/platform-impl/src/com/intellij/ui/FinderRecursivePanel.java
@@ -29,6 +29,9 @@ import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.UserDataHolder;
+import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.pom.Navigatable;
@@ -61,7 +64,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
* @param List item type. Must implement {@code equals()/hashCode()} correctly.
* @since 13.0
*/
-public abstract class FinderRecursivePanel extends OnePixelSplitter implements DataProvider, Disposable {
+public abstract class FinderRecursivePanel extends OnePixelSplitter implements DataProvider, UserDataHolder, Disposable {
@NotNull
private final Project myProject;
@@ -101,6 +104,8 @@ public abstract class FinderRecursivePanel extends OnePixelSplitter implement
}
};
+ private final UserDataHolderBase myUserDataHolder = new UserDataHolderBase();
+
protected FinderRecursivePanel(@NotNull FinderRecursivePanel parent) {
this(parent.getProject(), parent, parent.getGroupId());
}
@@ -385,6 +390,17 @@ public abstract class FinderRecursivePanel extends OnePixelSplitter implement
return null;
}
+ @Nullable
+ @Override
+ public U getUserData(@NotNull Key key) {
+ return myUserDataHolder.getUserData(key);
+ }
+
+ @Override
+ public void putUserData(@NotNull Key key, @Nullable U value) {
+ myUserDataHolder.putUserData(key, value);
+ }
+
@Override
public void dispose() {
super.dispose();
@@ -692,4 +708,24 @@ public abstract class FinderRecursivePanel extends OnePixelSplitter implement
protected final void customizeCellRenderer(@NotNull JList list, Object value, int index, boolean selected, boolean hasFocus) {
}
}
+
+ /**
+ * {@link FinderRecursivePanel} disposes right component on selection change if it is disposable.
+ * If an inheritor creates disposable objects during right component creation,
+ * the disposable objects must be registered as children of the created right component
+ * in order to dispose created objects on selection change.
+ * {@link DisposablePanel} could be used as a right component in that case.
+ */
+ protected static class DisposablePanel extends JPanel implements Disposable {
+ public DisposablePanel(LayoutManager layout, @Nullable Disposable parent) {
+ super(layout);
+ if (parent != null) {
+ Disposer.register(parent, this);
+ }
+ }
+
+ @Override
+ public void dispose() {
+ }
+ }
}
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/ui/TreeExpandCollapse.java b/platform/platform-impl/src/com/intellij/ui/TreeExpandCollapse.java
index baf86acc57b8..dfd3076583c2 100644
--- a/platform/platform-impl/src/com/intellij/ui/TreeExpandCollapse.java
+++ b/platform/platform-impl/src/com/intellij/ui/TreeExpandCollapse.java
@@ -31,9 +31,13 @@ public class TreeExpandCollapse {
}
public static void expandAll(JTree tree) {
- TreePath path = tree.getSelectionPath();
- if (path == null) path = new TreePath(tree.getModel().getRoot());
- new ExpandContext(300, 10).expand(tree, path);
+ TreePath[] paths = tree.getSelectionPaths();
+ if (paths == null) {
+ paths = new TreePath[] { new TreePath(tree.getModel().getRoot()) };
+ }
+ for (TreePath path : paths) {
+ new ExpandContext(300, 10).expand(tree, path);
+ }
}
private static class ExpandContext {
diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties
index 96d8a8c99a98..17a365ef4d17 100644
--- a/platform/platform-resources-en/src/messages/ActionsBundle.properties
+++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties
@@ -1318,7 +1318,6 @@ action.Diff.FocusOppositePaneAndScroll.text=Select Position In Opposite Diff Pan
action.Diff.FocusOppositePaneAndScroll.description=Select the same position in opposite pane in diff view
action.Diff.PrevChange.text=Compare Previous File
action.Diff.NextChange.text=Compare Next File
-action.Diff.SelectedChange.text=Choose File To Compare
action.Diff.ApplyLeftSide.text=Accept Left Side
action.Diff.ApplyRightSide.text=Accept Right Side
action.Diff.AppendLeftSide.text=Append Left Side
diff --git a/platform/platform-resources-en/src/messages/VcsBundle.properties b/platform/platform-resources-en/src/messages/VcsBundle.properties
index 682a2e481980..b81cae50d33e 100644
--- a/platform/platform-resources-en/src/messages/VcsBundle.properties
+++ b/platform/platform-resources-en/src/messages/VcsBundle.properties
@@ -367,6 +367,7 @@ create.patch.success.confirmation=Successfully created patch {0}
patch.apply.error=Failed to apply patch for file {0}: {1}
patch.load.base.revision.error=Failed to load patch base revision for file {0}: {1}
shelve.changes.only.directories=The selected changes affect only directories and no files, so they cannot be shelved
+stash.changes.message=Uncommitted changes before {0}
edit.errors=Edit Errors
rollback.modified.without.editing.confirm.single=Would you like to {0} the changes to {1}?
rollback.modified.without.editing.confirm.multiple=Would you like to {0} the changes to {1} selected files?
diff --git a/platform/platform-resources/src/idea/VcsActions.xml b/platform/platform-resources/src/idea/VcsActions.xml
index fb3f0a36184a..ecf6df0f61e5 100644
--- a/platform/platform-resources/src/idea/VcsActions.xml
+++ b/platform/platform-resources/src/idea/VcsActions.xml
@@ -218,8 +218,6 @@
icon="AllIcons.Actions.Prevfile" use-shortcut-of="PreviousTab"/>
-