From 59620fbdeca44b060932d69275e8d4d6434826c9 Mon Sep 17 00:00:00 2001 From: nik Date: Wed, 27 Jul 2011 11:07:58 +0400 Subject: [PATCH] new framework detection: excludes configuration --- .../com/intellij/framework/FrameworkType.java | 13 +- .../DetectionExcludesConfiguration.java | 39 ++++ .../detection/FrameworkDetector.java | 14 +- ...acetBasedDetectedFrameworkDescription.java | 2 +- .../impl/FrameworkDetectionManager.java | 14 +- .../impl/FrameworkDetectorRegistryImpl.java | 12 +- .../DetectionExcludesConfigurationImpl.java | 167 ++++++++++++++++++ .../impl/exclude/ExcludedFileState.java | 69 ++++++++ .../exclude/ExcludesConfigurationState.java | 64 +++++++ .../impl/ui/DetectedFrameworkNode.java | 18 +- .../ui/DetectedFrameworkTreeNodeBase.java | 8 +- .../impl/ui/DetectedFrameworksTree.java | 13 ++ .../impl/ui/FrameworkDirectoryNode.java | 19 +- .../detection/impl/ui/FrameworkTypeNode.java | 13 +- .../ui/SetupDetectedFrameworksDialog.java | 21 ++- .../DetectionExcludesConfigurationTest.java | 141 +++++++++++++++ .../src/META-INF/LangExtensions.xml | 2 + .../com/intellij/openapi/util/Comparing.java | 5 + 18 files changed, 603 insertions(+), 31 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/framework/detection/DetectionExcludesConfiguration.java create mode 100644 platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurationImpl.java create mode 100644 platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/ExcludedFileState.java create mode 100644 platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/ExcludesConfigurationState.java create mode 100644 platform/lang-impl/testSrc/com/intellij/framework/detection/DetectionExcludesConfigurationTest.java diff --git a/platform/lang-impl/src/com/intellij/framework/FrameworkType.java b/platform/lang-impl/src/com/intellij/framework/FrameworkType.java index 1b75d6568f78..ae256c6ba46f 100644 --- a/platform/lang-impl/src/com/intellij/framework/FrameworkType.java +++ b/platform/lang-impl/src/com/intellij/framework/FrameworkType.java @@ -23,10 +23,12 @@ import javax.swing.*; * @author nik */ public class FrameworkType { + private final String myId; private final String myPresentableName; private final Icon myIcon; - public FrameworkType(@NotNull String presentableName, @NotNull Icon icon) { + public FrameworkType(@NotNull String id, @NotNull String presentableName, @NotNull Icon icon) { + myId = id; myPresentableName = presentableName; myIcon = icon; } @@ -36,6 +38,11 @@ public class FrameworkType { return myPresentableName; } + @NotNull + public String getId() { + return myId; + } + @NotNull public Icon getIcon() { return myIcon; @@ -46,11 +53,11 @@ public class FrameworkType { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - return myPresentableName.equals(((FrameworkType)o).myPresentableName); + return myId.equals(((FrameworkType)o).myId); } @Override public int hashCode() { - return myPresentableName.hashCode(); + return myId.hashCode(); } } diff --git a/platform/lang-impl/src/com/intellij/framework/detection/DetectionExcludesConfiguration.java b/platform/lang-impl/src/com/intellij/framework/detection/DetectionExcludesConfiguration.java new file mode 100644 index 000000000000..25171d1c7fe2 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/framework/detection/DetectionExcludesConfiguration.java @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2011 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.framework.detection; + +import com.intellij.framework.FrameworkType; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +/** + * @author nik + */ +public abstract class DetectionExcludesConfiguration { + public static DetectionExcludesConfiguration getInstance(@NotNull Project project) { + return ServiceManager.getService(project, DetectionExcludesConfiguration.class); + } + + public abstract void addExcludedFramework(@NotNull FrameworkType type); + public abstract void addExcludedFile(@NotNull VirtualFile file, @Nullable FrameworkType type); + + public abstract void removeExcluded(@NotNull Collection files, @NotNull FrameworkDetector detector); +} diff --git a/platform/lang-impl/src/com/intellij/framework/detection/FrameworkDetector.java b/platform/lang-impl/src/com/intellij/framework/detection/FrameworkDetector.java index e121debd6312..9a1bb63a1afd 100644 --- a/platform/lang-impl/src/com/intellij/framework/detection/FrameworkDetector.java +++ b/platform/lang-impl/src/com/intellij/framework/detection/FrameworkDetector.java @@ -30,15 +30,15 @@ import java.util.List; */ public abstract class FrameworkDetector { public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.framework.detector"); - private final String myDetectorId; + private final String myFrameworkTypeId; private final int myDetectorVersion; - protected FrameworkDetector(String detectorId) { - this(detectorId, 0); + protected FrameworkDetector(String frameworkTypeId) { + this(frameworkTypeId, 0); } - protected FrameworkDetector(@NotNull String detectorId, int detectorVersion) { - myDetectorId = detectorId; + protected FrameworkDetector(@NotNull String frameworkTypeId, int detectorVersion) { + myFrameworkTypeId = frameworkTypeId; myDetectorVersion = detectorVersion; } @@ -52,8 +52,8 @@ public abstract class FrameworkDetector { @NotNull FrameworkDetectionContext context); @NotNull - public final String getDetectorId() { - return myDetectorId; + public final String getFrameworkTypeId() { + return myFrameworkTypeId; } public final int getDetectorVersion() { diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/FacetBasedDetectedFrameworkDescription.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/FacetBasedDetectedFrameworkDescription.java index d6b0450a5582..4ac3ed939aa2 100644 --- a/platform/lang-impl/src/com/intellij/framework/detection/impl/FacetBasedDetectedFrameworkDescription.java +++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/FacetBasedDetectedFrameworkDescription.java @@ -47,7 +47,7 @@ public class FacetBasedDetectedFrameworkDescription> newDescriptions = new HashMap>(); + final DetectionExcludesConfiguration excludesConfiguration = DetectionExcludesConfiguration.getInstance(myProject); for (Integer id : detectorsToProcess) { Collection files = index.getContainingFiles(FrameworkDetectionIndex.NAME, id, GlobalSearchScope.projectScope(myProject)); final Collection newFiles = myDetectedFrameworksData.retainNewFiles(id, files); - if (LOG.isDebugEnabled()) { - LOG.debug("Detector " + id + ": " + files.size() + " accepted files, " + newFiles.size() + " files to process"); - } FrameworkDetector detector = FrameworkDetectorRegistry.getInstance().getDetectorById(id); if (detector != null) { + excludesConfiguration.removeExcluded(newFiles, detector); + if (LOG.isDebugEnabled()) { + LOG.debug("Detector '" + detector.getFrameworkTypeId() + "': " + files.size() + " accepted files, " + newFiles.size() + " files to process"); + } final List frameworks; if (!newFiles.isEmpty()) { frameworks = detector.detect(newFiles, new FrameworkDetectionContextImpl(myProject)); diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/FrameworkDetectorRegistryImpl.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/FrameworkDetectorRegistryImpl.java index 07e3961e9e11..ad0607b6c41b 100644 --- a/platform/lang-impl/src/com/intellij/framework/detection/impl/FrameworkDetectorRegistryImpl.java +++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/FrameworkDetectorRegistryImpl.java @@ -47,7 +47,7 @@ public class FrameworkDetectorRegistryImpl extends FrameworkDetectorRegistry { private void loadDetectors() { Map newDetectors = new HashMap(); for (FrameworkDetector detector : FrameworkDetector.EP_NAME.getExtensions()) { - newDetectors.put(detector.getDetectorId(), detector); + newDetectors.put(detector.getFrameworkTypeId(), detector); } myDetectorIds = new TObjectIntHashMap(); @@ -106,10 +106,10 @@ public class FrameworkDetectorRegistryImpl extends FrameworkDetectorRegistry { myDetectorById = new TIntObjectHashMap(); myDetectorsByFileType = new MultiMap(); for (FrameworkDetector detector : FrameworkDetector.EP_NAME.getExtensions()) { - final int id = myDetectorIds.get(detector.getDetectorId()); + final int id = myDetectorIds.get(detector.getFrameworkTypeId()); myDetectorsByFileType.putValue(detector.getFileType(), id); myDetectorById.put(id, detector); - LOG.debug("'" + detector.getDetectorId() + "' framework detector: id = " + id); + LOG.debug("'" + detector.getFrameworkTypeId() + "' framework detector: id = " + id); } } @@ -124,8 +124,8 @@ public class FrameworkDetectorRegistryImpl extends FrameworkDetectorRegistry { final FrameworkDetector[] detectors = FrameworkDetector.EP_NAME.getExtensions(); output.writeInt(detectors.length); for (FrameworkDetector detector : detectors) { - output.writeUTF(detector.getDetectorId()); - output.writeInt(myDetectorIds.get(detector.getDetectorId())); + output.writeUTF(detector.getFrameworkTypeId()); + output.writeInt(myDetectorIds.get(detector.getFrameworkTypeId())); output.writeInt(detector.getDetectorVersion()); } } @@ -153,7 +153,7 @@ public class FrameworkDetectorRegistryImpl extends FrameworkDetectorRegistry { @Override public int getDetectorId(@NotNull FrameworkDetector detector) { - return myDetectorIds.get(detector.getDetectorId()); + return myDetectorIds.get(detector.getFrameworkTypeId()); } @Override diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurationImpl.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurationImpl.java new file mode 100644 index 000000000000..003bba04b14c --- /dev/null +++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurationImpl.java @@ -0,0 +1,167 @@ +/* + * Copyright 2000-2011 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.framework.detection.impl.exclude; + +import com.intellij.framework.FrameworkType; +import com.intellij.framework.detection.DetectionExcludesConfiguration; +import com.intellij.framework.detection.FrameworkDetector; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.components.PersistentStateComponent; +import com.intellij.openapi.components.State; +import com.intellij.openapi.components.Storage; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.pointers.VirtualFilePointerContainer; +import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager; +import com.intellij.util.containers.FactoryMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +/** + * @author nik + */ +@State( + name = "FrameworkDetectionExcludesConfiguration", + storages = { + @Storage( + id="other", + file = "$PROJECT_FILE$" + ) + } +) +public class DetectionExcludesConfigurationImpl extends DetectionExcludesConfiguration + implements PersistentStateComponent, Disposable { + private Map myExcludedFiles; + private Set myExcludedFrameworks; + private VirtualFilePointerManager myPointerManager; + + public DetectionExcludesConfigurationImpl(VirtualFilePointerManager pointerManager) { + myPointerManager = pointerManager; + myExcludedFrameworks = new HashSet(); + myExcludedFiles = new FactoryMap() { + @Override + protected VirtualFilePointerContainer create(String key) { + return myPointerManager.createContainer(DetectionExcludesConfigurationImpl.this); + } + }; + } + + @Override + public void addExcludedFramework(@NotNull FrameworkType type) { + myExcludedFrameworks.add(type.getId()); + final VirtualFilePointerContainer container = myExcludedFiles.remove(type.getId()); + if (container != null) { + container.clear(); + } + } + + private boolean isFileExcluded(@NotNull VirtualFile file, @Nullable String typeId) { + if (myExcludedFiles.containsKey(typeId) && isUnder(file, myExcludedFiles.get(typeId))) return true; + return typeId != null && myExcludedFiles.containsKey(null) && isUnder(file, myExcludedFiles.get(null)); + } + + private static boolean isUnder(VirtualFile file, final VirtualFilePointerContainer container) { + for (VirtualFile excludedFile : container.getFiles()) { + if (VfsUtil.isAncestor(excludedFile, file, false)) { + return true; + } + } + return false; + } + + @Override + public void addExcludedFile(@NotNull VirtualFile file, @Nullable FrameworkType type) { + final String typeId = type != null ? type.getId() : null; + if (typeId != null && myExcludedFrameworks.contains(typeId) || isFileExcluded(file, typeId)) { + return; + } + + final VirtualFilePointerContainer container = myExcludedFiles.get(typeId); + if (typeId == null) { + for (VirtualFilePointerContainer pointerContainer : myExcludedFiles.values()) { + removeDescendants(file, pointerContainer); + } + } + else { + removeDescendants(file, container); + } + container.add(file); + } + + private void removeDescendants(VirtualFile file, VirtualFilePointerContainer container) { + for (VirtualFile virtualFile : container.getFiles()) { + if (VfsUtil.isAncestor(file, virtualFile, false)) { + container.remove(myPointerManager.create(virtualFile, this, null)); + } + } + } + + @Override + public void removeExcluded(@NotNull Collection files, @NotNull FrameworkDetector detector) { + if (myExcludedFrameworks.contains(detector.getFrameworkTypeId())) { + files.clear(); + return; + } + + final Iterator iterator = files.iterator(); + while (iterator.hasNext()) { + VirtualFile file = iterator.next(); + if (isFileExcluded(file, detector.getFrameworkTypeId())) { + iterator.remove(); + } + } + } + + @Override + public ExcludesConfigurationState getState() { + final ExcludesConfigurationState state = new ExcludesConfigurationState(); + state.getFrameworkTypes().addAll(myExcludedFrameworks); + Collections.sort(state.getFrameworkTypes()); + + for (String typeId : myExcludedFiles.keySet()) { + final VirtualFilePointerContainer container = myExcludedFiles.get(typeId); + for (String url : container.getUrls()) { + state.getFiles().add(new ExcludedFileState(url, typeId)); + } + } + Collections.sort(state.getFiles(), new Comparator() { + @Override + public int compare(ExcludedFileState o1, ExcludedFileState o2) { + return Comparing.comparePairs(o1.getUrl(), o1.getFrameworkType(), o2.getUrl(), o2.getFrameworkType()); + } + }); + return state; + } + + @Override + public void loadState(ExcludesConfigurationState state) { + myExcludedFrameworks.clear(); + myExcludedFrameworks.addAll(state.getFrameworkTypes()); + for (VirtualFilePointerContainer container : myExcludedFiles.values()) { + container.clear(); + } + for (ExcludedFileState fileState : state.getFiles()) { + myExcludedFiles.get(fileState.getFrameworkType()).add(fileState.getUrl()); + } + } + + @Override + public void dispose() { + } +} diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/ExcludedFileState.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/ExcludedFileState.java new file mode 100644 index 000000000000..8d62a8dc298b --- /dev/null +++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/ExcludedFileState.java @@ -0,0 +1,69 @@ +/* + * Copyright 2000-2011 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.framework.detection.impl.exclude; + +import com.intellij.openapi.util.Comparing; +import com.intellij.util.xmlb.annotations.Attribute; +import com.intellij.util.xmlb.annotations.Tag; + +/** + * @author nik + */ +@Tag("file") +public class ExcludedFileState { + private String myUrl; + private String myFrameworkType; + + public ExcludedFileState() { + } + + public ExcludedFileState(String url, String frameworkType) { + myUrl = url; + myFrameworkType = frameworkType; + } + + @Attribute("url") + public String getUrl() { + return myUrl; + } + + public void setUrl(String url) { + myUrl = url; + } + + @Attribute("type") + public String getFrameworkType() { + return myFrameworkType; + } + + public void setFrameworkType(String frameworkType) { + myFrameworkType = frameworkType; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + ExcludedFileState state = (ExcludedFileState)o; + return Comparing.equal(myFrameworkType, state.myFrameworkType) && Comparing.equal(myUrl, state.myUrl); + } + + @Override + public int hashCode() { + return Comparing.hashcode(myUrl, myFrameworkType); + } +} diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/ExcludesConfigurationState.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/ExcludesConfigurationState.java new file mode 100644 index 000000000000..828c153dd696 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/ExcludesConfigurationState.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2011 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.framework.detection.impl.exclude; + +import com.intellij.util.xmlb.annotations.AbstractCollection; +import com.intellij.util.xmlb.annotations.Property; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author nik + */ +public class ExcludesConfigurationState { + private List myFrameworkTypes = new ArrayList(); + private List myFiles = new ArrayList(); + + @Property(surroundWithTag = false) + @AbstractCollection(surroundWithTag = false, elementTag = "type", elementValueAttribute = "id") + public List getFrameworkTypes() { + return myFrameworkTypes; + } + + @Property(surroundWithTag = false) + @AbstractCollection(surroundWithTag = false) + public List getFiles() { + return myFiles; + } + + public void setFrameworkTypes(List frameworkTypes) { + myFrameworkTypes = frameworkTypes; + } + + public void setFiles(List files) { + myFiles = files; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ExcludesConfigurationState)) return false; + + ExcludesConfigurationState state = (ExcludesConfigurationState)o; + return myFiles.equals(state.myFiles) && myFrameworkTypes.equals(state.myFrameworkTypes); + } + + @Override + public int hashCode() { + return 31 * myFrameworkTypes.hashCode() + myFiles.hashCode(); + } +} diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/DetectedFrameworkNode.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/DetectedFrameworkNode.java index c3655ef7dbf7..f2e848b3f496 100644 --- a/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/DetectedFrameworkNode.java +++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/DetectedFrameworkNode.java @@ -16,6 +16,7 @@ package com.intellij.framework.detection.impl.ui; import com.intellij.framework.detection.DetectedFrameworkDescription; +import com.intellij.framework.detection.DetectionExcludesConfiguration; import com.intellij.framework.detection.FrameworkDetectionContext; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.vfs.VfsUtil; @@ -75,13 +76,22 @@ class DetectedFrameworkNode extends DetectedFrameworkTreeNodeBase { } @Override - public String getActionDescription() { - if (isChecked()) { - return myDescription.getSetupDescription(); - } + public String getCheckedDescription() { + return myDescription.getSetupDescription(); + } + + @Override + public String getUncheckedDescription() { return null; } + @Override + public void disableDetection(DetectionExcludesConfiguration configuration) { + for (VirtualFile file : myDescription.getRelatedFiles()) { + configuration.addExcludedFile(file, myDescription.getFrameworkType()); + } + } + private void appendDirectoryPath(ColoredTreeCellRenderer renderer, final VirtualFile dir) { renderer.append(" (" + getRelativePath(dir) + ")", SimpleTextAttributes.GRAY_ATTRIBUTES); } diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/DetectedFrameworkTreeNodeBase.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/DetectedFrameworkTreeNodeBase.java index 1881f5f5e024..7aa8b10ae4b2 100644 --- a/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/DetectedFrameworkTreeNodeBase.java +++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/DetectedFrameworkTreeNodeBase.java @@ -15,6 +15,7 @@ */ package com.intellij.framework.detection.impl.ui; +import com.intellij.framework.detection.DetectionExcludesConfiguration; import com.intellij.ui.CheckedTreeNode; import com.intellij.ui.ColoredTreeCellRenderer; import org.jetbrains.annotations.Nullable; @@ -31,5 +32,10 @@ abstract class DetectedFrameworkTreeNodeBase extends CheckedTreeNode { public abstract void renderNode(ColoredTreeCellRenderer renderer); @Nullable - public abstract String getActionDescription(); + public abstract String getCheckedDescription(); + + @Nullable + public abstract String getUncheckedDescription(); + + public abstract void disableDetection(DetectionExcludesConfiguration configuration); } diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/DetectedFrameworksTree.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/DetectedFrameworksTree.java index 9e3a3f6b63bf..30d3ea61dfcf 100644 --- a/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/DetectedFrameworksTree.java +++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/DetectedFrameworksTree.java @@ -22,6 +22,7 @@ import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.CheckboxTree; import com.intellij.ui.CheckedTreeNode; +import com.intellij.util.Consumer; import com.intellij.util.ui.tree.TreeUtil; import org.jetbrains.annotations.NotNull; @@ -91,6 +92,18 @@ public class DetectedFrameworksTree extends CheckboxTree { } } + public void processUncheckedNodes(@NotNull final Consumer consumer) { + TreeUtil.traverse(getRoot(), new TreeUtil.Traverse() { + @Override + public boolean accept(Object node) { + if (node instanceof DetectedFrameworkTreeNodeBase) { + consumer.consume((DetectedFrameworkTreeNodeBase)node); + } + return true; + } + }); + } + private static FrameworkDirectoryNode collapseDirectoryNode(FrameworkDirectoryNode node) { if (node.getChildCount() == 1) { final TreeNode child = node.getChildAt(0); diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/FrameworkDirectoryNode.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/FrameworkDirectoryNode.java index 916dea383e9c..aedf1ccb83d0 100644 --- a/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/FrameworkDirectoryNode.java +++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/FrameworkDirectoryNode.java @@ -15,6 +15,7 @@ */ package com.intellij.framework.detection.impl.ui; +import com.intellij.framework.detection.DetectionExcludesConfiguration; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -39,6 +40,10 @@ class FrameworkDirectoryNode extends DetectedFrameworkTreeNodeBase { @Override public void renderNode(ColoredTreeCellRenderer renderer) { renderer.setIcon(PlatformIcons.FOLDER_ICON); + renderer.append(getRelativePath()); + } + + private String getRelativePath() { final TreeNode parent = getParent(); String path; if (parent instanceof FrameworkDirectoryNode) { @@ -49,11 +54,21 @@ class FrameworkDirectoryNode extends DetectedFrameworkTreeNodeBase { else { path = myDirectory.getPresentableUrl(); } - renderer.append(path); + return path; } @Override - public String getActionDescription() { + public String getCheckedDescription() { return null; } + + @Override + public String getUncheckedDescription() { + return "'" + getRelativePath() + "' directory will be excluded from framework detection"; + } + + @Override + public void disableDetection(DetectionExcludesConfiguration configuration) { + configuration.addExcludedFile(myDirectory, null); + } } diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/FrameworkTypeNode.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/FrameworkTypeNode.java index 2c965c813998..cb4f4ffe93d9 100644 --- a/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/FrameworkTypeNode.java +++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/FrameworkTypeNode.java @@ -16,6 +16,7 @@ package com.intellij.framework.detection.impl.ui; import com.intellij.framework.FrameworkType; +import com.intellij.framework.detection.DetectionExcludesConfiguration; import com.intellij.ui.ColoredTreeCellRenderer; import org.jetbrains.annotations.NotNull; @@ -37,7 +38,17 @@ class FrameworkTypeNode extends DetectedFrameworkTreeNodeBase { } @Override - public String getActionDescription() { + public String getCheckedDescription() { return null; } + + @Override + public String getUncheckedDescription() { + return "'" + myFrameworkType.getPresentableName() + "' framework detection will be disabled."; + } + + @Override + public void disableDetection(DetectionExcludesConfiguration configuration) { + configuration.addExcludedFramework(myFrameworkType); + } } diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/SetupDetectedFrameworksDialog.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/SetupDetectedFrameworksDialog.java index f65b164ce1e9..8fa2b5185121 100644 --- a/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/SetupDetectedFrameworksDialog.java +++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/ui/SetupDetectedFrameworksDialog.java @@ -16,6 +16,7 @@ package com.intellij.framework.detection.impl.ui; import com.intellij.framework.detection.DetectedFrameworkDescription; +import com.intellij.framework.detection.DetectionExcludesConfiguration; import com.intellij.framework.detection.impl.FrameworkDetectionContextImpl; import com.intellij.ide.ui.ListCellRendererWrapper; import com.intellij.openapi.project.Project; @@ -24,7 +25,9 @@ import com.intellij.openapi.ui.Splitter; import com.intellij.ui.CheckedTreeNode; import com.intellij.ui.EnumComboBoxModel; import com.intellij.ui.ScrollPaneFactory; +import com.intellij.util.Consumer; import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.event.TreeSelectionEvent; @@ -46,9 +49,11 @@ public class SetupDetectedFrameworksDialog extends DialogWrapper { private Splitter mySplitter; private JComboBox myGroupByComboBox; private JLabel myDescriptionLabel; + private final Project myProject; - public SetupDetectedFrameworksDialog(Project project, List descriptions) { + public SetupDetectedFrameworksDialog(@NotNull Project project, @NotNull List descriptions) { super(project, true); + myProject = project; setTitle("Setup Frameworks"); final FrameworkDetectionContextImpl context = new FrameworkDetectionContextImpl(project); myTree = new DetectedFrameworksTree(descriptions, context, GroupByOption.TYPE) { @@ -79,7 +84,8 @@ public class SetupDetectedFrameworksDialog extends DialogWrapper { private void updateOptionsPanel() { final DetectedFrameworkTreeNodeBase[] nodes = myTree.getSelectedNodes(DetectedFrameworkTreeNodeBase.class, null); if (nodes.length == 1) { - String description = nodes[0].getActionDescription(); + final DetectedFrameworkTreeNodeBase node = nodes[0]; + String description = node.isChecked() ? node.getCheckedDescription() : node.getUncheckedDescription(); if (description != null) { myDescriptionLabel.setText(UIUtil.toHtml(description)); return; @@ -93,6 +99,17 @@ public class SetupDetectedFrameworksDialog extends DialogWrapper { return myMainPanel; } + @Override + protected void doOKAction() { + myTree.processUncheckedNodes(new Consumer() { + @Override + public void consume(DetectedFrameworkTreeNodeBase node) { + node.disableDetection(DetectionExcludesConfiguration.getInstance(myProject)); + } + }); + super.doOKAction(); + } + public List getSelectedFrameworks() { return Arrays.asList(myTree.getCheckedNodes(DetectedFrameworkDescription.class, null)); } diff --git a/platform/lang-impl/testSrc/com/intellij/framework/detection/DetectionExcludesConfigurationTest.java b/platform/lang-impl/testSrc/com/intellij/framework/detection/DetectionExcludesConfigurationTest.java new file mode 100644 index 000000000000..02a6638464a8 --- /dev/null +++ b/platform/lang-impl/testSrc/com/intellij/framework/detection/DetectionExcludesConfigurationTest.java @@ -0,0 +1,141 @@ +/* + * Copyright 2000-2011 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.framework.detection; + +import com.intellij.framework.FrameworkType; +import com.intellij.framework.detection.impl.exclude.DetectionExcludesConfigurationImpl; +import com.intellij.framework.detection.impl.exclude.ExcludedFileState; +import com.intellij.framework.detection.impl.exclude.ExcludesConfigurationState; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.testFramework.PlatformTestCase; +import com.intellij.util.ui.EmptyIcon; + +import java.io.File; +import java.io.IOException; + +/** + * @author nik + */ +public class DetectionExcludesConfigurationTest extends PlatformTestCase { + private VirtualFile myTempDir; + private VirtualFile myTempFile; + + @Override + protected void setUp() throws Exception { + super.setUp(); + final File tempDir = doCreateTempDir(); + final File file = new File(tempDir, "file.xml"); + FileUtil.createIfDoesntExist(file); + myTempDir = getVirtualFile(tempDir); + myTempFile = getVirtualFile(file); + } + + public void testAddExcludedFramework() { + getConfiguration().addExcludedFramework(getType()); + assertEquals("type", assertOneElement(getState().getFrameworkTypes())); + } + + public void testAddExcludedFile() { + getConfiguration().addExcludedFile(myTempDir, null); + assertEquals(myTempDir.getUrl(), assertOneElement(getState().getFiles()).getUrl()); + } + + public void testAddExcludedFileForExcludedFramework() { + final FrameworkType type = getType(); + getConfiguration().addExcludedFramework(type); + getConfiguration().addExcludedFile(myTempDir, type); + assertEmpty(getState().getFiles()); + getConfiguration().addExcludedFile(myTempDir, null); + assertOneElement(getState().getFiles()); + } + + public void testAddExcludedFrameworkForExcludedFile() { + final FrameworkType type = getType(); + getConfiguration().addExcludedFile(myTempDir, type); + assertOneElement(getState().getFiles()); + getConfiguration().addExcludedFramework(type); + assertEmpty(getState().getFiles()); + assertOneElement(getState().getFrameworkTypes()); + } + + public void testAddExcludedFileInExcludedDirectory() { + getConfiguration().addExcludedFile(myTempDir, null); + getConfiguration().addExcludedFile(myTempFile, null); + assertEquals(myTempDir.getUrl(), assertOneElement(getState().getFiles()).getUrl()); + + getConfiguration().addExcludedFile(myTempFile, getType()); + assertEquals(myTempDir.getUrl(), assertOneElement(getState().getFiles()).getUrl()); + + getConfiguration().addExcludedFile(myTempDir, getType()); + final ExcludedFileState state = assertOneElement(getState().getFiles()); + assertEquals(myTempDir.getUrl(), state.getUrl()); + assertNull(state.getFrameworkType()); + } + + public void testAddExcludedFileInExcludedDirectoryForDifferentFramework() { + getConfiguration().addExcludedFile(myTempDir, getType()); + getConfiguration().addExcludedFile(myTempFile, null); + assertEquals(2, getState().getFiles().size()); + } + + public void testAddExcludedDirectoryContainingExcludedFile() { + getConfiguration().addExcludedFile(myTempFile, null); + assertEquals(myTempFile.getUrl(), assertOneElement(getState().getFiles()).getUrl()); + getConfiguration().addExcludedFile(myTempDir, null); + assertEquals(myTempDir.getUrl(), assertOneElement(getState().getFiles()).getUrl()); + } + + public void testAddExcludedDirectoryContainingExcludedFileForAllFrameworks() { + getConfiguration().addExcludedFile(myTempFile, getType()); + assertEquals(myTempFile.getUrl(), assertOneElement(getState().getFiles()).getUrl()); + getConfiguration().addExcludedFile(myTempDir, null); + assertEquals(myTempDir.getUrl(), assertOneElement(getState().getFiles()).getUrl()); + } + + public void testAddExcludedDirectoryContainingExcludedFileForDifferentFramework() { + getConfiguration().addExcludedFile(myTempFile, getType()); + assertEquals(myTempFile.getUrl(), assertOneElement(getState().getFiles()).getUrl()); + getConfiguration().addExcludedFile(myTempDir, getType2()); + assertEquals(2, getState().getFiles().size()); + } + + + private ExcludesConfigurationState getState() { + return getConfiguration().getState(); + } + + private File doCreateTempDir() { + try { + return createTempDirectory(); + } + catch (IOException e) { + throw new RuntimeException(e); + } + } + + private static FrameworkType getType() { + return new FrameworkType("type", "Type", EmptyIcon.ICON_16); + } + + private static FrameworkType getType2() { + return new FrameworkType("type2", "Type2", EmptyIcon.ICON_16); + } + + private DetectionExcludesConfigurationImpl getConfiguration() { + return (DetectionExcludesConfigurationImpl)DetectionExcludesConfiguration.getInstance(myProject); + } +} diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 12b25641ec35..49936ba0cae1 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -203,6 +203,8 @@ + diff --git a/platform/util/src/com/intellij/openapi/util/Comparing.java b/platform/util/src/com/intellij/openapi/util/Comparing.java index f87f848cd1b3..21f01c0d8ae3 100644 --- a/platform/util/src/com/intellij/openapi/util/Comparing.java +++ b/platform/util/src/com/intellij/openapi/util/Comparing.java @@ -168,4 +168,9 @@ public class Comparing { if (o2 == null) return 1; return o1.compareTo(o2); } + + public static , S extends Comparable> int comparePairs(F aFirst, S aSecond, F bFirst, S bSecond) { + final int compare = compare(aFirst, bFirst); + return compare != 0 ? compare : compare(aSecond, bSecond); + } }