Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Jemerov
2012-08-23 16:02:43 +02:00
95 changed files with 1126 additions and 464 deletions
@@ -85,12 +85,12 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
}
@Override
public boolean isEnabled(@NotNull ArrangementEntryType type, @Nullable ArrangementSettingsNode current) {
public boolean isEnabled(@NotNull ArrangementEntryType type, @Nullable ArrangementMatchCondition current) {
return SUPPORTED_TYPES.contains(type);
}
@Override
public boolean isEnabled(@NotNull ArrangementModifier modifier, @Nullable ArrangementSettingsNode current) {
public boolean isEnabled(@NotNull ArrangementModifier modifier, @Nullable ArrangementMatchCondition current) {
if (current == null) {
return SUPPORTED_MODIFIERS.contains(modifier);
}
@@ -98,15 +98,15 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
final Ref<Object> typeRef = new Ref<Object>();
current.invite(new ArrangementSettingsNodeVisitor() {
@Override
public void visit(@NotNull ArrangementSettingsAtomNode node) {
if (node.getType() == ArrangementSettingType.TYPE) {
typeRef.set(node.getValue());
public void visit(@NotNull ArrangementAtomMatchCondition setting) {
if (setting.getType() == ArrangementSettingType.TYPE) {
typeRef.set(setting.getValue());
}
}
@Override
public void visit(@NotNull ArrangementSettingsCompositeNode node) {
for (ArrangementSettingsNode n : node.getOperands()) {
public void visit(@NotNull ArrangementCompositeMatchCondition setting) {
for (ArrangementMatchCondition n : setting.getOperands()) {
if (typeRef.get() != null) {
return;
}
@@ -127,39 +127,39 @@ public class JavaRearranger implements Rearranger<JavaElementArrangementEntry>,
@NotNull
@Override
public HierarchicalArrangementSettingsNode group(@NotNull ArrangementSettingsNode node) {
final Ref<HierarchicalArrangementSettingsNode> result = new Ref<HierarchicalArrangementSettingsNode>();
public HierarchicalArrangementConditionNode group(@NotNull ArrangementMatchCondition node) {
final Ref<HierarchicalArrangementConditionNode> result = new Ref<HierarchicalArrangementConditionNode>();
node.invite(new ArrangementSettingsNodeVisitor() {
@Override
public void visit(@NotNull ArrangementSettingsAtomNode node) {
result.set(new HierarchicalArrangementSettingsNode(node));
public void visit(@NotNull ArrangementAtomMatchCondition setting) {
result.set(new HierarchicalArrangementConditionNode(setting));
}
@Override
public void visit(@NotNull ArrangementSettingsCompositeNode node) {
ArrangementSettingsNode typeNode = null;
for (ArrangementSettingsNode n : node.getOperands()) {
if (n instanceof ArrangementSettingsAtomNode && ((ArrangementSettingsAtomNode)n).getType() == ArrangementSettingType.TYPE) {
public void visit(@NotNull ArrangementCompositeMatchCondition setting) {
ArrangementMatchCondition typeNode = null;
for (ArrangementMatchCondition n : setting.getOperands()) {
if (n instanceof ArrangementAtomMatchCondition && ((ArrangementAtomMatchCondition)n).getType() == ArrangementSettingType.TYPE) {
typeNode = n;
break;
}
}
if (typeNode == null) {
result.set(new HierarchicalArrangementSettingsNode(node));
result.set(new HierarchicalArrangementConditionNode(setting));
}
else {
HierarchicalArrangementSettingsNode parent = new HierarchicalArrangementSettingsNode(typeNode);
ArrangementSettingsCompositeNode compositeWithoutType = new ArrangementSettingsCompositeNode(node.getOperator());
for (ArrangementSettingsNode n : node.getOperands()) {
HierarchicalArrangementConditionNode parent = new HierarchicalArrangementConditionNode(typeNode);
ArrangementCompositeMatchCondition compositeWithoutType = new ArrangementCompositeMatchCondition(setting.getOperator());
for (ArrangementMatchCondition n : setting.getOperands()) {
if (n != typeNode) {
compositeWithoutType.addOperand(n);
}
}
if (compositeWithoutType.getOperands().size() == 1) {
parent.setChild(new HierarchicalArrangementSettingsNode(compositeWithoutType.getOperands().iterator().next()));
parent.setChild(new HierarchicalArrangementConditionNode(compositeWithoutType.getOperands().iterator().next()));
}
else {
parent.setChild(new HierarchicalArrangementSettingsNode(compositeWithoutType));
parent.setChild(new HierarchicalArrangementConditionNode(compositeWithoutType));
}
result.set(parent);
}
@@ -33,7 +33,7 @@ public class MethodSignatureBackedByPsiMethod extends MethodSignatureBase {
super(substitutor, parameterTypes, methodTypeParameters);
myIsRaw = isRaw;
if (!method.isValid()) {
LOG.error("Invalid method: "+method);
LOG.error("Invalid method: "+method, new PsiInvalidElementAccessException(method));
}
myMethod = method;
}
@@ -57,7 +57,9 @@ public class PsiScopesUtil {
@NotNull final PsiElement entrance,
@Nullable final PsiElement maxScope,
@NotNull final ResolveState state) {
LOG.assertTrue(entrance.isValid(), entrance);
if (!entrance.isValid()) {
LOG.error(new PsiInvalidElementAccessException(entrance));
}
PsiElement prevParent = entrance;
PsiElement scope = entrance;
@@ -18,16 +18,15 @@ package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.psi.codeStyle.arrangement.JavaRearranger;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.ui.treeStructure.Tree;
import gnu.trove.TIntObjectHashMap;
import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import java.util.Arrays;
@@ -55,11 +54,11 @@ public abstract class AbstractArrangementRuleEditingModelTest {
myGrouper = new JavaRearranger();
}
protected void configure(@NotNull ArrangementSettingsNode settingsNode) {
myBuilder.build(settingsNode, myTree, myRoot, myGrouper, myRowMappings);
protected void configure(@NotNull ArrangementMatchCondition matchCondition) {
myBuilder.build(matchCondition, myTree, myRoot, myGrouper, myRowMappings);
}
protected static ArrangementSettingsAtomNode atom(@NotNull Object condition) {
protected static ArrangementAtomMatchCondition atom(@NotNull Object condition) {
final ArrangementSettingType type;
if (condition instanceof ArrangementEntryType) {
type = ArrangementSettingType.TYPE;
@@ -70,7 +69,7 @@ public abstract class AbstractArrangementRuleEditingModelTest {
else {
throw new IllegalArgumentException(String.format("Unexpected condition of class %s: %s", condition.getClass(), condition));
}
return new ArrangementSettingsAtomNode(type, condition);
return new ArrangementAtomMatchCondition(type, condition);
}
protected void checkRows(int... rows) {
@@ -16,7 +16,7 @@
package com.intellij.application.options.codeStyle.arrangement
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition
import gnu.trove.TIntIntHashMap
import org.jetbrains.annotations.NotNull
import org.jetbrains.annotations.Nullable
@@ -351,7 +351,7 @@ public class TreeNodeBuilder extends BuilderSupport {
@Override
protected Object createNode(Object name) {
def result = new ArrangementTreeNode(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, name))
def result = new ArrangementTreeNode(new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, name))
currentNode?.add(result)
result
}
@@ -15,11 +15,9 @@
*/
package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import org.junit.Test;
import javax.swing.tree.DefaultMutableTreeNode;
import static com.intellij.psi.codeStyle.arrangement.ArrangementUtil.and;
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType.FIELD;
import static com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier.*;
@@ -33,21 +31,21 @@ public class ArrangementRuleEditingModelBuilderTest extends AbstractArrangementR
@Test
public void mapToTheSameLayer() {
ArrangementSettingsNode settingsNode = and(atom(PUBLIC), atom(STATIC));
myBuilder.build(settingsNode, myTree, myRoot, myGrouper, myRowMappings);
ArrangementMatchCondition matchCondition = and(atom(PUBLIC), atom(STATIC));
myBuilder.build(matchCondition, myTree, myRoot, myGrouper, myRowMappings);
checkRows(1);
ArrangementRuleEditingModel model = myRowMappings.get(1);
assertTrue(model.hasCondition(PUBLIC));
assertTrue(model.hasCondition(STATIC));
assertFalse(model.hasCondition(PRIVATE));
assertEquals(1, myRoot.getChildCount());
assertEquals(settingsNode, myRoot.getFirstChild().getBackingSetting());
assertEquals(matchCondition, myRoot.getFirstChild().getBackingSetting());
}
@Test
public void splitIntoTwoLayers() {
ArrangementSettingsNode settingsNode = and(atom(FIELD), atom(PUBLIC), atom(STATIC));
myBuilder.build(settingsNode, myTree, myRoot, myGrouper, myRowMappings);
ArrangementMatchCondition matchCondition = and(atom(FIELD), atom(PUBLIC), atom(STATIC));
myBuilder.build(matchCondition, myTree, myRoot, myGrouper, myRowMappings);
checkRows(2);
@@ -15,7 +15,7 @@
*/
package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import org.junit.Test;
import static com.intellij.psi.codeStyle.arrangement.ArrangementUtil.and;
@@ -39,9 +39,9 @@ public class ArrangementRuleEditingModelImplTest extends AbstractArrangementRule
ArrangementTreeNode child = myRoot.getFirstChild();
assertNotNull(child);
ArrangementSettingsNode expectedSettingsNode = and(atom(PUBLIC), atom(STATIC));
assertEquals(expectedSettingsNode, child.getBackingSetting());
assertEquals(expectedSettingsNode, model.getSettingsNode());
ArrangementMatchCondition expectedMatchCondition = and(atom(PUBLIC), atom(STATIC));
assertEquals(expectedMatchCondition, child.getBackingSetting());
assertEquals(expectedMatchCondition, model.getMatchCondition());
}
@Test
@@ -54,7 +54,7 @@ public class ArrangementRuleEditingModelImplTest extends AbstractArrangementRule
model.addAndCondition(atom(FIELD));
assertEquals(2, model.getRow());
assertEquals(and(atom(FIELD), atom(PUBLIC)), model.getSettingsNode());
assertEquals(and(atom(FIELD), atom(PUBLIC)), model.getMatchCondition());
ArrangementTreeNode fieldNode = myRoot.getFirstChild();
assertNotNull(fieldNode);
@@ -76,7 +76,7 @@ public class ArrangementRuleEditingModelImplTest extends AbstractArrangementRule
assertEquals(1, myRowMappings.size());
assertSame(model, myRowMappings.get(2));
assertEquals(and(atom(FIELD), atom(PUBLIC), atom(STATIC)), model.getSettingsNode());
assertEquals(and(atom(FIELD), atom(PUBLIC), atom(STATIC)), model.getMatchCondition());
ArrangementTreeNode fieldNode = myRoot.getFirstChild();
assertNotNull(fieldNode);
@@ -98,7 +98,7 @@ public class ArrangementRuleEditingModelImplTest extends AbstractArrangementRule
assertEquals(1, myRowMappings.size());
assertSame(model, myRowMappings.get(2));
assertEquals(and(atom(FIELD), atom(STATIC)), model.getSettingsNode());
assertEquals(and(atom(FIELD), atom(STATIC)), model.getMatchCondition());
ArrangementTreeNode fieldNode = myRoot.getFirstChild();
assertNotNull(fieldNode);
@@ -119,7 +119,7 @@ public class ArrangementRuleEditingModelImplTest extends AbstractArrangementRule
model.removeAndCondition(atom(PUBLIC));
assertEquals(1, model.getRow());
assertEquals(atom(FIELD), model.getSettingsNode());
assertEquals(atom(FIELD), model.getMatchCondition());
ArrangementTreeNode fieldNode = myRoot.getFirstChild();
assertNotNull(fieldNode);
@@ -143,10 +143,10 @@ public class ArrangementRuleEditingModelImplTest extends AbstractArrangementRule
modelToChange.removeAndCondition(atom(PUBLIC));
assertSame(1, modelToChange.getRow());
assertEquals(atom(FIELD), modelToChange.getSettingsNode());
assertEquals(atom(FIELD), modelToChange.getMatchCondition());
assertSame(3, siblingModel.getRow());
assertEquals(and(atom(FIELD), atom(STATIC)), siblingModel.getSettingsNode());
assertEquals(and(atom(FIELD), atom(STATIC)), siblingModel.getMatchCondition());
ArrangementTreeNode atomFieldNode = myRoot.getFirstChild();
assertNotNull(atomFieldNode);
@@ -177,10 +177,10 @@ public class ArrangementRuleEditingModelImplTest extends AbstractArrangementRule
assertEquals(2, myRowMappings.size());
assertSame(siblingModel, myRowMappings.get(2));
assertEquals(and(atom(FIELD), atom(PUBLIC)), siblingModel.getSettingsNode());
assertEquals(and(atom(FIELD), atom(PUBLIC)), siblingModel.getMatchCondition());
assertSame(modelToChange, myRowMappings.get(3));
assertEquals(atom(FIELD), modelToChange.getSettingsNode());
assertEquals(atom(FIELD), modelToChange.getMatchCondition());
ArrangementTreeNode compositeFieldNode = myRoot.getFirstChild();
assertNotNull(compositeFieldNode);
@@ -125,6 +125,7 @@ public class ClassFilterEditor extends JPanel implements ComponentWithEmptyText
getEmptyText().setText(UIBundle.message("no.patterns"));
}
@NotNull
@Override
public StatusText getEmptyText() {
return myTable.getEmptyText();
@@ -1,6 +1,7 @@
package org.jetbrains.jps.model.library;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.JpsElement;
import org.jetbrains.jps.model.JpsNamedElement;
import org.jetbrains.jps.model.JpsReferenceableElement;
@@ -32,6 +33,10 @@ public interface JpsLibrary extends JpsNamedElement, JpsReferenceableElement<Jps
@NotNull
JpsLibraryType<?> getType();
@Nullable
<P extends JpsElement>
JpsTypedLibrary<P> asTyped(@NotNull JpsLibraryType<P> type);
@NotNull
JpsElement getProperties();
@@ -22,6 +22,10 @@ public interface JpsLibraryCollection {
@NotNull
List<JpsLibrary> getLibraries();
@NotNull
<P extends JpsElement>
Iterable<JpsTypedLibrary<P>> getLibraries(@NotNull JpsLibraryType<P> type);
void addLibrary(@NotNull JpsLibrary library);
@Nullable
@@ -12,21 +12,15 @@ import java.util.List;
public abstract class JpsNamedElementReferenceBase<S extends JpsNamedElement, T extends JpsNamedElement, Self extends JpsNamedElementReferenceBase<S, T, Self>>
extends JpsCompositeElementBase<Self> implements JpsElementReference<T> {
private static final JpsElementChildRole<JpsElementReference<? extends JpsCompositeElement>> PARENT_REFERENCE_ROLE = JpsElementChildRoleBase.create("parent");
protected final JpsElementCollectionRole<? extends S> myCollectionRole;
protected final String myElementName;
protected JpsNamedElementReferenceBase(@NotNull JpsElementCollectionRole<? extends S> role,
@NotNull String elementName,
@NotNull JpsElementReference<? extends JpsCompositeElement> parentReference) {
super();
myCollectionRole = role;
protected JpsNamedElementReferenceBase(@NotNull String elementName, @NotNull JpsElementReference<? extends JpsCompositeElement> parentReference) {
myElementName = elementName;
myContainer.setChild(PARENT_REFERENCE_ROLE, parentReference);
}
protected JpsNamedElementReferenceBase(JpsNamedElementReferenceBase<S, T, Self> original) {
super(original);
myCollectionRole = original.myCollectionRole;
myElementName = original.myElementName;
}
@@ -35,7 +29,7 @@ public abstract class JpsNamedElementReferenceBase<S extends JpsNamedElement, T
final JpsCompositeElement parent = getParentReference().resolve();
if (parent == null) return null;
JpsElementCollectionImpl<? extends S> collection = parent.getContainer().getChild(myCollectionRole);
JpsElementCollectionImpl<? extends S> collection = getCollection(parent);
if (collection == null) return null;
final List<? extends S> elements = collection.getElements();
@@ -50,10 +44,19 @@ public abstract class JpsNamedElementReferenceBase<S extends JpsNamedElement, T
return null;
}
@Nullable
protected abstract JpsElementCollectionImpl<? extends S> getCollection(@NotNull JpsCompositeElement parent);
@Nullable
protected abstract T resolve(S element);
public JpsElementReference<? extends JpsCompositeElement> getParentReference() {
return myContainer.getChild(PARENT_REFERENCE_ROLE);
}
@Override
public JpsElementReference<T> asExternal(@NotNull JpsModel model) {
model.registerExternalReference(this);
return this;
}
}
@@ -1,6 +1,7 @@
package org.jetbrains.jps.model.impl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.JpsCompositeElement;
import org.jetbrains.jps.model.JpsElementReference;
import org.jetbrains.jps.model.JpsNamedElement;
@@ -9,17 +10,26 @@ import org.jetbrains.jps.model.JpsNamedElement;
* @author nik
*/
public abstract class JpsNamedElementReferenceImpl<T extends JpsNamedElement, Self extends JpsNamedElementReferenceImpl<T, Self>> extends JpsNamedElementReferenceBase<T, T, Self> {
protected final JpsElementCollectionRole<? extends T> myCollectionRole;
protected JpsNamedElementReferenceImpl(@NotNull JpsElementCollectionRole<? extends T> role, @NotNull String elementName,
@NotNull JpsElementReference<? extends JpsCompositeElement> parentReference) {
super(role, elementName, parentReference);
super(elementName, parentReference);
myCollectionRole = role;
}
protected JpsNamedElementReferenceImpl(JpsNamedElementReferenceImpl<T, Self> original) {
super(original);
myCollectionRole = original.myCollectionRole;
}
@Override
protected T resolve(T element) {
return element;
}
@Nullable
protected JpsElementCollectionImpl<? extends T> getCollection(@NotNull JpsCompositeElement parent) {
return parent.getContainer().getChild(myCollectionRole);
}
}
@@ -2,8 +2,8 @@ package org.jetbrains.jps.model.library.impl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.model.JpsElement;
import org.jetbrains.jps.model.JpsElementCollection;
import org.jetbrains.jps.model.JpsElementTypeWithDefaultProperties;
import org.jetbrains.jps.model.impl.JpsElementCollectionImpl;
import org.jetbrains.jps.model.library.JpsLibrary;
import org.jetbrains.jps.model.library.JpsLibraryCollection;
import org.jetbrains.jps.model.library.JpsLibraryType;
@@ -15,9 +15,9 @@ import java.util.List;
* @author nik
*/
public class JpsLibraryCollectionImpl implements JpsLibraryCollection {
private final JpsElementCollection<JpsLibrary> myCollection;
private final JpsElementCollectionImpl<JpsLibrary> myCollection;
public JpsLibraryCollectionImpl(JpsElementCollection<JpsLibrary> collection) {
public JpsLibraryCollectionImpl(JpsElementCollectionImpl<JpsLibrary> collection) {
myCollection = collection;
}
@@ -41,6 +41,12 @@ public class JpsLibraryCollectionImpl implements JpsLibraryCollection {
return myCollection.getElements();
}
@NotNull
@Override
public <P extends JpsElement> Iterable<JpsTypedLibrary<P>> getLibraries(@NotNull JpsLibraryType<P> type) {
return myCollection.getElementsOfType(type);
}
@Override
public void addLibrary(@NotNull JpsLibrary library) {
myCollection.addChild(library);
@@ -2,6 +2,7 @@ package org.jetbrains.jps.model.library.impl;
import com.intellij.openapi.util.io.FileUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.JpsPathUtil;
import org.jetbrains.jps.model.*;
import org.jetbrains.jps.model.impl.JpsElementCollectionImpl;
@@ -37,6 +38,13 @@ public class JpsLibraryImpl<P extends JpsElement> extends JpsNamedCompositeEleme
return myLibraryType;
}
@Nullable
@Override
public <P extends JpsElement> JpsTypedLibrary<P> asTyped(@NotNull JpsLibraryType<P> type) {
//noinspection unchecked
return myLibraryType.equals(type) ? (JpsTypedLibrary<P>)this : null;
}
@NotNull
@Override
public P getProperties() {
@@ -1,10 +1,11 @@
package org.jetbrains.jps.model.library.impl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.JpsCompositeElement;
import org.jetbrains.jps.model.JpsElement;
import org.jetbrains.jps.model.JpsElementReference;
import org.jetbrains.jps.model.JpsModel;
import org.jetbrains.jps.model.impl.JpsElementCollectionImpl;
import org.jetbrains.jps.model.impl.JpsNamedElementReferenceBase;
import org.jetbrains.jps.model.library.JpsLibrary;
import org.jetbrains.jps.model.library.JpsTypedLibrary;
@@ -18,10 +19,9 @@ import org.jetbrains.jps.model.library.sdk.JpsSdkType;
public class JpsSdkReferenceImpl<P extends JpsElement> extends JpsNamedElementReferenceBase<JpsLibrary, JpsTypedLibrary<JpsSdk<P>>, JpsSdkReferenceImpl<P>> implements JpsSdkReference<P> {
private final JpsSdkType<P> mySdkType;
public JpsSdkReferenceImpl(@NotNull String elementName,
@NotNull JpsSdkType<P> sdkType,
public JpsSdkReferenceImpl(@NotNull String elementName, @NotNull JpsSdkType<P> sdkType,
@NotNull JpsElementReference<? extends JpsCompositeElement> parentReference) {
super(JpsLibraryRole.LIBRARIES_COLLECTION_ROLE, elementName, parentReference);
super(elementName, parentReference);
mySdkType = sdkType;
}
@@ -37,11 +37,7 @@ public class JpsSdkReferenceImpl<P extends JpsElement> extends JpsNamedElementRe
@Override
protected JpsTypedLibrary<JpsSdk<P>> resolve(JpsLibrary element) {
if (element.getType().equals(mySdkType)) {
//noinspection unchecked
return (JpsTypedLibrary<JpsSdk<P>>)element;
}
return null;
return element.asTyped(mySdkType);
}
@NotNull
@@ -50,9 +46,8 @@ public class JpsSdkReferenceImpl<P extends JpsElement> extends JpsNamedElementRe
return new JpsSdkReferenceImpl<P>(this);
}
@Override
public JpsSdkReferenceImpl<P> asExternal(@NotNull JpsModel model) {
model.registerExternalReference(this);
return this;
@Nullable
protected JpsElementCollectionImpl<? extends JpsLibrary> getCollection(@NotNull JpsCompositeElement parent) {
return parent.getContainer().getChild(JpsLibraryRole.LIBRARIES_COLLECTION_ROLE);
}
}
@@ -1,8 +1,6 @@
package org.jetbrains.jps.model.module.impl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.model.JpsElementReference;
import org.jetbrains.jps.model.JpsModel;
import org.jetbrains.jps.model.impl.JpsNamedElementReferenceImpl;
import org.jetbrains.jps.model.module.JpsFacet;
import org.jetbrains.jps.model.module.JpsFacetReference;
@@ -25,10 +23,4 @@ public class JpsFacetReferenceImpl extends JpsNamedElementReferenceImpl<JpsFacet
public JpsFacetReferenceImpl createCopy() {
return new JpsFacetReferenceImpl(this);
}
@Override
public JpsElementReference<JpsFacet> asExternal(@NotNull JpsModel model) {
model.registerExternalReference(this);
return this;
}
}
@@ -16,34 +16,56 @@
package com.intellij.psi;
import com.intellij.lang.Language;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.lang.ref.SoftReference;
/**
* @author mike
*/
public class PsiInvalidElementAccessException extends RuntimeException {
private final SoftReference<PsiElement> myElementReference; // to prevent leaks, exceptions are stored in IdeaLogger
private final SoftReference<PsiElement> myElementReference; // to prevent leaks, since exceptions are stored in IdeaLogger
public PsiInvalidElementAccessException(PsiElement element) {
super(element != null ? "Element: " + element.getClass() : "Unknown psi element");
myElementReference = new SoftReference<PsiElement>(element);
this(element, null, null);
}
public PsiInvalidElementAccessException(PsiElement element, String message) {
super(message);
myElementReference = new SoftReference<PsiElement>(element);
this(element, message, null);
}
public PsiInvalidElementAccessException(PsiElement element, Throwable cause) {
super(cause);
myElementReference = new SoftReference<PsiElement>(element);
this(element, null, cause);
}
public PsiInvalidElementAccessException(PsiElement element, String message, Throwable cause) {
super(message, cause);
super((element != null ? "Element: " + element.getClass() + " because: " + reason(element) : "Unknown psi element") +
(message == null ? "" : "; " + message), cause);
myElementReference = new SoftReference<PsiElement>(element);
}
@NonNls
@NotNull
private static String reason(@NotNull PsiElement element){
PsiFile file = element.getContainingFile();
if (file == null) return element.getParent() == null ? "parent is null" : "containing file is null";
FileViewProvider provider = file.getViewProvider();
VirtualFile vFile = provider.getVirtualFile();
if (!vFile.isValid()) return vFile+" is invalid";
if (!provider.isPhysical()) return "non-physical provider"; // "dummy" file
PsiManager manager = file.getManager();
if (manager.getProject().isDisposed()) return "project is disposed";
Language language = file.getLanguage();
if (language != provider.getBaseLanguage()) return "File language:"+language+" != Provider base language:"+provider.getBaseLanguage();
FileViewProvider provider1 = manager.findViewProvider(vFile);
if (provider != provider1) return "different providers: "+provider+"("+Integer.toHexString(System.identityHashCode(provider))+"); "+provider1+"("+Integer.toHexString(System.identityHashCode(provider1))+")";
return "psi is outdated";
}
public PsiElement getPsiElement() {
return myElementReference.get();
}
@@ -171,19 +171,12 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
@Override
public boolean isValid() {
final VirtualFile vFile = getViewProvider().getVirtualFile();
FileViewProvider provider = getViewProvider();
final VirtualFile vFile = provider.getVirtualFile();
if (!vFile.isValid()) return false;
if (!getViewProvider().isPhysical()) return true; // "dummy" file
if (!provider.isPhysical()) return true; // "dummy" file
if (myManager.getProject().isDisposed()) return false;
return isPsiUpToDate(vFile);
//FileViewProvider viewProvider = getViewProvider();
//if (!viewProvider.isPhysical()) return true; // "dummy" file
//final VirtualFile vFile = viewProvider.getVirtualFile();
//if (!vFile.isValid() || !isPsiUpToDate(vFile)) return false;
//PsiManager manager = getManager();
//boolean valid = manager != null && !manager.getProject().isDisposed();
//return valid;
}
protected boolean isPsiUpToDate(@NotNull VirtualFile vFile) {
@@ -23,12 +23,14 @@ import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.process.ProcessNotCreatedException;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.notification.NotificationGroup;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.util.ObjectUtils;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
@@ -95,7 +97,8 @@ public class ExecutionUtil {
@Override
public void run() {
ToolWindowManager.getInstance(project).notifyByBalloon(toolWindowId, MessageType.ERROR, fullMessage, null, finalListener);
ourNotificationGroup.createNotification(title, finalDescription, NotificationType.ERROR, null).notify(project);
NotificationListener notificationListener = ObjectUtils.tryCast(finalListener, NotificationListener.class);
ourNotificationGroup.createNotification(title, finalDescription, NotificationType.ERROR, notificationListener).notify(project);
}
});
}
@@ -16,15 +16,13 @@
package com.intellij.psi.codeStyle.arrangement;
import com.intellij.lang.Language;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.CompositeArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsCompositeNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNodeVisitor;
import com.intellij.psi.codeStyle.arrangement.model.*;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -116,18 +114,18 @@ public class ArrangementUtil {
//region Rule composition
@NotNull
public static ArrangementSettingsNode and(@NotNull ArrangementSettingsNode... nodes) {
final ArrangementSettingsCompositeNode result = new ArrangementSettingsCompositeNode(ArrangementSettingsCompositeNode.Operator.AND);
public static ArrangementMatchCondition and(@NotNull ArrangementMatchCondition... nodes) {
final ArrangementCompositeMatchCondition result = new ArrangementCompositeMatchCondition(ArrangementCompositeMatchCondition.Operator.AND);
final ArrangementSettingsNodeVisitor visitor = new ArrangementSettingsNodeVisitor() {
@Override
public void visit(@NotNull ArrangementSettingsAtomNode node) {
public void visit(@NotNull ArrangementAtomMatchCondition node) {
result.addOperand(node);
}
@Override
public void visit(@NotNull ArrangementSettingsCompositeNode node) {
if (node.getOperator() == ArrangementSettingsCompositeNode.Operator.AND) {
for (ArrangementSettingsNode operand : node.getOperands()) {
public void visit(@NotNull ArrangementCompositeMatchCondition node) {
if (node.getOperator() == ArrangementCompositeMatchCondition.Operator.AND) {
for (ArrangementMatchCondition operand : node.getOperands()) {
operand.invite(this);
}
}
@@ -136,7 +134,7 @@ public class ArrangementUtil {
}
}
};
for (ArrangementSettingsNode node : nodes) {
for (ArrangementMatchCondition node : nodes) {
node.invite(visitor);
}
return result;
@@ -18,19 +18,21 @@ package com.intellij.psi.codeStyle.arrangement.model;
import org.jetbrains.annotations.NotNull;
/**
* // TODO den add doc
* Encapsulates a single atom match condition, e.g. 'entry type is field' or 'entry has 'static' modifier' etc.
* <p/>
* Not thread-safe..
*
* @author Denis Zhdanov
* @since 8/8/12 1:17 PM
*/
public class ArrangementSettingsAtomNode implements ArrangementSettingsNode {
public class ArrangementAtomMatchCondition implements ArrangementMatchCondition {
@NotNull private final ArrangementSettingType myType;
@NotNull private final Object myValue;
private boolean myInverted;
public ArrangementSettingsAtomNode(@NotNull ArrangementSettingType type, @NotNull Object value) {
public ArrangementAtomMatchCondition(@NotNull ArrangementSettingType type, @NotNull Object value) {
myType = type;
myValue = value;
}
@@ -75,15 +77,15 @@ public class ArrangementSettingsAtomNode implements ArrangementSettingsNode {
return false;
}
ArrangementSettingsAtomNode node = (ArrangementSettingsAtomNode)o;
ArrangementAtomMatchCondition setting = (ArrangementAtomMatchCondition)o;
if (myInverted != node.myInverted) {
if (myInverted != setting.myInverted) {
return false;
}
if (myType != node.myType) {
if (myType != setting.myType) {
return false;
}
if (!myValue.equals(node.myValue)) {
if (!myValue.equals(setting.myValue)) {
return false;
}
@@ -92,8 +94,8 @@ public class ArrangementSettingsAtomNode implements ArrangementSettingsNode {
@NotNull
@Override
public ArrangementSettingsAtomNode clone() {
ArrangementSettingsAtomNode result = new ArrangementSettingsAtomNode(myType, myValue);
public ArrangementAtomMatchCondition clone() {
ArrangementAtomMatchCondition result = new ArrangementAtomMatchCondition(myType, myValue);
result.setInverted(myInverted);
return result;
}
@@ -22,26 +22,28 @@ import org.jetbrains.annotations.NotNull;
import java.util.Set;
/**
* // TODO den add doc
* Encapsulates composite match condition, e.g. "an entry has type 'field' and modifier 'static'".
* <p/>
* Thread-safe.
*
* @author Denis Zhdanov
* @since 8/8/12 1:18 PM
*/
public class ArrangementSettingsCompositeNode implements ArrangementSettingsNode {
public class ArrangementCompositeMatchCondition implements ArrangementMatchCondition {
@NotNull private final Set<ArrangementSettingsNode> myOperands = new HashSet<ArrangementSettingsNode>();
@NotNull private final Set<ArrangementMatchCondition> myOperands = new HashSet<ArrangementMatchCondition>();
@NotNull private final Operator myOperator;
public ArrangementSettingsCompositeNode(@NotNull Operator operator) {
public ArrangementCompositeMatchCondition(@NotNull Operator operator) {
myOperator = operator;
}
@NotNull
public Set<ArrangementSettingsNode> getOperands() {
public Set<ArrangementMatchCondition> getOperands() {
return myOperands;
}
public ArrangementSettingsCompositeNode addOperand(@NotNull ArrangementSettingsNode node) {
public ArrangementCompositeMatchCondition addOperand(@NotNull ArrangementMatchCondition node) {
myOperands.add(node);
return this;
}
@@ -55,12 +57,12 @@ public class ArrangementSettingsCompositeNode implements ArrangementSettingsNode
public void invite(@NotNull ArrangementSettingsNodeVisitor visitor) {
visitor.visit(this);
}
@NotNull
@Override
public ArrangementSettingsCompositeNode clone() {
ArrangementSettingsCompositeNode result = new ArrangementSettingsCompositeNode(myOperator);
for (ArrangementSettingsNode operand : myOperands) {
public ArrangementCompositeMatchCondition clone() {
ArrangementCompositeMatchCondition result = new ArrangementCompositeMatchCondition(myOperator);
for (ArrangementMatchCondition operand : myOperands) {
result.addOperand(operand.clone());
}
return result;
@@ -82,12 +84,12 @@ public class ArrangementSettingsCompositeNode implements ArrangementSettingsNode
return false;
}
ArrangementSettingsCompositeNode node = (ArrangementSettingsCompositeNode)o;
ArrangementCompositeMatchCondition setting = (ArrangementCompositeMatchCondition)o;
if (!myOperands.equals(node.myOperands)) {
if (!myOperands.equals(setting.myOperands)) {
return false;
}
if (myOperator != node.myOperator) {
if (myOperator != setting.myOperator) {
return false;
}
@@ -15,18 +15,21 @@
*/
package com.intellij.psi.codeStyle.arrangement.model;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
import org.jetbrains.annotations.NotNull;
/**
* // TODO den add doc
* Generic data model for {@link ArrangementEntryMatcher arrangement entry matcher}.
* <p/>
* Implementations of this interface are not obliged to be thread-safe.
*
* @author Denis Zhdanov
* @since 8/8/12 11:13 AM
*/
public interface ArrangementSettingsNode extends Cloneable {
public interface ArrangementMatchCondition extends Cloneable {
void invite(@NotNull ArrangementSettingsNodeVisitor visitor);
@NotNull
ArrangementSettingsNode clone();
ArrangementMatchCondition clone();
}
@@ -23,7 +23,7 @@ import org.jetbrains.annotations.NotNull;
*/
public interface ArrangementSettingsNodeVisitor {
void visit(@NotNull ArrangementSettingsAtomNode node);
void visit(@NotNull ArrangementAtomMatchCondition setting);
void visit(@NotNull ArrangementSettingsCompositeNode node);
void visit(@NotNull ArrangementCompositeMatchCondition setting);
}
@@ -19,7 +19,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* {@link #getCurrent() Wraps} {@link ArrangementSettingsNode} in order to allow to build {@link #getChild() hierarchy}
* {@link #getCurrent() Wraps} {@link ArrangementMatchCondition} in order to allow to build {@link #getChild() hierarchy}
* from a plain sequence of them
* <p/>
* Not thread-safe.
@@ -27,29 +27,29 @@ import org.jetbrains.annotations.Nullable;
* @author Denis Zhdanov
* @since 8/8/12 1:23 PM
*/
public class HierarchicalArrangementSettingsNode {
public class HierarchicalArrangementConditionNode {
@NotNull private final ArrangementSettingsNode myCurrent;
@Nullable private HierarchicalArrangementSettingsNode myChild;
@NotNull private final ArrangementMatchCondition myCurrent;
@Nullable private HierarchicalArrangementConditionNode myChild;
public HierarchicalArrangementSettingsNode(@NotNull ArrangementSettingsNode current) {
public HierarchicalArrangementConditionNode(@NotNull ArrangementMatchCondition current) {
myCurrent = current;
}
@NotNull
public ArrangementSettingsNode getCurrent() {
public ArrangementMatchCondition getCurrent() {
return myCurrent;
}
@Nullable
public HierarchicalArrangementSettingsNode getChild() {
public HierarchicalArrangementConditionNode getChild() {
return myChild;
}
public void setChild(@Nullable HierarchicalArrangementSettingsNode child) {
public void setChild(@Nullable HierarchicalArrangementConditionNode child) {
myChild = child;
}
@Override
public String toString() {
return myCurrent.toString();
@@ -15,10 +15,9 @@
*/
package com.intellij.psi.codeStyle.arrangement.settings;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsCompositeNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNodeVisitor;
import com.intellij.psi.codeStyle.arrangement.model.*;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
@@ -27,7 +26,7 @@ import java.util.List;
import java.util.Set;
/**
* Encapsulates information about {@link ArrangementSettingsNode standard arrangement match rule settings}.
* Encapsulates information about {@link ArrangementMatchCondition standard arrangement match rule settings}.
* <p/>
* Not thread-safe.
*
@@ -36,23 +35,23 @@ import java.util.Set;
*/
public class ArrangementMatcherSettings implements Cloneable {
@NotNull private final List<ArrangementSettingsNode> myConditions = new ArrayList<ArrangementSettingsNode>();
@NotNull private final Set<Object> myValues = new HashSet<Object>();
@NotNull private final ArrangementSettingsNodeVisitor myAddVisitor = new MyAddVisitor();
@NotNull private final ArrangementSettingsNodeVisitor myRemoveVisitor = new MyRemoveVisitor();
@NotNull private final List<ArrangementMatchCondition> myConditions = new ArrayList<ArrangementMatchCondition>();
@NotNull private final Set<Object> myValues = new HashSet<Object>();
@NotNull private final ArrangementSettingsNodeVisitor myAddVisitor = new MyAddVisitor();
@NotNull private final ArrangementSettingsNodeVisitor myRemoveVisitor = new MyRemoveVisitor();
@NotNull
public List<ArrangementSettingsNode> getConditions() {
public List<ArrangementMatchCondition> getConditions() {
return myConditions;
}
public boolean addCondition(@NotNull ArrangementSettingsNode condition) {
public boolean addCondition(@NotNull ArrangementMatchCondition condition) {
int size = myConditions.size();
condition.invite(myAddVisitor);
return myConditions.size() > size;
}
public boolean removeCondition(@NotNull ArrangementSettingsNode condition) {
public boolean removeCondition(@NotNull ArrangementMatchCondition condition) {
int size = myConditions.size();
condition.invite(myRemoveVisitor);
return myConditions.size() < size;
@@ -72,14 +71,14 @@ public class ArrangementMatcherSettings implements Cloneable {
private class MyAddVisitor implements ArrangementSettingsNodeVisitor {
@Override
public void visit(@NotNull ArrangementSettingsAtomNode node) {
myConditions.add(node);
myValues.add(node.getValue());
public void visit(@NotNull ArrangementAtomMatchCondition setting) {
myConditions.add(setting);
myValues.add(setting.getValue());
}
@Override
public void visit(@NotNull ArrangementSettingsCompositeNode node) {
for (ArrangementSettingsNode n : node.getOperands()) {
public void visit(@NotNull ArrangementCompositeMatchCondition setting) {
for (ArrangementMatchCondition n : setting.getOperands()) {
n.invite(this);
}
}
@@ -87,14 +86,14 @@ public class ArrangementMatcherSettings implements Cloneable {
private class MyRemoveVisitor implements ArrangementSettingsNodeVisitor {
@Override
public void visit(@NotNull ArrangementSettingsAtomNode node) {
myConditions.remove(node);
myValues.remove(node.getValue());
public void visit(@NotNull ArrangementAtomMatchCondition setting) {
myConditions.remove(setting);
myValues.remove(setting.getValue());
}
@Override
public void visit(@NotNull ArrangementSettingsCompositeNode node) {
for (ArrangementSettingsNode n : node.getOperands()) {
public void visit(@NotNull ArrangementCompositeMatchCondition setting) {
for (ArrangementMatchCondition n : setting.getOperands()) {
n.invite(this);
}
}
@@ -15,8 +15,8 @@
*/
package com.intellij.psi.codeStyle.arrangement.settings;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementConditionNode;
import org.jetbrains.annotations.NotNull;
/**
@@ -39,12 +39,12 @@ public interface ArrangementSettingsGrouper {
* |
* ---public---static---final
* </pre>
* That means that we'll return a {@link HierarchicalArrangementSettingsNode} with condition <code>'type: field'</code> and
* That means that we'll return a {@link HierarchicalArrangementConditionNode} with condition <code>'type: field'</code> and
* a single child node with composite <code>'AND'</code> condition <code>'modifier: public; modifier: static; modifier: final'</code>.
*
* @param node settings node which conditions should be grouped
* @return grouping-aware node
*/
@NotNull
HierarchicalArrangementSettingsNode group(@NotNull ArrangementSettingsNode node);
HierarchicalArrangementConditionNode group(@NotNull ArrangementMatchCondition node);
}
@@ -17,7 +17,7 @@ package com.intellij.psi.codeStyle.arrangement.settings;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -41,7 +41,7 @@ public interface ArrangementStandardSettingsAware {
* (<code>null</code> to indicate a query if given entry type is supported in general)
* @return <code>true</code> if given entry type is supported; <code>false</code> otherwise
*/
boolean isEnabled(@NotNull ArrangementEntryType type, @Nullable ArrangementSettingsNode current);
boolean isEnabled(@NotNull ArrangementEntryType type, @Nullable ArrangementMatchCondition current);
/**
* Allows to answer if given modifier can be applied for the rule specified by the given settings node.
@@ -51,7 +51,7 @@ public interface ArrangementStandardSettingsAware {
* (<code>null</code> to indicate a query if given modifier is supported in general)
* @return <code>true</code> if given modifier is supported; <code>false</code> otherwise
*/
boolean isEnabled(@NotNull ArrangementModifier modifier, @Nullable ArrangementSettingsNode current);
boolean isEnabled(@NotNull ArrangementModifier modifier, @Nullable ArrangementMatchCondition current);
/**
* @return collections of mutual exclusion settings. E.g. not more than one visibility modifier can be used for a single
@@ -15,8 +15,8 @@
*/
package com.intellij.psi.codeStyle.arrangement.settings;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementConditionNode;
import org.jetbrains.annotations.NotNull;
/**
@@ -29,8 +29,8 @@ public class DefaultArrangementSettingsGrouper implements ArrangementSettingsGro
@NotNull
@Override
public HierarchicalArrangementSettingsNode group(@NotNull ArrangementSettingsNode node) {
public HierarchicalArrangementConditionNode group(@NotNull ArrangementMatchCondition node) {
// Don't group.
return new HierarchicalArrangementSettingsNode(node);
return new HierarchicalArrangementConditionNode(node);
}
}
@@ -16,9 +16,9 @@
package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsCompositeNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNodeVisitor;
import com.intellij.ui.awt.RelativePoint;
import org.jetbrains.annotations.NotNull;
@@ -26,13 +26,14 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* {@link ArrangementNodeComponent Component} for showing {@link ArrangementSettingsCompositeNode composite nodes}.
* {@link ArrangementNodeComponent Component} for showing {@link ArrangementCompositeMatchCondition composite nodes}.
* <p/>
* Not thread-safe.
*
@@ -45,35 +46,35 @@ public class ArrangementAndNodeComponent extends JPanel implements ArrangementNo
@NotNull private final List<ArrangementNodeComponent> myComponents = new ArrayList<ArrangementNodeComponent>();
@NotNull private final ArrangementSettingsCompositeNode mySettingsNode;
@Nullable private Rectangle myScreenBounds;
@NotNull private final ArrangementCompositeMatchCondition mySetting;
@Nullable private Rectangle myScreenBounds;
public ArrangementAndNodeComponent(@NotNull ArrangementSettingsCompositeNode node,
public ArrangementAndNodeComponent(@NotNull ArrangementCompositeMatchCondition setting,
@NotNull ArrangementNodeComponentFactory factory,
@NotNull ArrangementNodeDisplayManager manager)
{
mySettingsNode = node;
mySetting = setting;
setLayout(null);
int x = 0;
final Map<Object, ArrangementSettingsNode> operands = new HashMap<Object, ArrangementSettingsNode>();
final Map<Object, ArrangementMatchCondition> operands = new HashMap<Object, ArrangementMatchCondition>();
ArrangementSettingsNodeVisitor visitor = new ArrangementSettingsNodeVisitor() {
@Override
public void visit(@NotNull ArrangementSettingsAtomNode node) {
public void visit(@NotNull ArrangementAtomMatchCondition node) {
operands.put(node.getValue(), node);
}
@Override
public void visit(@NotNull ArrangementSettingsCompositeNode node) {
operands.put(node, node);
public void visit(@NotNull ArrangementCompositeMatchCondition node) {
operands.put(node, node);
}
};
for (ArrangementSettingsNode operand : node.getOperands()) {
for (ArrangementMatchCondition operand : setting.getOperands()) {
operand.invite(visitor);
}
List<Object> ordered = manager.sort(operands.keySet());
for (Object key : ordered) {
ArrangementSettingsNode operand = operands.get(key);
ArrangementMatchCondition operand = operands.get(key);
assert operand != null;
ArrangementNodeComponent component = factory.getComponent(operand);
myComponents.add(component);
@@ -87,8 +88,8 @@ public class ArrangementAndNodeComponent extends JPanel implements ArrangementNo
@NotNull
@Override
public ArrangementSettingsNode getSettingsNode() {
return mySettingsNode;
public ArrangementMatchCondition getMatchCondition() {
return mySetting;
}
@NotNull
@@ -194,6 +195,30 @@ public class ArrangementAndNodeComponent extends JPanel implements ArrangementNo
}
}
@Override
public Rectangle handleMouseMove(@NotNull MouseEvent event) {
Point location = event.getLocationOnScreen();
for (ArrangementNodeComponent component : myComponents) {
Rectangle bounds = component.getScreenBounds();
if (bounds != null && bounds.contains(location)) {
return component.handleMouseMove(event);
}
}
return null;
}
@Override
public void handleMouseClick(@NotNull MouseEvent event) {
Point location = event.getLocationOnScreen();
for (ArrangementNodeComponent component : myComponents) {
Rectangle bounds = component.getScreenBounds();
if (bounds != null && bounds.contains(location)) {
component.handleMouseClick(event);
return;
}
}
}
@Override
public String toString() {
return String.format("(%s)", StringUtil.join(myComponents, " and "));
@@ -15,9 +15,11 @@
*/
package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
import com.intellij.openapi.actionSystem.impl.ActionButton;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.Consumer;
import com.intellij.util.ui.GridBag;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
@@ -25,9 +27,12 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
/**
* // TODO den add doc
* {@link ArrangementNodeComponent} for {@link ArrangementAtomMatchCondition} representation.
* <p/>
* Not thread-safe.
*
* @author Denis Zhdanov
* @since 8/8/12 10:06 AM
@@ -68,7 +73,9 @@ public class ArrangementAtomNodeComponent implements ArrangementNodeComponent {
}
};
@NotNull private final ArrangementSettingsAtomNode mySettingsNode;
@NotNull private final ArrangementAtomMatchCondition myCondition;
@Nullable private final ActionButton myCloseButton;
@Nullable private final Consumer<ArrangementAtomMatchCondition> myCloseCallback;
@Nullable private Dimension mySize;
@Nullable private Rectangle myScreenBounds;
@@ -76,18 +83,61 @@ public class ArrangementAtomNodeComponent implements ArrangementNodeComponent {
private boolean myEnabled = true;
private boolean mySelected;
private boolean myInverted;
private boolean myCloseButtonHovered;
public ArrangementAtomNodeComponent(@NotNull ArrangementNodeDisplayManager manager, @NotNull ArrangementSettingsAtomNode node) {
mySettingsNode = node;
public ArrangementAtomNodeComponent(@NotNull ArrangementNodeDisplayManager manager,
@NotNull ArrangementAtomMatchCondition condition,
@Nullable Consumer<ArrangementAtomMatchCondition> closeCallback)
{
myCondition = condition;
myCloseCallback = closeCallback;
myLabel.setHorizontalAlignment(SwingConstants.CENTER);
myLabel.setText(manager.getDisplayValue(node));
mySize = new Dimension(manager.getMaxWidth(node.getType()), myLabel.getPreferredSize().height);
myLabel.setText(manager.getDisplayValue(condition));
int width = manager.getMaxWidth(condition.getType());
int height = myLabel.getPreferredSize().height;
final ArrangementRemoveConditionAction action;
if (closeCallback == null) {
myCloseButton = null;
action = null;
}
else {
action = new ArrangementRemoveConditionAction();
Icon buttonIcon = action.getTemplatePresentation().getIcon();
Dimension buttonSize = new Dimension(buttonIcon.getIconWidth(), buttonIcon.getIconHeight());
myCloseButton = new ActionButton(action, action.getTemplatePresentation().clone(), ArrangementConstants.RULE_TREE_PLACE, buttonSize) {
@Override
protected Icon getIcon() {
return myCloseButtonHovered ? action.getTemplatePresentation().getHoveredIcon() : action.getTemplatePresentation().getIcon();
}
};
Dimension preferredButtonSize = myCloseButton.getPreferredSize();
width += preferredButtonSize.width;
height = Math.max(height, preferredButtonSize.height);
}
mySize = new Dimension(width, height);
GridBagConstraints constraints = new GridBag().anchor(GridBagConstraints.CENTER).insets(0, 0, 0, 0);
JPanel labelPanel = new JPanel(new GridBagLayout());
JPanel labelPanel = new JPanel(new GridBagLayout()) {
@Override
public void paint(Graphics g) {
Rectangle buttonBounds = getCloseButtonScreenLocation();
if (buttonBounds != null && action != null) {
Point mouseScreenLocation = MouseInfo.getPointerInfo().getLocation();
myCloseButtonHovered = buttonBounds.contains(mouseScreenLocation);
}
super.paint(g);
}
};
myLabel.setBackground(Color.red);
labelPanel.add(myLabel, constraints);
if (myCloseButton != null) {
labelPanel.add(myCloseButton, new GridBag().anchor(GridBagConstraints.EAST).insets(0, 0, 0, 0));
}
labelPanel.setBorder(IdeBorderFactory.createEmptyBorder(PADDING));
labelPanel.setOpaque(false);
@@ -113,8 +163,8 @@ public class ArrangementAtomNodeComponent implements ArrangementNodeComponent {
@NotNull
@Override
public ArrangementSettingsAtomNode getSettingsNode() {
return mySettingsNode;
public ArrangementAtomMatchCondition getMatchCondition() {
return myCondition;
}
@NotNull
@@ -168,6 +218,38 @@ public class ArrangementAtomNodeComponent implements ArrangementNodeComponent {
myInverted = inverted;
}
@Nullable
@Override
public Rectangle handleMouseMove(@NotNull MouseEvent event) {
Rectangle buttonBounds = getCloseButtonScreenLocation();
if (buttonBounds == null) {
return null;
}
boolean mouseOverButton = buttonBounds.contains(event.getLocationOnScreen());
return (mouseOverButton ^ myCloseButtonHovered) ? buttonBounds : null;
}
@Override
public void handleMouseClick(@NotNull MouseEvent event) {
Rectangle buttonBounds = getCloseButtonScreenLocation();
if (buttonBounds != null && buttonBounds.contains(event.getLocationOnScreen()) && myCloseCallback != null) {
myCloseCallback.consume(myCondition);
}
}
@Nullable
private Rectangle getCloseButtonScreenLocation() {
if (myCloseButton == null || myScreenBounds == null) {
return null;
}
Rectangle buttonBounds = myCloseButton.getBounds();
buttonBounds = SwingUtilities.convertRectangle(myCloseButton.getParent(), buttonBounds, myRenderer);
buttonBounds.x += myScreenBounds.x;
buttonBounds.y += myScreenBounds.y;
return buttonBounds;
}
@Override
public String toString() {
return myLabel.getText();
@@ -18,9 +18,9 @@ package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementConditionNode;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementMatcherSettings;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import com.intellij.util.containers.Stack;
@@ -58,7 +58,7 @@ public class ArrangementConfigUtil {
*/
@NotNull
public static Map<ArrangementSettingType, Collection<?>> buildAvailableOptions(@NotNull ArrangementStandardSettingsAware filter,
@Nullable ArrangementSettingsNode settings)
@Nullable ArrangementMatchCondition settings)
{
Map<ArrangementSettingType, Collection<?>> result = new EnumMap<ArrangementSettingType, Collection<?>>(ArrangementSettingType.class);
processData(filter, settings, result, ArrangementSettingType.TYPE, ArrangementEntryType.values());
@@ -67,7 +67,7 @@ public class ArrangementConfigUtil {
}
private static <T> void processData(@NotNull ArrangementStandardSettingsAware filter,
@Nullable ArrangementSettingsNode settings,
@Nullable ArrangementMatchCondition settings,
@NotNull Map<ArrangementSettingType, Collection<?>> result,
@NotNull ArrangementSettingType type,
@NotNull T[] values)
@@ -89,7 +89,7 @@ public class ArrangementConfigUtil {
public static boolean isEnabled(@NotNull Object conditionId,
@NotNull ArrangementStandardSettingsAware filter,
@Nullable ArrangementSettingsNode settings)
@Nullable ArrangementMatchCondition settings)
{
if (conditionId instanceof ArrangementEntryType) {
return filter.isEnabled((ArrangementEntryType)conditionId, settings);
@@ -121,15 +121,15 @@ public class ArrangementConfigUtil {
return null;
}
public static int getDepth(@NotNull HierarchicalArrangementSettingsNode node) {
HierarchicalArrangementSettingsNode child = node.getChild();
public static int getDepth(@NotNull HierarchicalArrangementConditionNode node) {
HierarchicalArrangementConditionNode child = node.getChild();
return child == null ? 1 : 1 + getDepth(child);
}
@NotNull
public static HierarchicalArrangementSettingsNode getLast(@NotNull HierarchicalArrangementSettingsNode node) {
HierarchicalArrangementSettingsNode result = node;
for (HierarchicalArrangementSettingsNode child = node.getChild(); child != null; child = child.getChild()) {
public static HierarchicalArrangementConditionNode getLast(@NotNull HierarchicalArrangementConditionNode node) {
HierarchicalArrangementConditionNode result = node;
for (HierarchicalArrangementConditionNode child = node.getChild(); child != null; child = child.getChild()) {
result = child;
}
return result;
@@ -175,25 +175,25 @@ public class ArrangementConfigUtil {
/**
* @param uiParentNode UI tree node which should hold UI nodes created for representing given settings node;
* <code>null</code> as an indication that we want to create a standalone nodes hierarchy
* @param settingsNode settings node which should be represented at the UI tree denoted by the given UI tree node
* @param conditionNode settings node which should be represented at the UI tree denoted by the given UI tree node
* @param model tree model to use for the tree modification
* @return pair {@code (bottom-most leaf node created; number of rows created)}
*/
@NotNull
public static Pair<ArrangementTreeNode, Integer> map(@Nullable ArrangementTreeNode uiParentNode,
@NotNull HierarchicalArrangementSettingsNode settingsNode,
@NotNull HierarchicalArrangementConditionNode conditionNode,
@Nullable DefaultTreeModel model)
{
ArrangementTreeNode uiNode = null;
int rowsCreated = 0;
if (uiParentNode != null && uiParentNode.getChildCount() > 0) {
ArrangementTreeNode child = uiParentNode.getChildAt(uiParentNode.getChildCount() - 1);
if (settingsNode.getCurrent().equals(child.getBackingSetting())) {
if (conditionNode.getCurrent().equals(child.getBackingSetting())) {
uiNode = child;
}
}
if (uiNode == null) {
uiNode = new ArrangementTreeNode(settingsNode.getCurrent());
uiNode = new ArrangementTreeNode(conditionNode.getCurrent());
if (uiParentNode != null) {
if (model == null) {
uiParentNode.add(uiNode);
@@ -205,9 +205,9 @@ public class ArrangementConfigUtil {
rowsCreated++;
}
ArrangementTreeNode leaf = uiNode;
HierarchicalArrangementSettingsNode childSettingsNode = settingsNode.getChild();
if (childSettingsNode != null) {
Pair<ArrangementTreeNode, Integer> pair = map(uiNode, childSettingsNode, model);
HierarchicalArrangementConditionNode childConditionNode = conditionNode.getChild();
if (childConditionNode != null) {
Pair<ArrangementTreeNode, Integer> pair = map(uiNode, childConditionNode, model);
leaf = pair.first;
rowsCreated += pair.second;
}
@@ -527,13 +527,13 @@ public class ArrangementConfigUtil {
}
private static boolean hasEqualSetting(@NotNull ArrangementTreeNode node1, @NotNull ArrangementTreeNode node2) {
ArrangementSettingsNode setting1 = node1.getBackingSetting();
ArrangementSettingsNode setting2 = node2.getBackingSetting();
if (setting1 == null) {
return setting2 == null;
ArrangementMatchCondition matchCondition1 = node1.getBackingSetting();
ArrangementMatchCondition matchCondition2 = node2.getBackingSetting();
if (matchCondition1 == null) {
return matchCondition2 == null;
}
else {
return setting1.equals(setting2);
return matchCondition1.equals(matchCondition2);
}
}
}
@@ -25,6 +25,7 @@ public class ArrangementConstants {
@NonNls public static final String ACTION_GROUP_RULE_EDITOR_CONTEXT_MENU = "Arrangement.RuleEditor.Context.Menu";
@NonNls public static final String RULE_EDITOR_PLACE = "Arrangement.RuleEditor.Place";
@NonNls public static final String RULE_TREE_PLACE = "Arrangement.RuleTree.Place";
private ArrangementConstants() {
}
@@ -16,8 +16,8 @@
package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import com.intellij.util.ui.GridBag;
import com.intellij.util.ui.MultiRowFlowPanel;
@@ -80,7 +80,7 @@ public class ArrangementMatcherRuleEditor extends JPanel {
JPanel valuesPanel = new MultiRowFlowPanel(FlowLayout.LEFT, 8, 5);
for (Object value : manager.sort(values)) {
ArrangementAtomNodeComponent component = new ArrangementAtomNodeComponent(manager, new ArrangementSettingsAtomNode(key, value));
ArrangementAtomNodeComponent component = new ArrangementAtomNodeComponent(manager, new ArrangementAtomMatchCondition(key, value), null);
myComponents.put(value, component);
valuesPanel.add(component.getUiComponent());
}
@@ -110,7 +110,7 @@ public class ArrangementMatcherRuleEditor extends JPanel {
return;
}
Map<ArrangementSettingType, Collection<?>> available = ArrangementConfigUtil.buildAvailableOptions(myFilter, model.getSettingsNode());
Map<ArrangementSettingType, Collection<?>> available = ArrangementConfigUtil.buildAvailableOptions(myFilter, model.getMatchCondition());
for (Collection<?> ids : available.values()) {
for (Object id : ids) {
ArrangementAtomNodeComponent component = myComponents.get(id);
@@ -138,30 +138,30 @@ public class ArrangementMatcherRuleEditor extends JPanel {
if (component == null) {
return;
}
ArrangementSettingsAtomNode settingsNode = component.getSettingsNode();
boolean remove = myModel.hasCondition(settingsNode.getValue());
ArrangementAtomMatchCondition setting = component.getMatchCondition();
boolean remove = myModel.hasCondition(setting.getValue());
component.setSelected(!remove);
repaintComponent(component);
if (remove) {
myModel.removeAndCondition(settingsNode);
myModel.removeAndCondition(setting);
return;
}
Collection<Set<?>> mutexes = myFilter.getMutexes();
for (Set<?> mutex : mutexes) {
if (!mutex.contains(settingsNode.getValue())) {
if (!mutex.contains(setting.getValue())) {
continue;
}
for (Object key : mutex) {
if (myModel.hasCondition(key)) {
ArrangementAtomNodeComponent componentToDeselect = myComponents.get(key);
componentToDeselect.setSelected(false);
myModel.removeAndCondition(componentToDeselect.getSettingsNode());
myModel.removeAndCondition(componentToDeselect.getMatchCondition());
repaintComponent(componentToDeselect);
}
}
}
myModel.addAndCondition(settingsNode);
myModel.addAndCondition(setting);
}
@Nullable
@@ -15,13 +15,14 @@
*/
package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.ui.awt.RelativePoint;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
/**
* // TODO den add doc
@@ -32,7 +33,7 @@ import java.awt.*;
public interface ArrangementNodeComponent {
@NotNull
ArrangementSettingsNode getSettingsNode();
ArrangementMatchCondition getMatchCondition();
// TODO den add doc
@NotNull
@@ -54,4 +55,19 @@ public interface ArrangementNodeComponent {
* @param selected flag that indicates if current component should be drawn as 'selected'
*/
void setSelected(boolean selected);
/**
* Instructs current component about mose move event.
* <p/>
* Primary intention is to allow to react on event like 'on mouse hover' etc. We can't do that by subscribing to the
* mouse events at the {@link #getUiComponent() corresponding UI control} because it's used only as a renderer and is not put
* to the containers hierarchy, hence, doesn't receive mouse events.
*
* @param event target mouse move event
* @return bounds to be repainted (in screen coordinates) if any; <code>null</code> otherwise
*/
@Nullable
Rectangle handleMouseMove(@NotNull MouseEvent event);
void handleMouseClick(@NotNull MouseEvent event);
}
@@ -17,6 +17,7 @@ package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.codeStyle.arrangement.model.*;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
/**
@@ -25,25 +26,30 @@ import org.jetbrains.annotations.NotNull;
*/
public class ArrangementNodeComponentFactory {
@NotNull private final ArrangementNodeDisplayManager myDisplayManager;
@NotNull private final ArrangementNodeDisplayManager myDisplayManager;
private Consumer<ArrangementAtomMatchCondition> myRemoveConditionCallback;
public ArrangementNodeComponentFactory(@NotNull ArrangementNodeDisplayManager manager) {
public ArrangementNodeComponentFactory(@NotNull ArrangementNodeDisplayManager manager,
@NotNull Consumer<ArrangementAtomMatchCondition> removeConditionCallback)
{
myDisplayManager = manager;
myRemoveConditionCallback = removeConditionCallback;
}
@NotNull
public ArrangementNodeComponent getComponent(@NotNull ArrangementSettingsNode node) {
public ArrangementNodeComponent getComponent(@NotNull ArrangementMatchCondition node) {
final Ref<ArrangementNodeComponent> ref = new Ref<ArrangementNodeComponent>();
node.invite(new ArrangementSettingsNodeVisitor() {
@Override
public void visit(@NotNull ArrangementSettingsAtomNode node) {
ref.set(new ArrangementAtomNodeComponent(myDisplayManager, node));
public void visit(@NotNull ArrangementAtomMatchCondition setting) {
ref.set(new ArrangementAtomNodeComponent(myDisplayManager, setting, myRemoveConditionCallback));
}
@Override
public void visit(@NotNull ArrangementSettingsCompositeNode node) {
switch (node.getOperator()) {
case AND: ref.set(new ArrangementAndNodeComponent(node, ArrangementNodeComponentFactory.this, myDisplayManager)); break;
public void visit(@NotNull ArrangementCompositeMatchCondition setting) {
switch (setting.getOperator()) {
case AND:
ref.set(new ArrangementAndNodeComponent(setting, ArrangementNodeComponentFactory.this, myDisplayManager)); break;
case OR: // TODO den implement
}
}
@@ -18,8 +18,8 @@ package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsAware;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsRepresentationAware;
import gnu.trove.TObjectIntHashMap;
@@ -67,8 +67,8 @@ public class ArrangementNodeDisplayManager {
}
@NotNull
public String getDisplayValue(@NotNull ArrangementSettingsAtomNode node) {
return getDisplayValue(node.getValue());
public String getDisplayValue(@NotNull ArrangementAtomMatchCondition setting) {
return getDisplayValue(setting.getValue());
}
@NotNull
@@ -0,0 +1,43 @@
/*
* Copyright 2000-2012 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.application.options.codeStyle.arrangement;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import javax.swing.*;
/**
* @author Denis Zhdanov
* @since 8/23/12 11:41 AM
*/
public class ArrangementRemoveConditionAction extends AnAction {
private static final Icon ICON = AllIcons.Actions.CloseNew;
private static final Icon HOVER_ICON = AllIcons.Actions.CloseNewHovered;
public ArrangementRemoveConditionAction() {
getTemplatePresentation().setIcon(ICON);
getTemplatePresentation().setHoveredIcon(HOVER_ICON);
}
@Override
public void actionPerformed(AnActionEvent e) {
// TODO den implement
System.out.println("ArrangementRemoveConditionAction.actionPerformed()");
}
}
@@ -17,15 +17,13 @@ package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import org.jetbrains.annotations.NotNull;
import javax.swing.tree.TreeNode;
/**
* Combines and encapsulates information about arrangement matcher rules representation (tree nodes) and
* underlying {@link ArrangementSettingsNode data model}.
* underlying {@link ArrangementMatchCondition data model}.
* <p/>
* Implementations of this interface are not obliged to be thread-safe.
*
@@ -35,7 +33,7 @@ import javax.swing.tree.TreeNode;
public interface ArrangementRuleEditingModel {
@NotNull
ArrangementSettingsNode getSettingsNode();
ArrangementMatchCondition getMatchCondition();
/**
* Allows to answer if current model has a registered condition for the given key. A key is expected to be one of the standard
@@ -47,7 +45,7 @@ public interface ArrangementRuleEditingModel {
*/
boolean hasCondition(@NotNull Object key);
void addAndCondition(@NotNull ArrangementSettingsAtomNode node);
void addAndCondition(@NotNull ArrangementAtomMatchCondition condition);
void removeAndCondition(@NotNull ArrangementSettingsNode node);
void removeAndCondition(@NotNull ArrangementMatchCondition condition);
}
@@ -17,8 +17,8 @@ package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.HierarchicalArrangementConditionNode;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementSettingsGrouper;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementStandardSettingsRepresentationAware;
import gnu.trove.TIntObjectHashMap;
@@ -31,7 +31,7 @@ import javax.swing.tree.TreeNode;
/**
* Holds glue logic between arrangement settings and their representation -
* '{@link ArrangementSettingsNode} -&gt; {@link ArrangementRuleEditingModel}'
* '{@link ArrangementMatchCondition} -&gt; {@link ArrangementRuleEditingModel}'
* <p/>
* Thread-safe.
*
@@ -45,11 +45,11 @@ public class ArrangementRuleEditingModelBuilder {
* <pre>
* <ol>
* <li>
* {@link HierarchicalArrangementSettingsNode Groups} given {@link ArrangementSettingsNode settings} using
* the given {@link ArrangementSettingsGrouper#group(ArrangementSettingsNode) strategy};
* {@link HierarchicalArrangementConditionNode Groups} given {@link ArrangementMatchCondition settings} using
* the given {@link ArrangementSettingsGrouper#group(ArrangementMatchCondition) strategy};
* </li>
* <li>
* Build {@link DefaultMutableTreeNode tree nodes} for the {@link HierarchicalArrangementSettingsNode groiping-aware nodes}
* Build {@link DefaultMutableTreeNode tree nodes} for the {@link HierarchicalArrangementConditionNode groiping-aware nodes}
* and register them within the target tree structure (denoted by the given settings root element);
* </li>
* <li>
@@ -58,7 +58,7 @@ public class ArrangementRuleEditingModelBuilder {
* </ol>
* </pre>
*
* @param setting target settings to process
* @param matchCondition target settings to process
* @param tree UI tree which shows arrangement matcher rules
* @param root UI tree settings root to use (may be not the same as the tree root)
* @param grouper strategy that knows how to
@@ -67,7 +67,7 @@ public class ArrangementRuleEditingModelBuilder {
* @param rowMappings container to hold built {@link ArrangementRuleEditingModel editing models} (UI tree row numbers are used as keys)
*/
@SuppressWarnings("MethodMayBeStatic")
public void build(@NotNull ArrangementSettingsNode setting,
public void build(@NotNull ArrangementMatchCondition matchCondition,
@NotNull JTree tree,
@NotNull ArrangementTreeNode root,
@NotNull ArrangementSettingsGrouper grouper,
@@ -92,14 +92,14 @@ public class ArrangementRuleEditingModelBuilder {
initialInsertRow--;
}
HierarchicalArrangementSettingsNode grouped = grouper.group(setting);
HierarchicalArrangementConditionNode grouped = grouper.group(matchCondition);
DefaultTreeModel treeModel = (DefaultTreeModel)tree.getModel();
Pair<ArrangementTreeNode, Integer> pair = ArrangementConfigUtil.map(root, grouped, treeModel);
ArrangementTreeNode topMostNode = ArrangementConfigUtil.getLastBefore(pair.first, root);
int row = initialInsertRow + pair.second - 1;
ArrangementRuleEditingModelImpl model = new ArrangementRuleEditingModelImpl(
treeModel,
setting,
matchCondition,
topMostNode,
pair.first,
grouper,
@@ -41,14 +41,14 @@ public class ArrangementRuleEditingModelImpl implements ArrangementRuleEditingMo
@NotNull private final Set<Listener> myListeners = new HashSet<Listener>();
@NotNull private final Set<Object> myConditions = new HashSet<Object>();
@NotNull private final DefaultTreeModel myTreeModel;
@NotNull private final ArrangementSettingsGrouper myGrouper;
private final boolean myRootVisible;
@NotNull private final DefaultTreeModel myTreeModel;
@NotNull private final ArrangementSettingsGrouper myGrouper;
private final boolean myRootVisible;
@NotNull private ArrangementTreeNode myTopMost;
@NotNull private ArrangementTreeNode myBottomMost;
@NotNull private ArrangementSettingsNode mySettingsNode;
private int myRow;
@NotNull private ArrangementTreeNode myTopMost;
@NotNull private ArrangementTreeNode myBottomMost;
@NotNull private ArrangementMatchCondition myMatchCondition;
private int myRow;
/**
* Creates new <code>ArrangementRuleEditingModelImpl</code> object.
@@ -57,7 +57,7 @@ public class ArrangementRuleEditingModelImpl implements ArrangementRuleEditingMo
* to generate corresponding events automatically
* @param node backing settings node
* @param topMost there is a possible case that a single settings node is shown in more than one visual line
* ({@link HierarchicalArrangementSettingsNode}). This argument is the top-most UI node used for the
* ({@link HierarchicalArrangementConditionNode}). This argument is the top-most UI node used for the
* settings node representation
* @param bottomMost bottom-most UI node used for the given settings node representation
* @param grouper strategy that encapsulates information on how settings node should be displayed
@@ -65,7 +65,7 @@ public class ArrangementRuleEditingModelImpl implements ArrangementRuleEditingMo
* @param rootVisible determines if the root should be count during rows calculations
*/
public ArrangementRuleEditingModelImpl(@NotNull DefaultTreeModel model,
@NotNull ArrangementSettingsNode node,
@NotNull ArrangementMatchCondition node,
@NotNull ArrangementTreeNode topMost,
@NotNull ArrangementTreeNode bottomMost,
@NotNull ArrangementSettingsGrouper grouper,
@@ -73,7 +73,7 @@ public class ArrangementRuleEditingModelImpl implements ArrangementRuleEditingMo
boolean rootVisible)
{
myTreeModel = model;
mySettingsNode = node;
myMatchCondition = node;
myTopMost = topMost;
myBottomMost = bottomMost;
myGrouper = grouper;
@@ -86,7 +86,7 @@ public class ArrangementRuleEditingModelImpl implements ArrangementRuleEditingMo
myConditions.clear();
CONDITIONS_BUILDER.conditions = myConditions;
try {
mySettingsNode.invite(CONDITIONS_BUILDER);
myMatchCondition.invite(CONDITIONS_BUILDER);
}
finally {
CONDITIONS_BUILDER.conditions = null;
@@ -95,8 +95,8 @@ public class ArrangementRuleEditingModelImpl implements ArrangementRuleEditingMo
@NotNull
@Override
public ArrangementSettingsNode getSettingsNode() {
return mySettingsNode;
public ArrangementMatchCondition getMatchCondition() {
return myMatchCondition;
}
public int getRow() {
@@ -129,8 +129,8 @@ public class ArrangementRuleEditingModelImpl implements ArrangementRuleEditingMo
// No refresh is necessary.
return;
}
ArrangementSettingsNode setting = myTopMost.getBackingSetting();
if (setting != null && setting.equals(node.getBackingSetting())) {
ArrangementMatchCondition matchCondition = myTopMost.getBackingSetting();
if (matchCondition != null && matchCondition.equals(node.getBackingSetting())) {
myTopMost = node;
return;
}
@@ -139,45 +139,45 @@ public class ArrangementRuleEditingModelImpl implements ArrangementRuleEditingMo
}
@Override
public void addAndCondition(@NotNull ArrangementSettingsAtomNode node) {
TIntIntHashMap rowChanges = doAddAndCondition(node);
public void addAndCondition(@NotNull ArrangementAtomMatchCondition condition) {
TIntIntHashMap rowChanges = doAddAndCondition(condition);
refreshConditions();
notifyListeners(rowChanges);
}
@NotNull
private TIntIntHashMap doAddAndCondition(@NotNull ArrangementSettingsAtomNode node) {
ArrangementSettingsNode newNode = ArrangementUtil.and(mySettingsNode.clone(), node);
return applyNewSetting(newNode);
private TIntIntHashMap doAddAndCondition(@NotNull ArrangementAtomMatchCondition condition) {
ArrangementMatchCondition newNode = ArrangementUtil.and(myMatchCondition.clone(), condition);
return applyNewCondition(newNode);
}
@Override
public void removeAndCondition(@NotNull ArrangementSettingsNode node) {
TIntIntHashMap rowChanges = doRemoveAndCondition(node);
public void removeAndCondition(@NotNull ArrangementMatchCondition condition) {
TIntIntHashMap rowChanges = doRemoveAndCondition(condition);
refreshConditions();
notifyListeners(rowChanges);
}
@NotNull
private TIntIntHashMap doRemoveAndCondition(@NotNull ArrangementSettingsNode node) {
if (!(mySettingsNode instanceof ArrangementSettingsCompositeNode)) {
private TIntIntHashMap doRemoveAndCondition(@NotNull ArrangementMatchCondition node) {
if (!(myMatchCondition instanceof ArrangementCompositeMatchCondition)) {
return EMPTY_CHANGES;
}
ArrangementSettingsNode newNode = mySettingsNode.clone();
ArrangementSettingsCompositeNode composite = (ArrangementSettingsCompositeNode)newNode;
ArrangementMatchCondition newNode = myMatchCondition.clone();
ArrangementCompositeMatchCondition composite = (ArrangementCompositeMatchCondition)newNode;
composite.getOperands().remove(node);
if (composite.getOperands().size() == 1) {
newNode = composite.getOperands().iterator().next();
}
return applyNewSetting(newNode);
return applyNewCondition(newNode);
}
@NotNull
private TIntIntHashMap applyNewSetting(@NotNull ArrangementSettingsNode newNode) {
mySettingsNode = newNode;
HierarchicalArrangementSettingsNode grouped = myGrouper.group(newNode);
private TIntIntHashMap applyNewCondition(@NotNull ArrangementMatchCondition newNode) {
myMatchCondition = newNode;
HierarchicalArrangementConditionNode grouped = myGrouper.group(newNode);
int newDepth = ArrangementConfigUtil.getDepth(grouped);
int oldDepth = ArrangementConfigUtil.distance(myTopMost, myBottomMost);
if (oldDepth == newDepth) {
@@ -210,7 +210,7 @@ public class ArrangementRuleEditingModelImpl implements ArrangementRuleEditingMo
@Override
public String toString() {
return "model for " + mySettingsNode;
return "model for " + myMatchCondition;
}
private static class MyConditionsBuilder implements ArrangementSettingsNodeVisitor {
@@ -218,13 +218,13 @@ public class ArrangementRuleEditingModelImpl implements ArrangementRuleEditingMo
@NotNull Set<Object> conditions;
@Override
public void visit(@NotNull ArrangementSettingsAtomNode node) {
conditions.add(node.getValue());
public void visit(@NotNull ArrangementAtomMatchCondition setting) {
conditions.add(setting.getValue());
}
@Override
public void visit(@NotNull ArrangementSettingsCompositeNode node) {
for (ArrangementSettingsNode operand : node.getOperands()) {
public void visit(@NotNull ArrangementCompositeMatchCondition setting) {
for (ArrangementMatchCondition operand : setting.getOperands()) {
operand.invite(this);
}
}
@@ -17,13 +17,13 @@ package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryType;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementModifier;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingType;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsAtomNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsCompositeNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.*;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.settings.ArrangementSettingsGrouper;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.Consumer;
import gnu.trove.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -67,7 +67,12 @@ public class ArrangementRuleTree {
private boolean mySkipSelectionChange;
public ArrangementRuleTree(@NotNull ArrangementSettingsGrouper grouper, @NotNull ArrangementNodeDisplayManager displayManager) {
myFactory = new ArrangementNodeComponentFactory(displayManager);
myFactory = new ArrangementNodeComponentFactory(displayManager, new Consumer<ArrangementAtomMatchCondition>() {
@Override
public void consume(@NotNull ArrangementAtomMatchCondition setting) {
removeConditionFromActiveModel(setting);
}
});
myRoot = new ArrangementTreeNode(null);
myTreeModel = new DefaultTreeModel(myRoot);
myTree = new Tree(myTreeModel) {
@@ -117,6 +122,12 @@ public class ArrangementRuleTree {
}
}
});
myTree.addMouseMotionListener(new MouseAdapter() {
@Override
public void mouseMoved(MouseEvent e) {
onMouseMoved(e);
}
});
myTree.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
@@ -138,28 +149,28 @@ public class ArrangementRuleTree {
}
});
List<ArrangementSettingsNode> rules = new ArrayList<ArrangementSettingsNode>();
rules.add(new ArrangementSettingsCompositeNode(ArrangementSettingsCompositeNode.Operator.AND)
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.TYPE, ArrangementEntryType.FIELD))
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.PUBLIC))
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.STATIC))
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.FINAL)));
rules.add(new ArrangementSettingsCompositeNode(ArrangementSettingsCompositeNode.Operator.AND)
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.TYPE, ArrangementEntryType.FIELD))
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.PRIVATE)));
rules.add(new ArrangementSettingsCompositeNode(ArrangementSettingsCompositeNode.Operator.AND)
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.TYPE, ArrangementEntryType.METHOD))
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.PUBLIC)));
rules.add(new ArrangementSettingsCompositeNode(ArrangementSettingsCompositeNode.Operator.AND)
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.TYPE, ArrangementEntryType.METHOD))
.addOperand(new ArrangementSettingsAtomNode(ArrangementSettingType.MODIFIER, ArrangementModifier.PRIVATE)));
List<ArrangementMatchCondition> rules = new ArrayList<ArrangementMatchCondition>();
rules.add(new ArrangementCompositeMatchCondition(ArrangementCompositeMatchCondition.Operator.AND)
.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.TYPE, ArrangementEntryType.FIELD))
.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, ArrangementModifier.PUBLIC))
.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, ArrangementModifier.STATIC))
.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, ArrangementModifier.FINAL)));
rules.add(new ArrangementCompositeMatchCondition(ArrangementCompositeMatchCondition.Operator.AND)
.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.TYPE, ArrangementEntryType.FIELD))
.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, ArrangementModifier.PRIVATE)));
rules.add(new ArrangementCompositeMatchCondition(ArrangementCompositeMatchCondition.Operator.AND)
.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.TYPE, ArrangementEntryType.METHOD))
.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, ArrangementModifier.PUBLIC)));
rules.add(new ArrangementCompositeMatchCondition(ArrangementCompositeMatchCondition.Operator.AND)
.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.TYPE, ArrangementEntryType.METHOD))
.addOperand(new ArrangementAtomMatchCondition(ArrangementSettingType.MODIFIER, ArrangementModifier.PRIVATE)));
map(myRoot, rules, grouper);
expandAll(myTree, new TreePath(myRoot));
myTree.setShowsRootHandles(false);
myTree.setCellRenderer(new MyCellRenderer());
}
private void selectPreviousRule() {
ArrangementTreeNode currentSelectionBottom = getCurrentSelectionBottom();
@@ -282,12 +293,12 @@ public class ArrangementRuleTree {
}
private void map(@NotNull ArrangementTreeNode root,
@NotNull List<ArrangementSettingsNode> settings,
@NotNull List<ArrangementMatchCondition> matchConditions,
@NotNull ArrangementSettingsGrouper grouper)
{
ArrangementRuleEditingModelBuilder builder = new ArrangementRuleEditingModelBuilder();
for (ArrangementSettingsNode setting : settings) {
builder.build(setting, myTree, root, grouper, myModels);
for (ArrangementMatchCondition matchCondition : matchConditions) {
builder.build(matchCondition, myTree, root, grouper, myModels);
}
myModels.forEachValue(new TObjectProcedure<ArrangementRuleEditingModelImpl>() {
@Override
@@ -330,7 +341,7 @@ public class ArrangementRuleTree {
}
@NotNull
private ArrangementNodeComponent getNodeComponentAt(int row, @NotNull ArrangementSettingsNode node) {
private ArrangementNodeComponent getNodeComponentAt(int row, @NotNull ArrangementMatchCondition node) {
ArrangementNodeComponent result = myRenderers.get(row);
if (result == null) {
myRenderers.put(row, result = myFactory.getComponent(node));
@@ -338,9 +349,29 @@ public class ArrangementRuleTree {
return result;
}
private void removeConditionFromActiveModel(@NotNull ArrangementAtomMatchCondition condition) {
ArrangementRuleEditingModel model = getActiveModel();
if (model != null) {
model.removeAndCondition(condition);
notifySelectionListeners(model);
}
}
private void onMouseMoved(@NotNull MouseEvent e) {
ArrangementNodeComponent component = getNodeComponentAt(e.getLocationOnScreen());
if (component == null) {
return;
}
Rectangle changedScreenRectangle = component.handleMouseMove(e);
if (changedScreenRectangle != null) {
repaintScreenBounds(changedScreenRectangle);
}
}
private void onMouseClicked(@NotNull MouseEvent e) {
ArrangementNodeComponent component = getNodeComponentAt(e.getLocationOnScreen());
if (component != null) {
component.handleMouseClick(e);
return;
}
// Clear selection
@@ -381,12 +412,16 @@ public class ArrangementRuleTree {
private void repaintComponent(@NotNull ArrangementNodeComponent component) {
Rectangle bounds = component.getScreenBounds();
if (bounds != null) {
Point location = bounds.getLocation();
SwingUtilities.convertPointFromScreen(location, myTree);
myTree.repaint(location.x, location.y, bounds.width, bounds.height);
repaintScreenBounds(bounds);
}
}
private void repaintScreenBounds(@NotNull Rectangle bounds) {
Point location = bounds.getLocation();
SwingUtilities.convertPointFromScreen(location, myTree);
myTree.repaint(location.x, location.y, bounds.width, bounds.height);
}
private void notifySelectionListeners(@Nullable ArrangementRuleEditingModel model) {
for (ArrangementRuleSelectionListener listener : myListeners) {
if (model == null) {
@@ -437,9 +472,9 @@ public class ArrangementRuleTree {
myRenderers.remove(row);
myTreeModel.nodeChanged(node);
mySelectionModel.addSelectionPath(path);
ArrangementSettingsNode setting = node.getBackingSetting();
if (setting != null) {
getNodeComponentAt(row, setting).setSelected(true);
ArrangementMatchCondition matchCondition = node.getBackingSetting();
if (matchCondition != null) {
getNodeComponentAt(row, matchCondition).setSelected(true);
}
if (node == topMost) {
break;
@@ -471,7 +506,7 @@ public class ArrangementRuleTree {
int row,
boolean hasFocus)
{
ArrangementSettingsNode node = ((ArrangementTreeNode)value).getBackingSetting();
ArrangementMatchCondition node = ((ArrangementTreeNode)value).getBackingSetting();
if (node == null) {
return EMPTY_RENDERER;
}
@@ -532,7 +567,7 @@ public class ArrangementRuleTree {
}
}
private class MyModelNodesRefresher implements TObjectProcedure<ArrangementRuleEditingModelImpl> {
private static class MyModelNodesRefresher implements TObjectProcedure<ArrangementRuleEditingModelImpl> {
@Override
public boolean execute(ArrangementRuleEditingModelImpl model) {
model.refreshTreeNodes();
@@ -15,7 +15,7 @@
*/
package com.intellij.application.options.codeStyle.arrangement;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementSettingsNode;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -31,31 +31,31 @@ public class ArrangementTreeNode extends DefaultMutableTreeNode {
private static final int NO_ROW = -1;
@Nullable private ArrangementSettingsNode mySettings;
private int myRow;
@Nullable private ArrangementMatchCondition mySettings;
private int myRow;
public ArrangementTreeNode(@Nullable ArrangementSettingsNode settings) {
public ArrangementTreeNode(@Nullable ArrangementMatchCondition settings) {
this(settings, NO_ROW);
}
public ArrangementTreeNode(@Nullable ArrangementSettingsNode settings, int row) {
public ArrangementTreeNode(@Nullable ArrangementMatchCondition settings, int row) {
mySettings = settings;
myRow = row;
}
@Nullable
public ArrangementSettingsNode getBackingSetting() {
public ArrangementMatchCondition getBackingSetting() {
return mySettings;
}
public void setSettings(@Nullable ArrangementSettingsNode settings) {
public void setSettings(@Nullable ArrangementMatchCondition settings) {
mySettings = settings;
}
public boolean isRowSet() {
return myRow >= 0;
}
public int getRow() {
return myRow;
}
@@ -179,6 +179,7 @@ public class HighlightUsagesHandler extends HighlightHandlerBase {
}
final EditorSearchComponent header = new EditorSearchComponent(editor, project);
header.setRegexp(false);
editor.setHeaderComponent(header);
}
@@ -74,4 +74,6 @@ public interface ModuleSettings extends ComponentManagerSettings {
boolean hasModuleLibrary(String libraryName);
List<Element> getOrderEntries();
void addFacetElement(@NotNull String facetTypeId, @NotNull String facetName, Element configuration);
}
@@ -32,6 +32,7 @@ import com.intellij.util.containers.ContainerUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.serialization.JDomSerializationUtil;
import org.jetbrains.jps.model.serialization.facet.JpsFacetSerializer;
import java.io.File;
@@ -83,6 +84,17 @@ public class ModuleSettingsImpl extends ComponentManagerSettingsImpl implements
return ContainerUtil.getFirstItem(getFacetElements(facetTypeId), null);
}
@Override
public void addFacetElement(@NotNull String facetTypeId, @NotNull String facetName, Element configuration) {
Element componentElement = JDomSerializationUtil.findOrCreateComponentElement(getRootElement(), FacetManagerImpl.COMPONENT_NAME);
Element facetElement = new Element(JpsFacetSerializer.FACET_TAG);
facetElement.setAttribute(JpsFacetSerializer.TYPE_ATTRIBUTE, facetTypeId);
facetElement.setAttribute(JpsFacetSerializer.NAME_ATTRIBUTE, facetName);
configuration.setName(JpsFacetSerializer.CONFIGURATION_TAG);
facetElement.addContent(configuration);
componentElement.addContent(facetElement);
}
public void setModuleType(@NotNull String moduleType) {
getRootElement().setAttribute(ModuleImpl.ELEMENT_TYPE, moduleType);
}
@@ -404,7 +404,7 @@ public abstract class LogConsoleBase extends AdditionalTabComponent implements L
LOG.assertTrue(editor != null);
final Document document = editor.getDocument();
final int caretOffset = editor.getCaretModel().getOffset();
if (caretOffset > -1) {
if (caretOffset > -1 && caretOffset < document.getTextLength()) {
int line;
try {
line = document.getLineNumber(caretOffset);
@@ -128,6 +128,7 @@ public class ExecutionTargetManagerImpl extends ExecutionTargetManager implement
private void updateActiveTarget(@Nullable RunnerAndConfigurationSettings settings, @Nullable ExecutionTarget toSelect) {
List<ExecutionTarget> suitable = settings == null ? Collections.singletonList(DefaultExecutionTarget.INSTANCE)
: getTargetsFor(settings);
ExecutionTarget toNotify = null;
synchronized (myActiveTargetLock) {
if (toSelect == null) toSelect = myActiveTarget;
@@ -143,18 +144,25 @@ public class ExecutionTargetManagerImpl extends ExecutionTargetManager implement
}
}
}
doSetActiveTarget(index >= 0 ? suitable.get(index) : ContainerUtil.getFirstItem(suitable, DefaultExecutionTarget.INSTANCE));
toNotify =
doSetActiveTarget(index >= 0 ? suitable.get(index) : ContainerUtil.getFirstItem(suitable, DefaultExecutionTarget.INSTANCE));
}
if (toNotify != null) {
myProject.getMessageBus().syncPublisher(TOPIC).activeTargetChanged(toNotify);
}
}
private void doSetActiveTarget(@NotNull ExecutionTarget newTarget) {
@Nullable
private ExecutionTarget doSetActiveTarget(@NotNull ExecutionTarget newTarget) {
mySavedActiveTargetId = null;
ExecutionTarget prev = myActiveTarget;
myActiveTarget = newTarget;
if (prev != null && !prev.equals(myActiveTarget)) {
myProject.getMessageBus().syncPublisher(TOPIC).activeTargetChanged(myActiveTarget);
return myActiveTarget;
}
return null;
}
@NotNull
@@ -20,6 +20,7 @@ import com.intellij.CommonBundle;
import com.intellij.ui.components.JBList;
import com.intellij.util.ui.ComponentWithEmptyText;
import com.intellij.util.ui.StatusText;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -82,6 +83,7 @@ public abstract class AddDeleteListPanel<T> extends PanelWithButtons implements
protected void customizeDecorator(ToolbarDecorator decorator) {
}
@NotNull
@Override
public StatusText getEmptyText() {
return myList.getEmptyText();
@@ -19,6 +19,7 @@ import com.intellij.ui.table.JBTable;
import com.intellij.util.ui.ComponentWithEmptyText;
import com.intellij.util.ui.StatusText;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -102,6 +103,7 @@ public abstract class AddEditRemovePanel<T> extends PanelWithButtons implements
return myLabel;
}
@NotNull
@Override
public StatusText getEmptyText() {
return myTable.getEmptyText();
@@ -20,4 +20,6 @@ import org.jetbrains.annotations.NotNull;
public interface ComponentWithExpandableItems<T> {
@NotNull
ExpandableItemsHandler<T> getExpandableItemsHandler();
void setExpandableItemsEnabled(boolean enabled);
}
@@ -0,0 +1,43 @@
/*
* Copyright 2000-2012 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.ui;
import com.intellij.util.ui.AbstractLayoutManager;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
public class ExpandedItemRendererComponentWrapper extends JComponent {
public ExpandedItemRendererComponentWrapper(@NotNull final Component rendererComponent) {
add(rendererComponent);
setOpaque(false);
setLayout(new AbstractLayoutManager() {
@Override
public Dimension preferredLayoutSize(Container parent) {
return rendererComponent.getPreferredSize();
}
@Override
public void layoutContainer(Container parent) {
Dimension size = parent.getSize();
Insets i = parent.getInsets();
Dimension pref = rendererComponent.getPreferredSize();
rendererComponent.setBounds(i.left, i.top, Math.max(pref.width, size.width - i.left - i.right), size.height - i.top - i.bottom);
}
});
}
}
@@ -43,6 +43,7 @@ public abstract class OptionalChooserComponent<T> implements CheckBoxListListene
reset();
}
@NotNull
@Override
public StatusText getEmptyText() {
return myList.getEmptyText();
@@ -97,6 +97,7 @@ public class PathsChooserComponent implements ComponentWithEmptyText {
reset();
}
@NotNull
@Override
public StatusText getEmptyText() {
return myList.getEmptyText();
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.ComponentWithExpandableItems;
import com.intellij.ui.ExpandableItemsHandler;
import com.intellij.ui.ExpandableItemsHandlerFactory;
import com.intellij.ui.ExpandedItemRendererComponentWrapper;
import com.intellij.util.ArrayUtil;
import com.intellij.util.NotNullFunction;
import com.intellij.util.ui.AsyncProcessIcon;
@@ -40,8 +41,8 @@ import java.util.Collection;
* @author Konstantin Bulenkov
*/
public class JBList extends JList implements ComponentWithEmptyText, ComponentWithExpandableItems<Integer>{
private StatusText myEmptyText;
private ExpandableItemsHandler<Integer> myExpandableItemsHandler;
@NotNull private StatusText myEmptyText;
@NotNull private ExpandableItemsHandler<Integer> myExpandableItemsHandler;
@Nullable private AsyncProcessIcon myBusyIcon;
private boolean myBusy;
@@ -172,15 +173,10 @@ public class JBList extends JList implements ComponentWithEmptyText, ComponentWi
}
};
if (shouldInstallItemTooltipExpander()) myExpandableItemsHandler = ExpandableItemsHandlerFactory.install(this);
myExpandableItemsHandler = ExpandableItemsHandlerFactory.install(this);
setCellRenderer(new DefaultListCellRenderer());
}
protected boolean shouldInstallItemTooltipExpander() {
return true;
}
public boolean isEmpty() {
return getItemsCount() == 0;
}
@@ -190,6 +186,7 @@ public class JBList extends JList implements ComponentWithEmptyText, ComponentWi
return model == null ? 0 : model.getSize();
}
@NotNull
@Override
public StatusText getEmptyText() {
return myEmptyText;
@@ -201,6 +198,25 @@ public class JBList extends JList implements ComponentWithEmptyText, ComponentWi
return myExpandableItemsHandler;
}
@Override
public void setExpandableItemsEnabled(boolean enabled) {
myExpandableItemsHandler.setEnabled(enabled);
}
@Override
public void setCellRenderer(final ListCellRenderer cellRenderer) {
super.setCellRenderer(new ListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Component result = cellRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (myExpandableItemsHandler != null && myExpandableItemsHandler.getExpandedItems().contains(index)) {
result = new ExpandedItemRendererComponentWrapper(result);
}
return result;
}
});
}
public <T> void installCellRenderer(@NotNull final NotNullFunction<T, JComponent> fun) {
setCellRenderer(new DefaultListCellRenderer() {
@NotNull
@@ -17,6 +17,7 @@ package com.intellij.ui.components;
import com.intellij.util.ui.ComponentWithEmptyText;
import com.intellij.util.ui.StatusText;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -59,6 +60,7 @@ public class JBTextField extends JTextField implements ComponentWithEmptyText {
myEmptyText.clear();
}
@NotNull
@Override
public StatusText getEmptyText() {
return myEmptyText;
@@ -18,10 +18,7 @@ package com.intellij.ui.table;
import com.intellij.Patches;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.ComponentWithExpandableItems;
import com.intellij.ui.ExpandableItemsHandler;
import com.intellij.ui.ExpandableItemsHandlerFactory;
import com.intellij.ui.TableCell;
import com.intellij.ui.*;
import com.intellij.ui.components.JBViewport;
import com.intellij.ui.speedSearch.SpeedSearchSupply;
import com.intellij.util.ui.*;
@@ -300,6 +297,7 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component
}
}
@NotNull
@Override
public StatusText getEmptyText() {
return myEmptyText;
@@ -311,6 +309,11 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component
return myExpandableItemsHandler;
}
@Override
public void setExpandableItemsEnabled(boolean enabled) {
myExpandableItemsHandler.setEnabled(enabled);
}
public void removeNotify() {
final KeyboardFocusManager keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
//noinspection HardCodedStringLiteral
@@ -460,12 +463,12 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component
private static boolean isTableDecorationSupported() {
return UIUtil.isUnderAlloyLookAndFeel()
|| UIUtil.isUnderNativeMacLookAndFeel()
|| UIUtil.isUnderDarcula()
|| UIUtil.isUnderQuaquaLookAndFeel()
|| UIUtil.isUnderMetalLookAndFeel()
|| UIUtil.isUnderNimbusLookAndFeel()
|| UIUtil.isUnderWindowsLookAndFeel();
|| UIUtil.isUnderNativeMacLookAndFeel()
|| UIUtil.isUnderDarcula()
|| UIUtil.isUnderQuaquaLookAndFeel()
|| UIUtil.isUnderMetalLookAndFeel()
|| UIUtil.isUnderNimbusLookAndFeel()
|| UIUtil.isUnderWindowsLookAndFeel();
}
public void disableTypeAheadInCellEditors() {
@@ -474,8 +477,7 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component
@Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
final Component result = super.prepareRenderer(renderer, row, column);
final boolean selected = myExpandableItemsHandler.getExpandedItems().contains(new TableCell(row, column));
Component result = super.prepareRenderer(renderer, row, column);
// Fix GTK background
if (UIUtil.isUnderGTKLookAndFeel()) {
@@ -483,7 +485,7 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component
}
if (isTableDecorationSupported() && isStriped() && result instanceof JComponent) {
final Color bg = row % 2 == 1 ? getBackground() : UIUtil.getDecoratedRowColor();
final Color bg = row % 2 == 1 ? getBackground() : UIUtil.getDecoratedRowColor();
final JComponent c = (JComponent)result;
final boolean cellSelected = isCellSelected(row, column);
if (!cellSelected) {
@@ -492,31 +494,13 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component
for (Component child : c.getComponents()) {
child.setBackground(bg);
}
}
}
}
if (!selected) return result;
return new JComponent() {
{
add(result);
setOpaque(false);
setLayout(new AbstractLayoutManager() {
@Override
public Dimension preferredLayoutSize(Container parent) {
return result.getPreferredSize();
}
@Override
public void layoutContainer(Container parent) {
Dimension size = parent.getSize();
Insets i = parent.getInsets();
Dimension pref = result.getPreferredSize();
result.setBounds(i.left, i.top, Math.max(pref.width, size.width - i.left - i.right), size.height - i.top - i.bottom);
}
});
}
};
if (myExpandableItemsHandler.getExpandedItems().contains(new TableCell(row, column))) {
result = new ExpandedItemRendererComponentWrapper(result);
}
return result;
}
private final class MyCellEditorRemover implements PropertyChangeListener {
@@ -148,6 +148,7 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith
return false;
}
@NotNull
@Override
public StatusText getEmptyText() {
return myEmptyText;
@@ -159,6 +160,11 @@ public class Tree extends JTree implements ComponentWithEmptyText, ComponentWith
return myExpandableItemsHandler;
}
@Override
public void setExpandableItemsEnabled(boolean enabled) {
myExpandableItemsHandler.setEnabled(enabled);
}
@Override
public Color getBackground() {
return isBackgroundSet() ? super.getBackground() : UIUtil.getTreeTextBackground();
@@ -209,8 +209,8 @@ public class QueueProcessor<T> {
try {
LOG.error(t);
}
catch (Exception ignore) {
// should survive assertions
catch (Throwable e2) {
e2.printStackTrace();
}
}
}
@@ -15,6 +15,8 @@
*/
package com.intellij.util.ui;
import org.jetbrains.annotations.NotNull;
public interface ComponentWithEmptyText {
StatusText getEmptyText();
@NotNull StatusText getEmptyText();
}
@@ -442,7 +442,8 @@ public class Switcher extends AnAction implements DumbAware {
new NameFilteringListModel<FileInfo>(files, new Function<FileInfo, String>() {
@Override
public String fun(FileInfo info) {
return info.getFirst().getName();
final VirtualFile file = info.getFirst();
return file instanceof VirtualFilePathWrapper ? ((VirtualFilePathWrapper)file).getPresentablePath() : file.getName();
}
}, new Condition<String>() {
@Override
@@ -513,6 +514,13 @@ public class Switcher extends AnAction implements DumbAware {
}).createPopup();
if (isPinnedMode()) {
new AnAction(null ,null ,null) {
@Override
public void actionPerformed(AnActionEvent e) {
changeSelection();
}
}.registerCustomShortcutSet(CustomShortcutSet.fromString("TAB"), this, myPopup);
new AnAction(null, null, null) {
@Override
public void actionPerformed(AnActionEvent e) {
@@ -625,11 +633,15 @@ public class Switcher extends AnAction implements DumbAware {
break;
}
if (e.getKeyCode() == ALT_KEY) {
if (isFilesSelected()) {
goLeft();
} else {
goRight();
}
changeSelection();
}
}
private void changeSelection() {
if (isFilesSelected()) {
goLeft();
} else {
goRight();
}
}
@@ -871,6 +883,15 @@ public class Switcher extends AnAction implements DumbAware {
setComparator(new SpeedSearchComparator(false, true));
}
@Override
protected void processKeyEvent(KeyEvent e) {
final int keyCode = e.getKeyCode();
if (keyCode == VK_LEFT || keyCode == VK_RIGHT) {
return;
}
super.processKeyEvent(e);
}
@Override
protected int getSelectedIndex() {
return isFilesSelected()
@@ -905,10 +926,13 @@ public class Switcher extends AnAction implements DumbAware {
@Override
protected String getElementText(Object element) {
return element instanceof ToolWindow
? ids.get(element)
: element instanceof FileInfo
? ((FileInfo)element).getFirst().getName() : "";
if (element instanceof ToolWindow) {
return ids.get(element);
} else if (element instanceof FileInfo) {
final VirtualFile file = ((FileInfo)element).getFirst();
return file instanceof VirtualFilePathWrapper ? ((VirtualFilePathWrapper)file).getPresentablePath() : file.getName();
}
return "";
}
@Override
@@ -147,6 +147,7 @@ public class ElementsChooser<T> extends JPanel implements ComponentWithEmptyText
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, KeyEvent.SHIFT_DOWN_MASK), "selectLastRowExtendSelection");
}
@NotNull
@Override
public StatusText getEmptyText() {
return myTable.getEmptyText();
@@ -158,6 +159,11 @@ public class ElementsChooser<T> extends JPanel implements ComponentWithEmptyText
return myTable.getExpandableItemsHandler();
}
@Override
public void setExpandableItemsEnabled(boolean enabled) {
myTable.setExpandableItemsEnabled(enabled);
}
public void setSingleSelectionMode() {
myTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
}
@@ -185,11 +185,12 @@ public class CommandMerger {
}
private boolean affectsMultiplePhysicalDocs() {
int count = 0;
Set<VirtualFile> affectedFiles = new HashSet<VirtualFile>();
for (DocumentReference each : myAllAffectedDocuments) {
VirtualFile file = each.getFile();
if (file instanceof LightVirtualFile) continue;
if (++count > 1) return true;
if (file == null || file instanceof LightVirtualFile) continue;
affectedFiles.add(file);
if (affectedFiles.size() > 1) return true;
}
return false;
}
@@ -150,7 +150,8 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen
private JTextField createColorField(boolean hex) {
final NumberDocument doc = new NumberDocument(hex);
final JTextField field = new JTextField(doc, "", hex ? 5:2);
final int lafFix = UIUtil.isUnderWindowsClassicLookAndFeel() || UIUtil.isUnderWindowsLookAndFeel() ? 1 : 0;
final JTextField field = new JTextField(doc, "", (hex ? 5:2) + lafFix);
field.setSize(50, -1);
doc.setSource(field);
field.getDocument().addDocumentListener(this);
@@ -289,7 +289,7 @@ public abstract class SpeedSearchBase<Comp extends JComponent> extends SpeedSear
manageSearchPopup(null);
}
private void processKeyEvent(KeyEvent e) {
protected void processKeyEvent(KeyEvent e) {
if (e.isAltDown()) return;
if (mySearchPopup != null) {
mySearchPopup.processKeyEvent(e);
@@ -28,6 +28,7 @@ import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.table.TableView;
import com.intellij.util.IconUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -166,6 +167,7 @@ public abstract class ValidatingTableEditor<Item> implements ComponentWithEmptyT
}
}
@NotNull
@Override
public StatusText getEmptyText() {
return myTable.getEmptyText();
@@ -24,6 +24,7 @@ import com.intellij.psi.codeStyle.MinusculeMatcher;
import com.intellij.psi.codeStyle.NameUtil;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.ui.SpeedSearchComparator;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.containers.CollectionFactory;
import com.intellij.util.text.Matcher;
@@ -519,4 +520,12 @@ public class NameUtilTest extends UsefulTestCase {
}
}).cpuBound().attempts(20).assertTiming();
}
public void testSpeedSearchComparator() {
final SpeedSearchComparator c = new SpeedSearchComparator(false, true);
assertTrue(c.matchingFragments("a", "Ant") != null);
assertTrue(c.matchingFragments("an", "Changes") != null);
assertTrue(c.matchingFragments("a", "Changes") != null);
}
}
@@ -56,7 +56,8 @@ create.global.library=Create Glob&al library ''{0}''
create.library.dialog.title=Create Android library
select.target.dialog.text=Please select Android Target
default.activity.not.found.error=Default Activity not found
activity.not.launchable.error=The Intent Filter of the Activity must contain {0} action
activity.not.launchable.error=The intent-filter of the activity must contain {0} action
activity.not.declared.in.manifest=The activity ''{0}'' is not declared in AndroidManifest.xml
new.typed.resource.command.name=New {0} resource file
new.typed.resource.dialog.title=New {0} Resource File
new.file.dialog.text=Enter a new file name
@@ -50,7 +50,7 @@ public class AndroidDependencyProcessor implements DependencyProcessor {
@Override
public void run() {
final PsiClass[] classes =
JavaPsiFacade.getInstance(project).findClasses(topLevelClassName, GlobalSearchScope.allScope(project));
JavaPsiFacade.getInstance(project).findClasses(topLevelClassName, GlobalSearchScope.projectScope(project));
for (PsiClass aClass : classes) {
final Collection<PsiReference> references = searcher.findReferences(aClass, true);
@@ -116,7 +116,8 @@ public class AndroidResourceReferenceBase extends PsiReferenceBase.Poly<XmlEleme
if (manager != null) {
String resName = resValue.getResourceName();
if (resName != null) {
List<ValueResourceInfoImpl> valueResources = manager.findValueResourceInfos(resType, resName, false);
final boolean attrReference = resValue.getPrefix() == '?';
List<ValueResourceInfoImpl> valueResources = manager.findValueResourceInfos(resType, resName, false, attrReference);
for (final ValueResourceInfo resource : valueResources) {
elements.add(new LazyValueResourceElementWrapper(resource, myElement));
@@ -23,5 +23,6 @@ import com.android.resources.ResourceType;
public class ParentStyleConverter extends ResourceReferenceConverter {
public ParentStyleConverter() {
super(ResourceType.STYLE.getName(), false, false);
setAllowAttributeReferences(false);
}
}
@@ -55,6 +55,7 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
private boolean myWithPrefix = true;
private boolean myWithExplicitResourceType = true;
private boolean myQuiet = false;
private boolean myAllowAttributeReferences = true;
public ResourceReferenceConverter() {
this(new ArrayList<String>());
@@ -79,6 +80,10 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
myQuiet = quiet;
}
public void setAllowAttributeReferences(boolean allowAttributeReferences) {
myAllowAttributeReferences = allowAttributeReferences;
}
@NotNull
private String getPackagePrefix(@Nullable String resourcePackage) {
String prefix = myWithPrefix ? "@" : "";
@@ -126,10 +131,12 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
else {
result.add(ResourceValue.literal(systemPrefix));
}
final char prefix = myWithPrefix ? '@' : 0;
if (recommendedTypes.size() == 1) {
String type = recommendedTypes.iterator().next();
boolean explicitResourceType = value.startsWith(getTypePrefix(resourcePackage, type)) || myWithExplicitResourceType;
addResourceReferenceValues(facet, type, resourcePackage, result, explicitResourceType);
addResourceReferenceValues(facet, prefix, type, resourcePackage, result, explicitResourceType);
}
else {
final Set<String> filteringSet = SYSTEM_RESOURCE_PACKAGE.equals(resourcePackage)
@@ -140,7 +147,7 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
final String type = resourceType.getName();
String typePrefix = getTypePrefix(resourcePackage, type);
if (value.startsWith(typePrefix)) {
addResourceReferenceValues(facet, type, resourcePackage, result, true);
addResourceReferenceValues(facet, prefix, type, resourcePackage, result, true);
}
else if (recommendedTypes.contains(type) &&
(filteringSet == null || filteringSet.contains(type))) {
@@ -149,6 +156,9 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
}
}
}
if (myAllowAttributeReferences) {
completeAttributeReferences(value, facet, result);
}
final ResolvingConverter<String> additionalConverter = getAdditionalConverter(context);
if (additionalConverter != null) {
@@ -159,6 +169,19 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
return result;
}
private static void completeAttributeReferences(String value, AndroidFacet facet, Set<ResourceValue> result) {
if (StringUtil.startsWith(value, "?attr/")) {
addResourceReferenceValues(facet, '?', ResourceType.ATTR.getName(), null, result, true);
}
else if (StringUtil.startsWith(value, "?android:attr/")) {
addResourceReferenceValues(facet, '?', ResourceType.ATTR.getName(), SYSTEM_RESOURCE_PACKAGE, result, true);
}
else if (StringUtil.startsWithChar(value, '?')) {
addResourceReferenceValues(facet, '?', ResourceType.ATTR.getName(), null, result, false);
addResourceReferenceValues(facet, '?', ResourceType.ATTR.getName(), SYSTEM_RESOURCE_PACKAGE, result, false);
}
}
@NotNull
public static Set<String> getResourceTypesInCurrentModule(@NotNull AndroidFacet facet) {
final Set<String> result = new HashSet<String>();
@@ -205,21 +228,22 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
return types;
}
private void addResourceReferenceValues(AndroidFacet facet,
String type,
String resPackage,
Collection<ResourceValue> result,
boolean explicitResourceType) {
private static void addResourceReferenceValues(AndroidFacet facet,
char prefix,
String type,
@Nullable String resPackage,
Collection<ResourceValue> result,
boolean explicitResourceType) {
final ResourceManager manager = facet.getResourceManager(resPackage);
if (manager != null) {
for (String name : manager.getResourceNames(type)) {
result.add(referenceTo(type, resPackage, name, explicitResourceType));
result.add(referenceTo(prefix, type, resPackage, name, explicitResourceType));
}
}
}
private ResourceValue referenceTo(String type, String resPackage, String name, boolean explicitResourceType) {
return ResourceValue.referenceTo(myWithPrefix ? '@' : 0, resPackage, explicitResourceType ? type : null, name);
private static ResourceValue referenceTo(char prefix, String type, String resPackage, String name, boolean explicitResourceType) {
return ResourceValue.referenceTo(prefix, resPackage, explicitResourceType ? type : null, name);
}
public ResourceValue fromString(@Nullable @NonNls String s, ConvertContext context) {
@@ -236,8 +260,28 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
return null;
}
}
if (parsed != null && parsed.getResourceType() == null && myResourceTypes.size() == 1) {
parsed.setResourceType(myResourceTypes.get(0));
if (parsed != null) {
final String resType = parsed.getResourceType();
if (parsed.getPrefix() == '?') {
if (!myAllowAttributeReferences) {
return null;
}
if (resType == null) {
parsed.setResourceType(ResourceType.ATTR.getName());
}
else if (!ResourceType.ATTR.getName().equals(resType)) {
return null;
}
}
else if (resType == null && parsed.isReference()) {
if (myWithExplicitResourceType && !"@null".equals(s)) {
return null;
}
if (myResourceTypes.size() == 1) {
parsed.setResourceType(myResourceTypes.get(0));
}
}
}
return parsed;
}
@@ -66,7 +66,7 @@ public class ResourceValue {
if (s == null) {
return null;
}
if (s.startsWith("@")) {
if (s.startsWith("@") || s.startsWith("?")) {
return reference(s, true);
}
else if (!withPrefix) {
@@ -92,9 +92,11 @@ public class ResourceValue {
assert value.length() > 0;
result.myPrefix = value.charAt(0);
}
final int startIndex = withPrefix ? 1 : 0;
int pos = value.indexOf('/');
if (pos > 0) {
String resType = value.substring(withPrefix ? 1 : 0, pos);
String resType = value.substring(startIndex, pos);
int colonIndex = resType.indexOf(':');
if (colonIndex > 0) {
result.myPackage = resType.substring(0, colonIndex);
@@ -117,10 +119,13 @@ public class ResourceValue {
}
else {
int colonIndex = value.indexOf(':');
if (colonIndex > 0) {
result.myPackage = value.substring(0, colonIndex);
if (colonIndex > startIndex) {
result.myPackage = value.substring(startIndex, colonIndex);
result.myResourceName = value.substring(colonIndex + 1);
}
else {
result.myResourceName = value.substring(startIndex);
}
result.myResourceName = value.substring(colonIndex + 1);
}
return result;
}
@@ -433,7 +433,7 @@ public abstract class ResourceManager {
public List<ResourceElement> findValueResources(@NotNull String resourceType,
@NotNull String resourceName,
boolean distinguishDelimitersInName) {
final List<ValueResourceInfoImpl> resources = findValueResourceInfos(resourceType, resourceName, distinguishDelimitersInName);
final List<ValueResourceInfoImpl> resources = findValueResourceInfos(resourceType, resourceName, distinguishDelimitersInName, false);
final List<ResourceElement> result = new ArrayList<ResourceElement>();
for (ValueResourceInfoImpl resource : resources) {
@@ -449,14 +449,14 @@ public abstract class ResourceManager {
@NotNull
public List<ValueResourceInfoImpl> findValueResourceInfos(@NotNull String resourceType,
@NotNull final String resourceName,
final boolean distinguishDelimetersInName) {
final boolean distinguishDelimetersInName,
boolean searchAttrs) {
final ResourceType type = ResourceType.getEnum(resourceType);
if (type == null || !AndroidResourceUtil.VALUE_RESOURCE_TYPES.contains(type)) {
// do not search for styleables and atts here because we don't want to resolve references to it
if (type == null ||
!AndroidResourceUtil.VALUE_RESOURCE_TYPES.contains(type) &&
(type != ResourceType.ATTR || !searchAttrs)) {
return Collections.emptyList();
}
new HashMap<VirtualFile, Set<AndroidValueResourcesIndex.MyResourceInfo>>();
final GlobalSearchScope scope = GlobalSearchScope.allScope(myModule.getProject());
final List<ValueResourceInfoImpl> result = new ArrayList<ValueResourceInfoImpl>();
final Set<VirtualFile> valueResourceFiles = getAllValueResourceFiles();
@@ -26,7 +26,6 @@ import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
@@ -82,7 +81,12 @@ public class AndroidRunConfiguration extends AndroidRunConfigurationBase impleme
if (!c.isInheritor(activityClass, true)) {
throw new RuntimeConfigurationError(AndroidBundle.message("not.activity.subclass.error", ACTIVITY_CLASS));
}
if (!isActivityLaunchable(facet.getModule(), c)) {
final Activity activity = AndroidDomUtil.getActivityDomElementByClass(facet.getModule(), c);
if (activity == null) {
throw new RuntimeConfigurationError(AndroidBundle.message("activity.not.declared.in.manifest", c.getName()));
}
if (!isActivityLaunchable(activity)) {
throw new RuntimeConfigurationError(AndroidBundle.message("activity.not.launchable.error", AndroidUtils.LAUNCH_ACTION_NAME));
}
}
@@ -170,13 +174,10 @@ public class AndroidRunConfiguration extends AndroidRunConfigurationBase impleme
return new MyApplicationLauncher(activityToLaunch);
}
private static boolean isActivityLaunchable(@NotNull Module module, PsiClass c) {
Activity activity = AndroidDomUtil.getActivityDomElementByClass(module, c);
if (activity != null) {
for (IntentFilter filter : activity.getIntentFilters()) {
if (AndroidDomUtil.containsAction(filter, AndroidUtils.LAUNCH_ACTION_NAME)) {
return true;
}
private static boolean isActivityLaunchable(Activity activity) {
for (IntentFilter filter : activity.getIntentFilters()) {
if (AndroidDomUtil.containsAction(filter, AndroidUtils.LAUNCH_ACTION_NAME)) {
return true;
}
}
return false;
@@ -0,0 +1,43 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?myAttr"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?otherAttr"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="<error>?unknown</error>"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/myAttr"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="<error>?attr/unknown</error>"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="<error>@attr/myAttr</error>"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="<error>@myAttr</error>"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/myDrawable"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="<error>?drawable/myDrawable</error>"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?android:text"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="<error>?android:unknown</error>"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?android:attr/text"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="</error>?android:attr/unknown</error>"/>
</LinearLayout>
@@ -0,0 +1,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="<caret>"/>
</LinearLayout>
@@ -0,0 +1,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?<caret>"/>
</LinearLayout>
@@ -0,0 +1,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/<caret>"/>
</LinearLayout>
@@ -0,0 +1,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?attr/myAttr"/>
</LinearLayout>
@@ -0,0 +1,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?android:attr/<caret>"/>
</LinearLayout>
@@ -0,0 +1,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?android:attr/textAppearance"/>
</LinearLayout>
@@ -0,0 +1,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?<caret>"/>
</LinearLayout>
@@ -0,0 +1,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?myAttr"/>
</LinearLayout>
@@ -0,0 +1,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?<caret>"/>
</LinearLayout>
@@ -0,0 +1,7 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?android:textAppearance"/>
</LinearLayout>
@@ -0,0 +1,9 @@
<resources>
<attr name="myAttr" format="integer"/>
<declare-styleable name="MyCustomView">
<attr name="otherAttr" format="integer"/>
</declare-styleable>
<drawable name="myDrawable"/>
</resources>
@@ -0,0 +1,6 @@
<resources>
<attr name="myAttr" format="integer"/>
<style name="myStyle" parent="?<caret>">
</style>
</resources>
@@ -0,0 +1,6 @@
<resources>
<attr name="myAttr" format="integer"/>
<style name="myStyle" parent="?">
</style>
</resources>
@@ -0,0 +1,20 @@
<resources>
<attr name="myAttr" format="integer"/>
<style name="myStyle1" parent="<error>?myAttr</error>">
</style>
<style name="myStyle2" parent="<error>?attr/myAttr</error>">
</style>
<style name="myStyle3" parent="<error>attr/myAttr</error>">
</style>
<style name="myStyle4" parent="<error>myAttr</error>">
</style>
<style name="myStyle5" parent="<error>android:textAppearance</error>">
</style>
<style name="myStyle6" parent="<error>android:attr/textAppearance</error>">
</style>
<style name="myStyle7" parent="<error>?android:attr/textAppearance</error>">
</style>
<style name="myStyle8" parent="<error>?android:textAppearance</error>">
</style>
</resources>
@@ -667,6 +667,64 @@ public class AndroidLayoutDomTest extends AndroidDomTest {
doTestHighlighting();
}
public void testAttrReferences1() throws Throwable {
copyFileToProject("attrReferences_attrs.xml", "res/values/attrReferences_attrs.xml");
doTestHighlighting();
}
public void testAttrReferences2() throws Throwable {
doTestAttrReferenceCompletionVariants("?");
}
public void testAttrReferences3() throws Throwable {
doTestAttrReferenceCompletionVariants("attr");
}
private void doTestAttrReferenceCompletionVariants(String prefix) throws IOException {
copyFileToProject("attrReferences_attrs.xml", "res/values/attrReferences_attrs.xml");
VirtualFile file = copyFileToProject(getTestName(true) + ".xml");
myFixture.configureFromExistingVirtualFile(file);
myFixture.complete(CompletionType.BASIC);
final List<String> variants = myFixture.getLookupElementStrings();
assertNotNull(variants);
assertTrue(variants.size() > 0);
assertFalse(containElementStartingWith(variants, prefix));
}
public void testAttrReferences4() throws Throwable {
doTestAttrReferenceCompletion("myA\n");
}
public void testAttrReferences5() throws Throwable {
doTestAttrReferenceCompletion("textAppear\n");
}
public void testAttrReferences6() throws Throwable {
doTestAttrReferenceCompletion("myA\n");
}
public void testAttrReferences7() throws Throwable {
doTestAttrReferenceCompletion("android:textAppear\n");
}
private void doTestAttrReferenceCompletion(String textToType) throws IOException {
copyFileToProject("attrReferences_attrs.xml", "res/values/attrReferences_attrs.xml");
VirtualFile file = copyFileToProject(getTestName(true) + ".xml");
myFixture.configureFromExistingVirtualFile(file);
myFixture.complete(CompletionType.BASIC);
myFixture.type(textToType);
myFixture.checkResultByFile(testFolder + '/' + getTestName(true) + "_after.xml");
}
private static boolean containElementStartingWith(List<String> elements, String prefix) {
for (String element : elements) {
if (element.startsWith(prefix)) {
return true;
}
}
return false;
}
private void doCreateFileResourceFromUsage(VirtualFile virtualFile) {
myFixture.configureFromExistingVirtualFile(virtualFile);
final List<HighlightInfo> infos = myFixture.doHighlighting();
@@ -317,6 +317,14 @@ public class AndroidValueResourcesTest extends AndroidDomTest {
myFixture.checkResultByFile("res/values/bools.xml", testFolder + '/' + getTestName(true) + "_bools_after.xml", true);
}
public void testAttrReferenceCompletion() throws Throwable {
doTestCompletion();
}
public void testAttrReferenceHighlighting() throws Throwable {
doTestHighlighting();
}
private void doCreateValueResourceFromUsage(VirtualFile virtualFile) {
myFixture.configureFromExistingVirtualFile(virtualFile);
final List<HighlightInfo> infos = myFixture.doHighlighting();
@@ -20,14 +20,19 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.components.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.FileEditorManagerAdapter;
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.DocumentListener;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.FileStatus;
import com.intellij.openapi.vcs.FileStatusManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packageDependencies.DependencyValidationManager;
import com.intellij.psi.PsiFile;
@@ -87,9 +92,13 @@ public class CopyrightManager extends AbstractProjectComponent implements JDOMEx
public void projectOpened() {
if (myProject != null) {
FileEditorManagerListener listener = new FileEditorManagerAdapter() {
public void fileOpened(FileEditorManager fileEditorManager, VirtualFile virtualFile) {
if (virtualFile.isWritable() && NewFileTracker.getInstance().contains(virtualFile)) {
final FileDocumentManager fileDocumentManager = FileDocumentManager.getInstance();
DocumentListener listener = new DocumentAdapter() {
@Override
public void documentChanged(DocumentEvent e) {
final Document document = e.getDocument();
final VirtualFile virtualFile = fileDocumentManager.getFile(document);
if (virtualFile != null && NewFileTracker.getInstance().contains(virtualFile)) {
NewFileTracker.getInstance().remove(virtualFile);
if (FileTypeUtil.getInstance().isSupportedFile(virtualFile)) {
final Module module = ProjectRootManager.getInstance(myProject).getFileIndex().getModuleForFile(virtualFile);
@@ -100,7 +109,7 @@ public class CopyrightManager extends AbstractProjectComponent implements JDOMEx
public void run() {
if (myProject.isDisposed()) return;
if (file.isValid() && file.isWritable()) {
final CopyrightProfile opts = getInstance(myProject).getCopyrightOptions(file);
final CopyrightProfile opts = getCopyrightOptions(file);
if (opts != null) {
new UpdateCopyrightProcessor(myProject, module, file).run();
}
@@ -113,8 +122,10 @@ public class CopyrightManager extends AbstractProjectComponent implements JDOMEx
}
}
};
FileEditorManager.getInstance(myProject).addFileEditorManagerListener(listener, myProject);
final EditorFactory factory = EditorFactory.getInstance();
if (factory != null) {
factory.getEventMulticaster().addDocumentListener(listener, myProject);
}
}
}
@@ -787,7 +787,7 @@ public abstract class DomInvocationHandler<T extends AbstractDomChildDescription
@Override
public DomElement fun(DomStub stub) {
if (stub instanceof ElementStub && ((ElementStub)stub).isCustom()) {
EvaluatedXmlName name = new DummyEvaluatedXmlName(stub.getName(), null);
EvaluatedXmlName name = new DummyEvaluatedXmlName(stub.getName(), "");
return new CollectionElementInvocationHandler(name, (CustomDomChildrenDescriptionImpl)description, myManager, (ElementStub)stub).getProxy();
}
return null;
@@ -27,11 +27,11 @@ public class DummyEvaluatedXmlName implements EvaluatedXmlName {
private final XmlName myXmlName;
private final String myNamespace;
public DummyEvaluatedXmlName(final String localName, final String namespace) {
public DummyEvaluatedXmlName(final String localName, @NotNull final String namespace) {
this(new XmlName(localName), namespace);
}
public DummyEvaluatedXmlName(final XmlName xmlName, final String namespace) {
public DummyEvaluatedXmlName(final XmlName xmlName, @NotNull final String namespace) {
myXmlName = xmlName;
myNamespace = namespace;
}