diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index 800db37461d2..fb8437096563 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -504,28 +504,29 @@ public class JavaCompletionUtil { } if (plainQualifier != null) { Object o = item.getObject(); - if (containsMember(plainQualifier, o)) { - if (!(o instanceof PsiMethod)) { - return item; - } + if (o instanceof PsiMethod) { PsiType castType = castTypeItem.getPsiType(); if (plainQualifier instanceof PsiClassType && castType instanceof PsiClassType) { PsiMethod method = (PsiMethod)o; PsiClassType.ClassResolveResult plainResult = ((PsiClassType)plainQualifier).resolveGenerics(); PsiClass plainClass = plainResult.getElement(); - PsiClass castClass = ((PsiClassType)castType).resolveGenerics().getElement(); + if (plainClass != null && plainClass.findMethodBySignature(method, true) != null) { + PsiClass castClass = ((PsiClassType)castType).resolveGenerics().getElement(); - if (castClass == null || plainClass == null || !castClass.isInheritor(plainClass, true)) { - return item; - } + if (castClass == null || !castClass.isInheritor(plainClass, true)) { + return item; + } - PsiSubstitutor plainSub = plainResult.getSubstitutor(); - PsiSubstitutor castSub = TypeConversionUtil.getSuperClassSubstitutor(plainClass, (PsiClassType)castType); - if (method.getSignature(plainSub).equals(method.getSignature(castSub)) && - plainSub.substitute(method.getReturnType()).equals(castSub.substitute(method.getReturnType()))) { - return item; + PsiSubstitutor plainSub = plainResult.getSubstitutor(); + PsiSubstitutor castSub = TypeConversionUtil.getSuperClassSubstitutor(plainClass, (PsiClassType)castType); + if (method.getSignature(plainSub).equals(method.getSignature(castSub)) && + plainSub.substitute(method.getReturnType()).equals(castSub.substitute(method.getReturnType()))) { + return item; + } } } + } else if (containsMember(plainQualifier, o)) { + return item; } } diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java index 5ce2fbd6c1f5..ee177909adad 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java @@ -123,7 +123,11 @@ public class StandardInstructionVisitor extends InstructionVisitor { final DfaValue qualifier = memState.pop(); if (instruction.getExpression().isPhysical() && !memState.applyNotNull(qualifier)) { onInstructionProducesNPE(instruction, runner); - return DfaInstructionState.EMPTY_ARRAY; + + if (qualifier instanceof DfaVariableValue) { + final DfaNotNullValue.Factory factory = runner.getFactory().getNotNullFactory(); + memState.setVarValue((DfaVariableValue)qualifier, factory.create(((DfaVariableValue)qualifier).getPsiVariable().getType())); + } } return nextInstruction(instruction, runner, memState); diff --git a/java/java-tests/testData/codeInsight/completion/normal/InterfaceImplementationNoCast.java b/java/java-tests/testData/codeInsight/completion/normal/InterfaceImplementationNoCast.java new file mode 100644 index 000000000000..5f342695a4fe --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/InterfaceImplementationNoCast.java @@ -0,0 +1,18 @@ +public class Util2 { + void foo(XmlAttribute o ) { + if (o instanceof XmlAttributeImpl) { + o.getpar + } + } +} + +interface PsiElement { + PsiElement getParent(); +} +interface XmlAttribute extends PsiElement {} +class XmlAttributeImpl implements XmlAttribute { + @Override + public PsiElement getParent() { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/InterfaceImplementationNoCast_after.java b/java/java-tests/testData/codeInsight/completion/normal/InterfaceImplementationNoCast_after.java new file mode 100644 index 000000000000..94718eeb8f2e --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/InterfaceImplementationNoCast_after.java @@ -0,0 +1,18 @@ +public class Util2 { + void foo(XmlAttribute o ) { + if (o instanceof XmlAttributeImpl) { + o.getParent() + } + } +} + +interface PsiElement { + PsiElement getParent(); +} +interface XmlAttribute extends PsiElement {} +class XmlAttributeImpl implements XmlAttribute { + @Override + public PsiElement getParent() { + return null; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index 49f4a214442c..772881af6d50 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -1325,5 +1325,6 @@ public class ListUtils { } public void testListArrayListCast() { doTest('\n') } + public void testInterfaceImplementationNoCast() { doTest() } } diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/ChangeListsScopesProvider.java b/platform/lang-impl/src/com/intellij/packageDependencies/ChangeListsScopesProvider.java index 7229c7dd08dc..1e9dcaeddd26 100644 --- a/platform/lang-impl/src/com/intellij/packageDependencies/ChangeListsScopesProvider.java +++ b/platform/lang-impl/src/com/intellij/packageDependencies/ChangeListsScopesProvider.java @@ -79,7 +79,7 @@ public class ChangeListsScopesProvider extends CustomScopesProviderEx { if (IdeBundle.message("scope.modified.files").equals(name)) { return createScope(changeListManager.getAffectedFiles(), IdeBundle.message("scope.modified.files")); } - final LocalChangeList changeList = changeListManager.getChangeList(name); + final LocalChangeList changeList = changeListManager.findChangeList(name); if (changeList != null) { return createChangeListScope(changeList); } diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java index 911243734158..dd3ebd75c5a5 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java @@ -379,22 +379,8 @@ public class SingleInspectionProfilePanel extends JPanel { }); actions.addSeparator(); - actions.add(new AddScopeAction(myTree){ - protected InspectionProfileImpl getSelectedProfile() { - return mySelectedProfile; - } - - @Override - public void actionPerformed(AnActionEvent e) { - super.actionPerformed(e); - updateOptionsAndDescriptionPanel(myTree.getSelectionPath()); - } - }); - actions.add(new DeleteScopeAction(myTree){ - protected InspectionProfileImpl getSelectedProfile() { - return mySelectedProfile; - } - }); + actions.add(new MyAddScopeAction()); + actions.add(new MyDeleteScopeAction()); actions.add(new MoveScopeAction(myTree, "Move Scope Up", IconLoader.getIcon("/actions/moveUp.png"), -1) { protected boolean isEnabledFor(int idx, InspectionConfigTreeNode parent) { return idx > 0; @@ -568,7 +554,7 @@ public class SingleInspectionProfilePanel extends JPanel { } private JPopupMenu compoundPopup() { - final JPopupMenu popup = new JPopupMenu(InspectionsBundle.message("inspection.error.level.popup.menu.title")); + final DefaultActionGroup group = new DefaultActionGroup(); final SeverityRegistrar severityRegistrar = ((SeverityProvider)mySelectedProfile.getProfileManager()).getOwnSeverityRegistrar(); TreeSet severities = new TreeSet(severityRegistrar); severities.add(HighlightSeverity.ERROR); @@ -581,12 +567,18 @@ public class SingleInspectionProfilePanel extends JPanel { } for (HighlightSeverity severity : severities) { final HighlightDisplayLevel level = HighlightDisplayLevel.find(severity); - final JMenuItem item = new JMenuItem(renderSeverity(level.getSeverity())); - item.setIcon(level.getIcon()); //todo correct position - item.addActionListener(new LevelSelection(level)); - popup.add(item); + group.add(new AnAction(renderSeverity(severity), renderSeverity(severity), level.getIcon()) { + @Override + public void actionPerformed(AnActionEvent e) { + setNewHighlightingLevel(level); + } + }); } - return popup; + group.add(Separator.getInstance()); + group.add(new MyAddScopeAction()); + group.add(new MyDeleteScopeAction()); + ActionPopupMenu menu = ActionManager.getInstance().createActionPopupMenu(ActionPlaces.UNKNOWN, group); + return menu.getComponent(); } static String renderSeverity(HighlightSeverity severity) { @@ -1051,6 +1043,57 @@ public class SingleInspectionProfilePanel extends JPanel { super.setVisible(aFlag); } + private void setNewHighlightingLevel(final HighlightDisplayLevel level) { + final int[] rows = myTree.getSelectionRows(); + final boolean showOptionsAndDescriptorPanels = rows != null && rows.length == 1; + for (int i = 0; rows != null && i < rows.length; i++) { + final InspectionConfigTreeNode node = (InspectionConfigTreeNode)myTree.getPathForRow(rows[i]).getLastPathComponent(); + final InspectionConfigTreeNode parent = (InspectionConfigTreeNode)node.getParent(); + if (node.getUserObject() instanceof Descriptor) { + updateErrorLevel(node, showOptionsAndDescriptorPanels, level); + updateUpHierarchy(node, parent); + } + else { + node.isProperSetting = false; + for (int j = 0; j < node.getChildCount(); j++) { + final InspectionConfigTreeNode child = (InspectionConfigTreeNode)node.getChildAt(j); + if (child.getUserObject() instanceof Descriptor) { //group node + updateErrorLevel(child, showOptionsAndDescriptorPanels, level); + } + else { //root node + child.isProperSetting = false; + for (int k = 0; k < child.getChildCount(); k++) { + final InspectionConfigTreeNode descriptorNode = (InspectionConfigTreeNode)child.getChildAt(k); + if (descriptorNode.getUserObject() instanceof Descriptor) { + updateErrorLevel(descriptorNode, showOptionsAndDescriptorPanels, level); + } + child.isProperSetting |= descriptorNode.isProperSetting; + } + } + node.isProperSetting |= child.isProperSetting; + } + updateUpHierarchy(node, parent); + } + } + if (rows != null && rows.length == 1) { + updateOptionsAndDescriptionPanel(myTree.getPathForRow(rows[0])); + } + else { + initOptionsAndDescriptionPanel(); + } + repaintTableData(); + } + + private void updateErrorLevel(final InspectionConfigTreeNode child, + final boolean showOptionsAndDescriptorPanels, final HighlightDisplayLevel level) { + final HighlightDisplayKey key = child.getDesriptor().getKey(); + mySelectedProfile.setErrorLevel(key, level, child.isInspectionNode() || child.isByDefault() ? -1 : child.getParent().getIndex(child)); + child.isProperSetting = mySelectedProfile.isProperSetting(key); + if (showOptionsAndDescriptorPanels) { + updateOptionsAndDescriptionPanel(new TreePath(child.getPath())); + } + } + private class LevelSelection implements ActionListener { private final HighlightDisplayLevel myLevel; @@ -1059,53 +1102,7 @@ public class SingleInspectionProfilePanel extends JPanel { } public void actionPerformed(ActionEvent e) { - final int[] rows = myTree.getSelectionRows(); - final boolean showOptionsAndDescriptorPanels = rows != null && rows.length == 1; - for (int i = 0; rows != null && i < rows.length; i++) { - final InspectionConfigTreeNode node = (InspectionConfigTreeNode)myTree.getPathForRow(rows[i]).getLastPathComponent(); - final InspectionConfigTreeNode parent = (InspectionConfigTreeNode)node.getParent(); - if (node.getUserObject() instanceof Descriptor) { - updateErrorLevel(node, showOptionsAndDescriptorPanels); - updateUpHierarchy(node, parent); - } - else { - node.isProperSetting = false; - for (int j = 0; j < node.getChildCount(); j++) { - final InspectionConfigTreeNode child = (InspectionConfigTreeNode)node.getChildAt(j); - if (child.getUserObject()instanceof Descriptor) { //group node - updateErrorLevel(child, showOptionsAndDescriptorPanels); - } - else { //root node - child.isProperSetting = false; - for (int k = 0; k < child.getChildCount(); k++) { - final InspectionConfigTreeNode descriptorNode = (InspectionConfigTreeNode)child.getChildAt(k); - if (descriptorNode.getUserObject()instanceof Descriptor) { - updateErrorLevel(descriptorNode, showOptionsAndDescriptorPanels); - } - child.isProperSetting |= descriptorNode.isProperSetting; - } - } - node.isProperSetting |= child.isProperSetting; - } - updateUpHierarchy(node, parent); - } - } - if (rows != null && rows.length == 1) { - updateOptionsAndDescriptionPanel(myTree.getPathForRow(rows[0])); - } - else { - initOptionsAndDescriptionPanel(); - } - repaintTableData(); - } - - private void updateErrorLevel(final InspectionConfigTreeNode child, final boolean showOptionsAndDescriptorPanels) { - final HighlightDisplayKey key = child.getDesriptor().getKey(); - mySelectedProfile.setErrorLevel(key, myLevel, child.isInspectionNode() || child.isByDefault() ? -1 : child.getParent().getIndex(child)); - child.isProperSetting = mySelectedProfile.isProperSetting(key); - if (showOptionsAndDescriptorPanels) { - updateOptionsAndDescriptionPanel(new TreePath(child.getPath())); - } + setNewHighlightingLevel(myLevel); } } @@ -1135,4 +1132,34 @@ public class SingleInspectionProfilePanel extends JPanel { } } + private class MyAddScopeAction extends AddScopeAction { + public MyAddScopeAction() { + super(SingleInspectionProfilePanel.this.myTree); + } + + protected InspectionProfileImpl getSelectedProfile() { + return mySelectedProfile; + } + + @Override + public void actionPerformed(AnActionEvent e) { + super.actionPerformed(e); + final TreePath[] paths = myTree.getSelectionPaths(); + if (paths != null && paths.length == 1) { + updateOptionsAndDescriptionPanel(myTree.getSelectionPath()); + } else { + initOptionsAndDescriptionPanel(); + } + } + } + + private class MyDeleteScopeAction extends DeleteScopeAction { + public MyDeleteScopeAction() { + super(SingleInspectionProfilePanel.this.myTree); + } + + protected InspectionProfileImpl getSelectedProfile() { + return mySelectedProfile; + } + } } diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/actions/AddScopeAction.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/actions/AddScopeAction.java index b6b321646101..15d705ccbc82 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/actions/AddScopeAction.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/actions/AddScopeAction.java @@ -59,54 +59,67 @@ public abstract class AddScopeAction extends AnAction { final Project project = PlatformDataKeys.PROJECT.getData(e.getDataContext()); if (project == null) return; final InspectionConfigTreeNode[] nodes = myTree.getSelectedNodes(InspectionConfigTreeNode.class, null); - if (nodes.length > 0) { - final InspectionConfigTreeNode node = nodes[0]; + final List descriptors = new ArrayList(); + for (InspectionConfigTreeNode node : nodes) { final Descriptor descriptor = node.getDesriptor(); - if (descriptor != null && node.getScopeName() == null && !getAvailableScopes(descriptor, project).isEmpty()) { - presentation.setEnabled(true); + if (descriptor != null && node.getScopeName() == null) { + descriptors.add(descriptor); } } + + presentation.setEnabled(!getAvailableScopes(project, descriptors).isEmpty()); } @Override public void actionPerformed(AnActionEvent e) { final InspectionConfigTreeNode[] nodes = myTree.getSelectedNodes(InspectionConfigTreeNode.class, null); - final InspectionConfigTreeNode node = nodes[0]; - final Descriptor descriptor = node.getDesriptor(); - LOG.assertTrue(descriptor != null); - final Project project = PlatformDataKeys.PROJECT.getData(e.getDataContext()); - final InspectionProfileEntry tool = descriptor.getTool(); //copy - final List availableScopes = getAvailableScopes(descriptor, project); + List descriptors = new ArrayList(); + for (InspectionConfigTreeNode node : nodes) { + final Descriptor descriptor = node.getDesriptor(); + if (node.getScopeName() == null && descriptor != null) { + descriptors.add(descriptor); + } + } + final Project project = PlatformDataKeys.PROJECT.getData(e.getDataContext()); + final List availableScopes = getAvailableScopes(project, descriptors); final int idx = Messages.showChooseDialog(myTree, "Scope:", "Choose Scope", ArrayUtil.toStringArray(availableScopes), availableScopes.get(0), Messages.getQuestionIcon()); if (idx == -1) return; final NamedScope chosenScope = NamedScopesHolder.getScope(project, availableScopes.get(idx)); - final ScopeToolState scopeToolState = getSelectedProfile().addScope(tool, chosenScope, - getSelectedProfile().getErrorLevel(descriptor.getKey(), chosenScope), - getSelectedProfile().isToolEnabled(descriptor.getKey())); - final Descriptor addedDescriptor = new Descriptor(scopeToolState, getSelectedProfile()); - if (node.getChildCount() == 0) { - node.add(new InspectionConfigTreeNode(descriptor, scopeToolState, true, true, false)); + + for (InspectionConfigTreeNode node : nodes) { + final Descriptor descriptor = node.getDesriptor(); + if (node.getScopeName() != null || descriptor == null) continue; + final InspectionProfileEntry tool = descriptor.getTool(); //copy + final ScopeToolState scopeToolState = getSelectedProfile().addScope(tool, chosenScope, + getSelectedProfile().getErrorLevel(descriptor.getKey(), chosenScope), + getSelectedProfile().isToolEnabled(descriptor.getKey())); + final Descriptor addedDescriptor = new Descriptor(scopeToolState, getSelectedProfile()); + if (node.getChildCount() == 0) { + node.add(new InspectionConfigTreeNode(descriptor, scopeToolState, true, true, false)); + } + node.insert(new InspectionConfigTreeNode(addedDescriptor, scopeToolState, false, true, false), 0); + node.setInspectionNode(false); + node.isProperSetting = getSelectedProfile().isProperSetting(HighlightDisplayKey.find(tool.getShortName())); + ((DefaultTreeModel)myTree.getModel()).reload(node); + myTree.expandPath(new TreePath(node.getPath())); } - node.insert(new InspectionConfigTreeNode(addedDescriptor, scopeToolState, false, true, false), 0); - node.setInspectionNode(false); - node.isProperSetting = getSelectedProfile().isProperSetting(HighlightDisplayKey.find(tool.getShortName())); - ((DefaultTreeModel)myTree.getModel()).reload(node); - myTree.expandPath(new TreePath(node.getPath())); myTree.revalidate(); } - private List getAvailableScopes(Descriptor descriptor, Project project) { + private List getAvailableScopes(Project project, List descriptors) { final ArrayList scopes = new ArrayList(); for (NamedScopesHolder holder : NamedScopesHolder.getAllNamedScopeHolders(project)) { Collections.addAll(scopes, holder.getScopes()); } scopes.remove(DefaultScopesProvider.getAllScope()); final Set used = new HashSet(); - final List nonDefaultTools = getSelectedProfile().getNonDefaultTools(descriptor.getKey().toString()); - if (nonDefaultTools != null) { - for (ScopeToolState state : nonDefaultTools) { - used.add(state.getScope(project)); + for (Descriptor descriptor : descriptors) { + final List nonDefaultTools = getSelectedProfile().getNonDefaultTools(descriptor.getKey().toString()); + if (nonDefaultTools != null) { + for (ScopeToolState state : nonDefaultTools) { + used.add(state.getScope(project)); + } } } scopes.removeAll(used); diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index e19855dc5a48..235aad239af4 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -581,7 +581,8 @@ - + diff --git a/plugins/git4idea/src/git4idea/roots/GitRootsListener.java b/platform/util/src/com/intellij/util/NotNullProducer.java similarity index 72% rename from plugins/git4idea/src/git4idea/roots/GitRootsListener.java rename to platform/util/src/com/intellij/util/NotNullProducer.java index 62c07c802fcf..12ff1c38bd8f 100644 --- a/plugins/git4idea/src/git4idea/roots/GitRootsListener.java +++ b/platform/util/src/com/intellij/util/NotNullProducer.java @@ -13,17 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package git4idea.roots; +package com.intellij.util; -import com.intellij.openapi.vfs.VirtualFile; - -import java.util.Collection; - -/** - * @author Kirill Likhodedov - */ -public interface GitRootsListener { - - void gitRootsChanged(Collection roots); +import org.jetbrains.annotations.NotNull; +public interface NotNullProducer extends Producer { + @Override + @NotNull + T produce(); } diff --git a/platform/util/src/com/intellij/util/concurrency/FutureResult.java b/platform/util/src/com/intellij/util/concurrency/FutureResult.java index d5ad8640b416..141b21816886 100644 --- a/platform/util/src/com/intellij/util/concurrency/FutureResult.java +++ b/platform/util/src/com/intellij/util/concurrency/FutureResult.java @@ -2,6 +2,7 @@ package com.intellij.util.concurrency; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; +import org.jetbrains.annotations.Nullable; import java.util.concurrent.*; import java.util.concurrent.Semaphore; @@ -27,7 +28,7 @@ public class FutureResult implements Future { return myValue != null; } - public void set(T result) { + public void set(@Nullable T result) { assert myValue == null; myValue = Ref.create(Pair.create((Object)result, true)); diff --git a/plugins/git4idea/src/git4idea/GitRootConverter.java b/plugins/git4idea/src/git4idea/GitRootConverter.java index 862ea923ac68..0250524bcaf5 100644 --- a/plugins/git4idea/src/git4idea/GitRootConverter.java +++ b/plugins/git4idea/src/git4idea/GitRootConverter.java @@ -16,72 +16,32 @@ package git4idea; -import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.AbstractVcs; -import com.intellij.openapi.vcs.VcsDirectoryMapping; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.HashSet; -import git4idea.repo.GitRepositoryManager; -import git4idea.roots.GitRootDetector; -import git4idea.roots.GitRootsListener; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.ArrayList; -import java.util.Collection; import java.util.List; /** * Given VFS content roots, filters them and returns only those, which are actual Git roots. */ -public class GitRootConverter implements AbstractVcs.RootsConvertor, GitRootsListener { +public class GitRootConverter implements AbstractVcs.RootsConvertor { - @NotNull private final Project myProject; - @NotNull private final PlatformFacade myPlatformFacade; - - @Nullable private Collection myDetectedRoots; - - public GitRootConverter(@NotNull Project project, @NotNull PlatformFacade facade) { - myProject = project; - myPlatformFacade = facade; - myProject.getMessageBus().connect().subscribe(GitRepositoryManager.GIT_ROOTS_CHANGE, this); - } + public static final GitRootConverter INSTANCE = new GitRootConverter(); @NotNull public List convertRoots(@NotNull List result) { - if (myDetectedRoots == null) { - myDetectedRoots = new GitRootDetector(myProject, myPlatformFacade).detect().getRoots(); - } - + // TODO this should be faster, because it is called rather often. gitRootOrNull could be a bottle-neck. ArrayList roots = new ArrayList(); - if (hasProjectMapping()) { - roots.addAll(myDetectedRoots); - } - HashSet listed = new HashSet(); for (VirtualFile f : result) { VirtualFile r = GitUtil.gitRootOrNull(f); if (r != null && listed.add(r)) { - if (!roots.contains(r)) { - roots.add(r); - } + roots.add(r); } } return roots; } - - private boolean hasProjectMapping() { - for (VcsDirectoryMapping mapping : myPlatformFacade.getVcsManager(myProject).getDirectoryMappings()) { - if (mapping.isDefaultMapping()) { - return true; - } - } - return false; - } - - @Override - public void gitRootsChanged(Collection roots) { - myDetectedRoots = roots; - } - } diff --git a/plugins/git4idea/src/git4idea/GitUtil.java b/plugins/git4idea/src/git4idea/GitUtil.java index adcc40604db6..9d21bab8482c 100644 --- a/plugins/git4idea/src/git4idea/GitUtil.java +++ b/plugins/git4idea/src/git4idea/GitUtil.java @@ -48,6 +48,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.util.*; @@ -93,6 +94,43 @@ public class GitUtil { // do nothing } + @Nullable + public static VirtualFile findGitDir(@NotNull VirtualFile rootDir) { + VirtualFile child = rootDir.findChild(".git"); + if (child == null) { + return null; + } + if (child.isDirectory()) { + return child; + } + + // this is standard for submodules, although probably it can + String content = readFile(child); + String pathToDir; + String prefix = "gitdir:"; + if (content.startsWith(prefix)) { + pathToDir = content.substring(prefix.length()).trim(); + } + else { + pathToDir = content; + } + return VcsUtil.getVirtualFile(pathToDir); + } + + @NotNull + private static String readFile(@NotNull VirtualFile file) { + Exception exception = null; + for (int attempts = 0; attempts < 3; attempts++) { + try { + return new String(file.contentsToByteArray()); + } + catch (IOException e) { + exception = e; + } + } + throw new RuntimeException("Couldn't read " + file, exception); + } + /** * Sort files by Git root * diff --git a/plugins/git4idea/src/git4idea/GitVcs.java b/plugins/git4idea/src/git4idea/GitVcs.java index 6f4e778b7655..8bee54c341f3 100644 --- a/plugins/git4idea/src/git4idea/GitVcs.java +++ b/plugins/git4idea/src/git4idea/GitVcs.java @@ -135,7 +135,6 @@ public class GitVcs extends AbstractVcs { private GitBranchWidget myBranchWidget; private GitVersion myVersion = GitVersion.NULL; // version of Git which this plugin uses. - private final GitRootConverter myRootConverter; @Nullable public static GitVcs getInstance(Project project) { @@ -175,7 +174,6 @@ public class GitVcs extends AbstractVcs { myTaskQueue = new BackgroundTaskQueue(myProject, GitBundle.getString("task.queue.title")); myExecutableValidator = new GitExecutableValidator(myProject, this); myPlatformFacade = ServiceManager.getService(myProject, PlatformFacade.class); - myRootConverter = new GitRootConverter(myProject, myPlatformFacade); } @@ -497,7 +495,7 @@ public class GitVcs extends AbstractVcs { @Override public RootsConvertor getCustomConvertor() { - return myRootConverter; + return GitRootConverter.INSTANCE; } public static VcsKey getKey() { diff --git a/plugins/git4idea/src/git4idea/PlatformFacade.java b/plugins/git4idea/src/git4idea/PlatformFacade.java index 8e8e60f55a58..4b7bd2146c9d 100644 --- a/plugins/git4idea/src/git4idea/PlatformFacade.java +++ b/plugins/git4idea/src/git4idea/PlatformFacade.java @@ -59,4 +59,6 @@ public interface PlatformFacade { * Invokes {@link com.intellij.openapi.application.Application#runReadAction(Computable)}. */ T runReadAction(@NotNull Computable computable); + + void runReadAction(@NotNull Runnable runnable); } diff --git a/plugins/git4idea/src/git4idea/PlatformFacadeImpl.java b/plugins/git4idea/src/git4idea/PlatformFacadeImpl.java index 0a7601305b18..1748811c1c90 100644 --- a/plugins/git4idea/src/git4idea/PlatformFacadeImpl.java +++ b/plugins/git4idea/src/git4idea/PlatformFacadeImpl.java @@ -57,6 +57,11 @@ public class PlatformFacadeImpl implements PlatformFacade { return ApplicationManager.getApplication().runReadAction(computable); } + @Override + public void runReadAction(@NotNull Runnable runnable) { + ApplicationManager.getApplication().runReadAction(runnable); + } + @NotNull @Override public AbstractVcs getVcs(@NotNull Project project) { diff --git a/plugins/git4idea/src/git4idea/repo/GitRepository.java b/plugins/git4idea/src/git4idea/repo/GitRepository.java index b3d88b4b5efc..12f571199f28 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepository.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepository.java @@ -26,6 +26,7 @@ import com.intellij.util.messages.MessageBus; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.messages.Topic; import git4idea.GitBranch; +import git4idea.GitUtil; import git4idea.branch.GitBranchesCollection; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -174,12 +175,12 @@ public final class GitRepository implements Disposable { myProject = project; Disposer.register(parentDisposable, this); - myGitDir = myRootDir.findChild(".git"); + myGitDir = GitUtil.findGitDir(myRootDir); assert myGitDir != null : ".git directory wasn't found under " + rootDir.getPresentableUrl(); myReader = new GitRepositoryReader(VfsUtil.virtualToIoFile(myGitDir)); - myUntrackedFilesHolder = new GitUntrackedFilesHolder(rootDir, project); + myUntrackedFilesHolder = new GitUntrackedFilesHolder(this); Disposer.register(this, myUntrackedFilesHolder); myMessageBus = project.getMessageBus(); @@ -222,6 +223,11 @@ public final class GitRepository implements Disposable { return myRootDir; } + @NotNull + public VirtualFile getGitDir() { + return myGitDir; + } + @NotNull public String getPresentableUrl() { return getRoot().getPresentableUrl(); diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryFiles.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryFiles.java index 3dea7f406c29..d4f68bb512f4 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryFiles.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryFiles.java @@ -45,16 +45,13 @@ public class GitRepositoryFiles { private final String myCommitMessagePath; private final String myExcludePath; - public static GitRepositoryFiles getInstance(@NotNull VirtualFile root) { + public static GitRepositoryFiles getInstance(@NotNull VirtualFile gitDir) { // maybe will be cached later to store a single GitRepositoryFiles for a root. - return new GitRepositoryFiles(root); + return new GitRepositoryFiles(gitDir); } - private GitRepositoryFiles(@NotNull VirtualFile root) { + private GitRepositoryFiles(@NotNull VirtualFile gitDir) { // add .git/ and .git/refs/heads to the VFS - VirtualFile gitDir = root.findChild(".git"); - assert gitDir != null; - // save paths of the files, that we will watch String gitDirPath = GitFileUtils.stripFileProtocolPrefix(gitDir.getPath()); myConfigFilePath = gitDirPath + "/config"; diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryManager.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryManager.java index e1c95222d77b..e75e8583e8d3 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryManager.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryManager.java @@ -16,8 +16,6 @@ package git4idea.repo; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.messages.Topic; -import git4idea.roots.GitRootsListener; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -29,8 +27,6 @@ import java.util.List; */ public interface GitRepositoryManager { - Topic GIT_ROOTS_CHANGE = Topic.create("Git Roots change", GitRootsListener.class); - /** * Returns the {@link GitRepository} which tracks the Git repository located in the given directory, * or {@code null} if the given file is not a Git root known to this {@link com.intellij.openapi.project.Project}. diff --git a/plugins/git4idea/src/git4idea/repo/GitRepositoryUpdater.java b/plugins/git4idea/src/git4idea/repo/GitRepositoryUpdater.java index cce8a02bf5ba..b495b534a295 100644 --- a/plugins/git4idea/src/git4idea/repo/GitRepositoryUpdater.java +++ b/plugins/git4idea/src/git4idea/repo/GitRepositoryUpdater.java @@ -50,11 +50,10 @@ final class GitRepositoryUpdater implements Disposable, BulkFileListener { myRepository = repository; VirtualFile root = repository.getRoot(); - VirtualFile gitDir = root.findChild(".git"); - assert gitDir != null; + VirtualFile gitDir = repository.getGitDir(); LocalFileSystem.getInstance().addRootToWatch(gitDir.getPath(), true); - myRepositoryFiles = GitRepositoryFiles.getInstance(root); + myRepositoryFiles = GitRepositoryFiles.getInstance(gitDir); visitGitDirVfs(gitDir); myHeadsDir = VcsUtil.getVirtualFile(myRepositoryFiles.getRefsHeadsPath()); myRemotesDir = VcsUtil.getVirtualFile(myRepositoryFiles.getRefsRemotesPath()); diff --git a/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java b/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java index 31d2aee06b2c..356ba991486b 100644 --- a/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java +++ b/plugins/git4idea/src/git4idea/repo/GitUntrackedFilesHolder.java @@ -89,14 +89,18 @@ public class GitUntrackedFilesHolder implements Disposable, BulkFileListener { private Set myPossiblyTrackedFiles = new HashSet(); private boolean myReady; // if false, total refresh is needed private final Object LOCK = new Object(); + private final GitRepositoryManager myRepositoryManager; - GitUntrackedFilesHolder(@NotNull VirtualFile root, @NotNull Project project) { - myProject = project; - myRoot = root; - myRepositoryFiles = GitRepositoryFiles.getInstance(root); - myChangeListManager = ChangeListManager.getInstance(project); - myDirtyScopeManager = VcsDirtyScopeManager.getInstance(project); + GitUntrackedFilesHolder(@NotNull GitRepository repository) { + myProject = repository.getProject(); + myRoot = repository.getRoot(); + myChangeListManager = ChangeListManager.getInstance(myProject); + myDirtyScopeManager = VcsDirtyScopeManager.getInstance(myProject); myGit = ServiceManager.getService(Git.class); + + myRepositoryManager = GitUtil.getRepositoryManager(myProject); + assert myRepositoryManager != null; + myRepositoryFiles = GitRepositoryFiles.getInstance(repository.getGitDir()); } void setupVfsListener(@NotNull Project project) { @@ -302,7 +306,7 @@ public class GitUntrackedFilesHolder implements Disposable, BulkFileListener { } private boolean belongsToThisRepository(VirtualFile file) { - final GitRepository repository = GitUtil.getRepositoryManager(myProject).getRepositoryForFile(file); + final GitRepository repository = myRepositoryManager.getRepositoryForFile(file); return repository != null && repository.getRoot().equals(myRoot); } diff --git a/plugins/git4idea/src/git4idea/roots/GitIntegrationEnabler.java b/plugins/git4idea/src/git4idea/roots/GitIntegrationEnabler.java index 0ac640759235..ae1765dc4aaa 100644 --- a/plugins/git4idea/src/git4idea/roots/GitIntegrationEnabler.java +++ b/plugins/git4idea/src/git4idea/roots/GitIntegrationEnabler.java @@ -21,7 +21,9 @@ import com.intellij.openapi.vcs.AbstractVcs; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.VcsDirectoryMapping; import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.ui.UIUtil; import git4idea.Notificator; import git4idea.PlatformFacade; import git4idea.commands.Git; @@ -74,9 +76,10 @@ public class GitIntegrationEnabler { notificator.notifySuccess("", String.format("Added Git %s: %s", pluralize("root", roots.size()), joinRootsPaths(roots))); } - private boolean gitInitOrNotifyError(@NotNull Notificator notificator, @NotNull VirtualFile projectDir) { + private boolean gitInitOrNotifyError(@NotNull Notificator notificator, @NotNull final VirtualFile projectDir) { try { myGit.init(myProject, projectDir); + refreshGitDir(projectDir); notificator.notifySuccess("", "Created Git repository in \n" + projectDir.getPresentableUrl()); return true; } @@ -87,6 +90,18 @@ public class GitIntegrationEnabler { } } + private void refreshGitDir(final VirtualFile projectDir) { + UIUtil.invokeAndWaitIfNeeded(new Runnable() { + @Override public void run() { + myPlatformFacade.runReadAction(new Runnable() { + @Override public void run() { + LocalFileSystem.getInstance().refreshAndFindFileByPath(projectDir.getPath() + "/.git"); + } + }); + } + }); + } + private void addVcsRoots(@NotNull Collection roots) { ProjectLevelVcsManager vcsManager = myPlatformFacade.getVcsManager(myProject); AbstractVcs vcs = myPlatformFacade.getVcs(myProject); diff --git a/plugins/git4idea/src/git4idea/roots/GitRootChecker.java b/plugins/git4idea/src/git4idea/roots/GitRootChecker.java index bfd046344ea4..ec5e97cf4efe 100644 --- a/plugins/git4idea/src/git4idea/roots/GitRootChecker.java +++ b/plugins/git4idea/src/git4idea/roots/GitRootChecker.java @@ -35,7 +35,7 @@ public class GitRootChecker implements VcsRootChecker { private final boolean myProjectMappingIsInvalid; public GitRootChecker(@NotNull Project project, @NotNull PlatformFacade platformFacade) { - myErrors = new GitRootErrorsFinder(project, platformFacade).find(new GitRootDetector(project, platformFacade).detect()); + myErrors = new GitRootErrorsFinder(project, platformFacade).find(); myProjectMappingIsInvalid = isProjectMappingInvalid(); } diff --git a/plugins/git4idea/src/git4idea/roots/GitRootErrorsFinder.java b/plugins/git4idea/src/git4idea/roots/GitRootErrorsFinder.java index 1ca0ffb9053d..8f03a93e0d0f 100644 --- a/plugins/git4idea/src/git4idea/roots/GitRootErrorsFinder.java +++ b/plugins/git4idea/src/git4idea/roots/GitRootErrorsFinder.java @@ -25,6 +25,7 @@ import git4idea.PlatformFacade; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -48,26 +49,22 @@ public class GitRootErrorsFinder { } @NotNull - public Collection find(@NotNull GitRootDetectInfo rootDetectInfo) { + public Collection find() { List mappings = myVcsManager.getDirectoryMappings(myVcs); - Collection gitRoots = rootDetectInfo.getRoots(); + Collection gitRoots = new GitRootDetector(myProject, myPlatformFacade).detect().getRoots(); Collection errors = new ArrayList(); - Collection gitPaths = rootsToPaths(gitRoots); - errors.addAll(findExtraMappings(mappings, gitPaths)); - errors.addAll(findUnregisteredRoots(mappings, gitPaths)); + errors.addAll(findExtraMappings(mappings, rootsToPaths(gitRoots))); + errors.addAll(findUnregisteredRoots(gitRoots)); return errors; } - private Collection findUnregisteredRoots(List mappings, Collection gitPaths) { + private Collection findUnregisteredRoots(Collection gitRoots) { Collection errors = new ArrayList(); - if (hasProjectMapping(myPlatformFacade.getVcsManager(myProject).getDirectoryMappings())) { - return errors; - } - List mappedPaths = mappingsToPaths(mappings); - for (String gitPath : gitPaths) { - if (!mappedPaths.contains(gitPath)) { - errors.add(new VcsRootError(VcsRootError.Type.UNREGISTERED_ROOT, gitPath)); + Collection vcsRoots = Arrays.asList(myVcsManager.getRootsUnderVcs(myVcs)); + for (VirtualFile gitRoot : gitRoots) { + if (!vcsRoots.contains(gitRoot)) { + errors.add(new VcsRootError(VcsRootError.Type.UNREGISTERED_ROOT, gitRoot.getPath())); } } return errors; @@ -100,23 +97,4 @@ public class GitRootErrorsFinder { return gitPaths; } - private static List mappingsToPaths(List mappings) { - List paths = new ArrayList(); - for (VcsDirectoryMapping mapping : mappings) { - if (!mapping.isDefaultMapping()) { - paths.add(mapping.systemIndependentPath()); - } - } - return paths; - } - - private static boolean hasProjectMapping(List mappings) { - for (VcsDirectoryMapping mapping : mappings) { - if (mapping.isDefaultMapping()) { - return true; - } - } - return false; - } - } diff --git a/plugins/git4idea/src/git4idea/roots/GitRootProblemNotifier.java b/plugins/git4idea/src/git4idea/roots/GitRootProblemNotifier.java index 13665681761e..9f2d4bb17de3 100644 --- a/plugins/git4idea/src/git4idea/roots/GitRootProblemNotifier.java +++ b/plugins/git4idea/src/git4idea/roots/GitRootProblemNotifier.java @@ -67,19 +67,17 @@ public class GitRootProblemNotifier { mySettings = VcsConfiguration.getInstance(myProject); } - public GitRootDetectInfo rescanAndNotifyIfNeeded() { - GitRootDetectInfo detectInfo = new GitRootDetector(myProject, myPlatformFacade).detect(); - + public void rescanAndNotifyIfNeeded() { if (!mySettings.SHOW_VCS_ERROR_NOTIFICATIONS) { - return detectInfo; + return; } - Collection errors = scan(detectInfo); + Collection errors = scan(); if (errors.isEmpty()) { synchronized (NOTIFICATION_LOCK) { expireNotification(); } - return detectInfo; + return; } Collection unregisteredRoots = getUnregisteredRoots(errors); @@ -91,10 +89,9 @@ public class GitRootProblemNotifier { synchronized (NOTIFICATION_LOCK) { expireNotification(); myNotification = createNotification(IMPORTANT_ERROR_NOTIFICATION, title, description, ERROR, - new MyNotificationListener(myProject, mySettings, myPlatformFacade)); + new MyNotificationListener(myProject, mySettings)); myPlatformFacade.getNotificator(myProject).notify(myNotification); } - return detectInfo; } private void expireNotification() { @@ -112,8 +109,8 @@ public class GitRootProblemNotifier { } @NotNull - private Collection scan(GitRootDetectInfo detectInfo) { - return new GitRootErrorsFinder(myProject, myPlatformFacade).find(detectInfo); + private Collection scan() { + return new GitRootErrorsFinder(myProject, myPlatformFacade).find(); } @SuppressWarnings("StringConcatenationInsideStringBufferAppend") @@ -198,12 +195,10 @@ public class GitRootProblemNotifier { @NotNull private final Project myProject; @NotNull private final VcsConfiguration mySettings; - @NotNull private final PlatformFacade myPlatformFacade; - private MyNotificationListener(@NotNull Project project, @NotNull VcsConfiguration settings, @NotNull PlatformFacade facade) { + private MyNotificationListener(@NotNull Project project, @NotNull VcsConfiguration settings) { myProject = project; mySettings = settings; - myPlatformFacade = facade; } @Override @@ -211,8 +206,7 @@ public class GitRootProblemNotifier { if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { if (event.getDescription().equals("configure")) { ShowSettingsUtil.getInstance().showSettingsDialog(myProject, ActionsBundle.message("group.VcsGroup.text")); - Collection errorsAfterPossibleFix = GitRootProblemNotifier.getInstance(myProject).scan( - new GitRootDetector(myProject, myPlatformFacade).detect()); + Collection errorsAfterPossibleFix = GitRootProblemNotifier.getInstance(myProject).scan(); if (errorsAfterPossibleFix.isEmpty() && !notification.isExpired()) { notification.expire(); } diff --git a/plugins/git4idea/src/git4idea/roots/GitRootScanner.java b/plugins/git4idea/src/git4idea/roots/GitRootScanner.java index 28846df88e02..9c0c37bdffca 100644 --- a/plugins/git4idea/src/git4idea/roots/GitRootScanner.java +++ b/plugins/git4idea/src/git4idea/roots/GitRootScanner.java @@ -30,7 +30,6 @@ import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.newvfs.BulkFileListener; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; import com.intellij.util.messages.MessageBus; -import git4idea.repo.GitRepositoryManager; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -41,7 +40,6 @@ import java.util.List; */ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Disposable, VcsListener { - @NotNull private final Project myProject; @NotNull private final Runnable myExecuteAfterScan; @NotNull private final GitRootProblemNotifier myRootProblemNotifier; @@ -51,7 +49,6 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Dis @NotNull private final Object SCAN_LOCK = new Object(); public GitRootScanner(@NotNull Project project, @NotNull Runnable executeAfterScan) { - myProject = project; myExecuteAfterScan = executeAfterScan; StartupManager.getInstance(project).runWhenProjectIsInitialized(new DumbAwareRunnable() { @@ -132,8 +129,7 @@ public class GitRootScanner implements BulkFileListener, ModuleRootListener, Dis return; } myScanning = true; - GitRootDetectInfo detectInfo = myRootProblemNotifier.rescanAndNotifyIfNeeded(); - myProject.getMessageBus().syncPublisher(GitRepositoryManager.GIT_ROOTS_CHANGE).gitRootsChanged(detectInfo.getRoots()); + myRootProblemNotifier.rescanAndNotifyIfNeeded(); myExecuteAfterScan.run(); myScanning = false; } diff --git a/plugins/git4idea/tests/git4idea/roots/GitRootErrorsFinderTest.groovy b/plugins/git4idea/tests/git4idea/roots/GitRootErrorsFinderTest.groovy index 74bffd57c458..f40b1a590cda 100644 --- a/plugins/git4idea/tests/git4idea/roots/GitRootErrorsFinderTest.groovy +++ b/plugins/git4idea/tests/git4idea/roots/GitRootErrorsFinderTest.groovy @@ -131,19 +131,20 @@ class GitRootErrorsFinderTest extends AbstractGitRootTest { } @Test - void "Project root, git below project folder not in a content root, then correct since folders are auto-detected"() { + void "Project root, git below project folder not in a content root, then unregistered root error"() { + // this is to be fixed: auto-detection of Git repositories in subfolders for the mapping doTest content_roots: ["."], git: ["community"], roots: [PROJECT], - errors: [] + errors: [unreg: ["community"]] } @Test - void "Project root, git for full project, content root, linked source, folder below project, then correct since folders are detected"() { + void "Project root, git for full project, content root, linked source, folder below project, then error in folder below"() { doTest content_roots: [".", "content_root", "../linked_source_root"], git: [".", "content_root", "../linked_source_root", "folder"], roots: [PROJECT], - errors: [] + errors: [unreg: ["folder"]] } @Test @@ -172,8 +173,7 @@ class GitRootErrorsFinderTest extends AbstractGitRootTest { expected.addAll map.errors.unreg.collect { unreg(it) } expected.addAll map.errors.extra.collect { extra(it) } - Collection actual = new GitRootErrorsFinder(myProject, myPlatformFacade).find( - new GitRootDetector(myProject, myPlatformFacade).detect()) + Collection actual = new GitRootErrorsFinder(myProject, myPlatformFacade).find() assertEquals expected.toSet(), actual.toSet() } diff --git a/plugins/git4idea/tests/git4idea/test/GitMockVcsManager.groovy b/plugins/git4idea/tests/git4idea/test/GitMockVcsManager.groovy index 779ba4173494..4486690c47f2 100644 --- a/plugins/git4idea/tests/git4idea/test/GitMockVcsManager.groovy +++ b/plugins/git4idea/tests/git4idea/test/GitMockVcsManager.groovy @@ -57,7 +57,6 @@ public class GitMockVcsManager extends ProjectLevelVcsManager { List roots = myRoots.collect { new GitMockVirtualFile(it) } roots.addAll(myPlatformFacade.getProjectRootManager(myProject).getContentRoots()) roots -// new GitRootConverter(myProject, myPlatformFacade).convertRoots(roots) } @Override diff --git a/plugins/git4idea/tests/git4idea/test/GitTestPlatformFacade.groovy b/plugins/git4idea/tests/git4idea/test/GitTestPlatformFacade.groovy index 5559051898ab..ca0467020269 100644 --- a/plugins/git4idea/tests/git4idea/test/GitTestPlatformFacade.groovy +++ b/plugins/git4idea/tests/git4idea/test/GitTestPlatformFacade.groovy @@ -77,6 +77,11 @@ public class GitTestPlatformFacade implements PlatformFacade { computable.compute() } + @Override + void runReadAction(Runnable runnable) { + runnable.run() + } + @NotNull @Override AbstractVcs getVcs(@NotNull Project project) { diff --git a/plugins/gradle/resources/i18n/GradleBundle.properties b/plugins/gradle/resources/i18n/GradleBundle.properties index 4993111dcfad..cec812d7e1d1 100644 --- a/plugins/gradle/resources/i18n/GradleBundle.properties +++ b/plugins/gradle/resources/i18n/GradleBundle.properties @@ -14,7 +14,7 @@ gradle.import.structure.tree.node.content.root=content-root gradle.import.structure.tree.node.libraries=libraries gradle.import.structure.settings.label.name=Name: gradle.import.structure.settings.label.language.level=Language level: -gradle.import.structure.settings.label.sdk=Sdk: +gradle.import.structure.settings.label.sdk=SDK: gradle.import.structure.settings.no.sdk.for.language.level.text= gradle.import.structure.settings.label.project.config.location=Project config location: gradle.import.structure.settings.title.project.config.location=Project config location diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml index a6919bcbbf21..b6a5ec5aa1e0 100644 --- a/plugins/gradle/src/META-INF/plugin.xml +++ b/plugins/gradle/src/META-INF/plugin.xml @@ -108,6 +108,7 @@ + diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java index 41c0725e5078..18d7dfe121b8 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java @@ -26,6 +26,7 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.config.GradleGroovyEnabler; import org.jetbrains.plugins.gradle.config.GradleSettings; import org.jetbrains.plugins.gradle.model.gradle.*; +import org.jetbrains.plugins.gradle.sync.GradleProjectStructureChangesModel; import org.jetbrains.plugins.gradle.task.GradleResolveProjectTask; import org.jetbrains.plugins.gradle.util.GradleBundle; import org.jetbrains.plugins.gradle.util.GradleLog; @@ -318,6 +319,21 @@ public class GradleModulesImporter { finally { writeLock.finish(); } + final GradleSettings settings = GradleSettings.getInstance(intellijProject); + final String gradleHome = settings.getGradleHome(); + if (gradleHome != null) { + final GradleGroovyEnabler groovyEnabler = intellijProject.getComponent(GradleGroovyEnabler.class); + libraryToPreserve.set(groovyEnabler.setupGroovySdkIfNecessary(gradleHome)); + } + + // Force refresh the infrastructure in order to apply newly introduce intellij project structure changes + final GradleProjectStructureChangesModel changesModel = intellijProject.getComponent(GradleProjectStructureChangesModel.class); + if (changesModel != null) { + final GradleProject project = changesModel.getGradleProject(); + if (project != null) { + changesModel.update(project); + } + } } }; @@ -337,21 +353,8 @@ public class GradleModulesImporter { }); } }; - - Runnable setupGroovyTask = new Runnable() { - @Override - public void run() { - final GradleSettings settings = GradleSettings.getInstance(intellijProject); - final String gradleHome = settings.getGradleHome(); - if (gradleHome != null) { - final GradleGroovyEnabler groovyEnabler = intellijProject.getComponent(GradleGroovyEnabler.class); - libraryToPreserve.set(groovyEnabler.setupGroovySdkIfNecessary(gradleHome)); - } - resolveDependenciesTask.run(); - } - }; - - UIUtil.invokeLaterIfNeeded(setupGroovyTask); + + UIUtil.invokeLaterIfNeeded(resolveDependenciesTask); } private static void doSetupLibraries(@NotNull Map moduleMappings, diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleProjectImportBuilder.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleProjectImportBuilder.java index fa12623f17ca..3c65acce4d9f 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleProjectImportBuilder.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleProjectImportBuilder.java @@ -23,6 +23,7 @@ import org.jetbrains.plugins.gradle.model.gradle.GradleModule; import org.jetbrains.plugins.gradle.model.gradle.GradleProject; import org.jetbrains.plugins.gradle.ui.GradleIcons; import org.jetbrains.plugins.gradle.util.GradleBundle; +import org.jetbrains.plugins.gradle.util.GradleConstants; import org.jetbrains.plugins.gradle.util.GradleUtil; import javax.swing.*; @@ -78,8 +79,8 @@ public class GradleProjectImportBuilder extends ProjectImportBuilder commit(final Project project, ModifiableModuleModel model, ModulesProvider modulesProvider, - ModifiableArtifactModel artifactModel) - { + ModifiableArtifactModel artifactModel) { + System.setProperty(GradleConstants.NEWLY_IMPORTED_PROJECT, Boolean.TRUE.toString()); final Runnable task = new Runnable() { @Override public void run() { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/adjust/GradleAdjustImportSettingsStep.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/adjust/GradleAdjustImportSettingsStep.java index 81e35d435fd7..51e53af5c892 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/adjust/GradleAdjustImportSettingsStep.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/adjust/GradleAdjustImportSettingsStep.java @@ -152,7 +152,11 @@ public class GradleAdjustImportSettingsStep extends AbstractImportFromGradleWiza public JComponent getComponent() { return myComponent; } - + @Override + public String getHelpId() { + return GradleConstants.HELP_TOPIC_ADJUST_SETTINGS_STEP; + } + @Override public void updateStep() { if (myOnValidateAttempt) { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/select/GradleSelectProjectStep.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/select/GradleSelectProjectStep.java index 36d1d71fd131..32f381b37993 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/select/GradleSelectProjectStep.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/wizard/select/GradleSelectProjectStep.java @@ -13,6 +13,7 @@ import org.jetbrains.plugins.gradle.config.GradleHomeSettingType; import org.jetbrains.plugins.gradle.importing.GradleProjectImportBuilder; import org.jetbrains.plugins.gradle.importing.wizard.AbstractImportFromGradleWizardStep; import org.jetbrains.plugins.gradle.util.GradleBundle; +import org.jetbrains.plugins.gradle.util.GradleConstants; import org.jetbrains.plugins.gradle.util.GradleUtil; import javax.swing.*; @@ -86,6 +87,11 @@ public class GradleSelectProjectStep extends AbstractImportFromGradleWizardStep public void updateDataModel() { } + @Override + public String getHelpId() { + return GradleConstants.HELP_TOPIC_IMPORT_SELECT_PROJECT_STEP; + } + @Override public boolean validate() throws ConfigurationException { if (myConfigurable.getCurrentGradleHomeSettingType() == GradleHomeSettingType.EXPLICIT_INCORRECT) { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleApiFacadeManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleApiFacadeManager.java index 3f884ccec8b2..9994b4c74bdf 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleApiFacadeManager.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/GradleApiFacadeManager.java @@ -236,7 +236,10 @@ public class GradleApiFacadeManager { GradleLog.LOG.warn("Detected unexpected duplicate tooling api facade instance creation"); return myFacade.get().first; } - result.applySettings(getRemoteSettings()); + if (!StringUtil.isEmpty(newPair.second.getJavaHome())) { + GradleLog.LOG.info("Instructing gradle to use java from " + newPair.second.getJavaHome()); + } + result.applySettings(newPair.second); RemoteGradleProgressNotificationManager exported = myExportedProgressManager.get(); if (exported == null) { try { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/RemoteGradleProcessSettings.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/RemoteGradleProcessSettings.java index 826988950428..3f67572335f3 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/RemoteGradleProcessSettings.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/RemoteGradleProcessSettings.java @@ -16,14 +16,18 @@ import java.io.Serializable; */ public class RemoteGradleProcessSettings implements Serializable { + private static final boolean USE_VERBOSE_GRADLE_API_BY_DEFAULT = Boolean.parseBoolean(System.getProperty("gradle.api.verbose")); + private static final long serialVersionUID = 1L; - private final String myGradleHome; - private long myTtlInMs; - private String myJavaHome; + private final String myGradleHome; + private long myTtlInMs; + private String myJavaHome; + private boolean myVerboseApi; public RemoteGradleProcessSettings(@NotNull String gradleHome) { myGradleHome = gradleHome; + setVerboseApi(USE_VERBOSE_GRADLE_API_BY_DEFAULT); } @NotNull @@ -51,6 +55,14 @@ public class RemoteGradleProcessSettings implements Serializable { myJavaHome = javaHome; } + public boolean isVerboseApi() { + return myVerboseApi; + } + + public void setVerboseApi(boolean verboseApi) { + myVerboseApi = verboseApi; + } + @Override public String toString() { return "home: " + myGradleHome; diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleProjectResolverImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleProjectResolverImpl.java index 8764ece4961f..898d65f2bb24 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleProjectResolverImpl.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/remote/impl/GradleProjectResolverImpl.java @@ -8,6 +8,7 @@ import com.intellij.util.PathUtil; import com.intellij.util.containers.ConcurrentHashSet; import com.intellij.util.containers.HashMap; import org.gradle.tooling.*; +import org.gradle.tooling.internal.consumer.DefaultGradleConnector; import org.gradle.tooling.model.DomainObjectSet; import org.gradle.tooling.model.idea.*; import org.jetbrains.annotations.NotNull; @@ -398,6 +399,9 @@ public class GradleProjectResolverImpl extends RemoteObject implements GradlePro RemoteGradleProcessSettings settings = mySettings.get(); if (settings != null) { connector.useInstallation(new File(settings.getGradleHome())); + if (settings.isVerboseApi() && connector instanceof DefaultGradleConnector) { + ((DefaultGradleConnector)connector).setVerboseLogging(true); + } } connector.forProjectDirectory(projectDir); ProjectConnection connection = connector.connect(); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleInitialProjectRefresher.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleInitialProjectRefresher.java index 7f0680d7b1f9..d1fd5d25b6b3 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleInitialProjectRefresher.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleInitialProjectRefresher.java @@ -3,6 +3,7 @@ package org.jetbrains.plugins.gradle.sync; import com.intellij.openapi.project.Project; import com.intellij.openapi.startup.StartupActivity; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.gradle.util.GradleConstants; import org.jetbrains.plugins.gradle.util.GradleUtil; /** @@ -14,8 +15,11 @@ import org.jetbrains.plugins.gradle.util.GradleUtil; * @since 3/13/12 12:01 PM */ public class GradleInitialProjectRefresher implements StartupActivity { + @SuppressWarnings("UseOfArchaicSystemPropertyAccessors") @Override public void runActivity(@NotNull Project project) { - GradleUtil.refreshProject(project); + if (!Boolean.getBoolean(GradleConstants.NEWLY_IMPORTED_PROJECT)) { + GradleUtil.refreshProject(project); + } } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java index 239e313cefd5..fbb2edcd5409 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java @@ -47,7 +47,7 @@ import java.util.List; */ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel { - private static final int TOOLTIP_DELAY_MILLIS = 500; + private static final int TOOLTIP_DELAY_MILLIS = 300; private static final int COLLAPSE_STATE_PROCESSING_DELAY_MILLIS = 200; private static final Comparator PATH_COMPARATOR = new Comparator() { @@ -59,7 +59,7 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel { private final Alarm myToolbarAppearanceAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); private final Alarm myToolbarTrackingAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); - private final Alarm myCollapseStateAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); + private final Alarm myCollapseStateAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); private final List myToolbarControls = new ArrayList(); /** Holds list of paths which 'expand/collapse' state should be restored. */ @@ -213,14 +213,14 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel { final @NotNull ActionToolbar toolbar, final @NotNull JComponent toolbarComponent) { - if (mySuppressToolbar || node == myNodeWithActiveToolbar) { + if (mySuppressToolbar || node == myNodeWithActiveToolbar || myTree.getSelectionCount() > 1) { return; } myToolbarAppearanceAlarm.cancelAllRequests(); myToolbarAppearanceAlarm.addRequest(new Runnable() { @Override public void run() { - if (myNodeUnderMouse != node) { + if (myNodeUnderMouse != node || myTree.getSelectionCount() > 1) { return; } final Point mouseLocation = MouseInfo.getPointerInfo().getLocation(); @@ -319,6 +319,9 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel { } return result; } + else if (PlatformDataKeys.HELP_ID.is(dataId)) { + return GradleConstants.HELP_TOPIC_TOOL_WINDOW; + } else { return super.getData(dataId); } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java index d43481149b38..6f976c121c77 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java @@ -12,6 +12,8 @@ import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNodeDescriptor; */ public class GradleConstants { + @NonNls public static final String NEWLY_IMPORTED_PROJECT = "gradle.newly.imported"; + @NonNls public static final String EXTENSION = "gradle"; @NonNls public static final String DEFAULT_SCRIPT_NAME = "build.gradle"; @@ -23,7 +25,10 @@ public class GradleConstants { @NonNls public static final String SYNC_TREE_FILTER_PLACE = "GRADLE_SYNC_TREE_FILTER_PLACE"; @NonNls public static final String ACTION_GROUP_SYNC_TREE = "Gradle.SyncTreeGroup"; - + + @NonNls public static final String HELP_TOPIC_IMPORT_SELECT_PROJECT_STEP = "reference.dialogs.new.project.import.gradle.page1"; + @NonNls public static final String HELP_TOPIC_ADJUST_SETTINGS_STEP = "reference.dialogs.new.project.import.gradle.page2"; + @NonNls public static final String HELP_TOPIC_TOOL_WINDOW = "reference.toolwindows.gradle"; public static final GradleProjectStructureNodeDescriptor DEPENDENCIES_NODE_DESCRIPTOR = GradleUtil.buildSyntheticDescriptor(GradleBundle.message("gradle.project.structure.tree.node.dependencies")); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenResumeAction.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenResumeAction.java index ec96119caa86..ef58e4603d20 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenResumeAction.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenResumeAction.java @@ -119,38 +119,32 @@ public class MavenResumeAction extends AnAction { String text = event.getText().trim(); if (text.isEmpty()) return; + String textWithoutInfo = ""; + if (text.startsWith("[INFO] ")) { + textWithoutInfo = text.substring("[INFO] ".length()).trim(); + } + switch (myState) { case STATE_INITIAL: // initial state. - if (text.equals("[INFO] Reactor build order:")) { + if (textWithoutInfo.equalsIgnoreCase("Reactor build order:")) { myState = STATE_READING_PROJECT_LIST; } break; case STATE_READING_PROJECT_LIST: - if (text.equals("[INFO] ------------------------------------------------------------------------")) { + if (textWithoutInfo.equals("------------------------------------------------------------------------")) { myState = STATE_WAIT_FOR_BUILD; } - else if (text.startsWith("[INFO] ")) { - String projectName = text.substring("[INFO] ".length()); - if (projectName.isEmpty()) { - myState = STATE_WTF; - log("Empty project name in \"Reactor build order\" section!!! other project names: " + myMavenProjectNames); - } - else { - myMavenProjectNames.add(projectName); - } - } - else { - myState = STATE_WTF; - log("\"Reactor build order\" doesn't end by \"-----\"!!! it's end by: " + text); + else if (textWithoutInfo.length() > 0) { + myMavenProjectNames.add(textWithoutInfo); } break; case STATE_WAIT_FOR_BUILD: - if (text.startsWith("[INFO] Building ")) { - String projectName = text.substring("[INFO] Building ".length()); + if (textWithoutInfo.startsWith("Building ")) { + String projectName = textWithoutInfo.substring("Building ".length()); if (myBuildingProjectIndex > myMavenProjectNames.size() || - !myMavenProjectNames.get(myBuildingProjectIndex).equals(projectName)) { + !projectName.startsWith(myMavenProjectNames.get(myBuildingProjectIndex))) { myState = STATE_WTF; log(String.format("Invalid project building order. Defined order: %s, error index: %d, invalid line: %s", myMavenProjectNames, myBuildingProjectIndex, text)); @@ -163,7 +157,7 @@ public class MavenResumeAction extends AnAction { break; case STATE_WAIT_FOR______: - if (text.equals("[INFO] ------------------------------------------------------------------------")) { + if (textWithoutInfo.equals("------------------------------------------------------------------------")) { myState = STATE_WAIT_FOR_BUILD; } break; @@ -216,6 +210,21 @@ public class MavenResumeAction extends AnAction { } } + if (candidate != null) { + return candidate; + } + + for (MavenProject mavenProject : projects) { + if (projectName.equals(mavenProject.getMavenId().getArtifactId())) { + if (candidate == null) { + candidate = mavenProject; + } + else { + return null; + } + } + } + return candidate; } diff --git a/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettings.java b/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettings.java index 9e470ac2022c..8f7b70d539ca 100644 --- a/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettings.java +++ b/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettings.java @@ -15,6 +15,7 @@ */ package com.intellij.ide.browsers.chrome; +import com.intellij.execution.configurations.ParametersList; import com.intellij.ide.browsers.BrowserSpecificSettings; import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.ArrayUtil; @@ -30,6 +31,7 @@ public class ChromeSettings extends BrowserSpecificSettings { @NonNls public static final String REMOTE_DEBUGGING_PORT_ARG = "--remote-debugging-port="; @NonNls public static final String USER_DATA_DIR_ARG = "--user-data-dir="; public static final int DEFAULT_REMOTE_SHELL_PORT = 7930; + private String myCommandLineOptions = ""; private String myUserDataDirectoryPath; private boolean myUseCustomProfile; private boolean myEnableRemoteDebug; @@ -59,6 +61,15 @@ public class ChromeSettings extends BrowserSpecificSettings { return myRemoteShellPort; } + @Tag("command-line-options") + public String getCommandLineOptions() { + return myCommandLineOptions; + } + + public void setCommandLineOptions(String commandLineOptions) { + myCommandLineOptions = commandLineOptions; + } + public void setEnableRemoteDebug(boolean enableRemoteDebug) { myEnableRemoteDebug = enableRemoteDebug; } @@ -94,7 +105,7 @@ public class ChromeSettings extends BrowserSpecificSettings { remoteShellArg = ArrayUtil.EMPTY_STRING_ARRAY; } - return ArrayUtil.mergeArrays(customProfileArg, remoteShellArg); + return ArrayUtil.mergeArrays(ParametersList.parse(myCommandLineOptions), ArrayUtil.mergeArrays(customProfileArg, remoteShellArg)); } @Override diff --git a/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.form b/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.form index 39b81024be5c..f3013409e001 100644 --- a/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.form +++ b/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.form @@ -1,6 +1,6 @@
- + @@ -10,7 +10,7 @@ - + @@ -18,12 +18,12 @@ - + - + @@ -31,7 +31,7 @@ - + @@ -39,12 +39,26 @@ - + + + + + + + + + + + + + + + diff --git a/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.java b/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.java index 59ed138ddf1d..42ceaeb47caf 100644 --- a/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.java +++ b/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.java @@ -21,6 +21,7 @@ import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.ui.RawCommandLineEditor; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -40,6 +41,8 @@ public class ChromeSettingsConfigurable implements Configurable { private TextFieldWithBrowseButton myUserDataDirField; private JCheckBox myEnableRemoteDebugCheckBox; private JTextField myPortField; + private JLabel myCommandLineOptionsLabel; + private RawCommandLineEditor myCommandLineOptionsEditor; private final String myDefaultUserDirPath; public ChromeSettingsConfigurable(@NotNull ChromeSettings settings) { @@ -59,6 +62,7 @@ public class ChromeSettingsConfigurable implements Configurable { myPortField.setEnabled(myEnableRemoteDebugCheckBox.isSelected()); } }); + myCommandLineOptionsLabel.setLabelFor(myCommandLineOptionsEditor.getTextField()); } @Override @@ -70,7 +74,8 @@ public class ChromeSettingsConfigurable implements Configurable { public boolean isModified() { if (myEnableRemoteDebugCheckBox.isSelected() != mySettings.isEnableRemoteDebug() || !myPortField.getText().equals(String.valueOf(mySettings.getRemoteShellPort())) - || myUseCustomProfileCheckBox.isSelected() != mySettings.isUseCustomProfile()) { + || myUseCustomProfileCheckBox.isSelected() != mySettings.isUseCustomProfile() + || !myCommandLineOptionsEditor.getText().equals(mySettings.getCommandLineOptions())) { return true; } @@ -93,6 +98,7 @@ public class ChromeSettingsConfigurable implements Configurable { catch (NumberFormatException ignored) { throw new ConfigurationException("Port is not integer!"); } + mySettings.setCommandLineOptions(myCommandLineOptionsEditor.getText()); mySettings.setUseCustomProfile(myUseCustomProfileCheckBox.isSelected()); mySettings.setUserDataDirectoryPath(getConfiguredUserDataDirPath()); mySettings.setEnableRemoteDebug(myEnableRemoteDebugCheckBox.isSelected()); @@ -104,6 +110,7 @@ public class ChromeSettingsConfigurable implements Configurable { myPortField.setText(String.valueOf(mySettings.getRemoteShellPort())); myPortField.setEnabled(mySettings.isEnableRemoteDebug()); + myCommandLineOptionsEditor.setText(mySettings.getCommandLineOptions()); myUseCustomProfileCheckBox.setSelected(mySettings.isUseCustomProfile()); myUserDataDirField.setEnabled(mySettings.isUseCustomProfile()); String path = mySettings.getUserDataDirectoryPath();