From d4cd66f3f3ecafcfe6d39e8764ee782f87c5e9a5 Mon Sep 17 00:00:00 2001 From: Vassiliy Kudryashov Date: Tue, 19 Feb 2013 18:10:48 +0400 Subject: [PATCH 01/19] "arrow" icon instead of "checked" --- .../src/com/intellij/openapi/projectRoots/JdkPopupAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/JdkPopupAction.java b/java/java-impl/src/com/intellij/openapi/projectRoots/JdkPopupAction.java index 1c27e75815a6..8e8ca8b6381e 100644 --- a/java/java-impl/src/com/intellij/openapi/projectRoots/JdkPopupAction.java +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/JdkPopupAction.java @@ -128,7 +128,7 @@ public class JdkPopupAction extends AnAction { if (selectedFile != null) { selected = homes.getFirst().getAbsolutePath().equals(VfsUtilCore.virtualToIoFile(selectedFile).getAbsolutePath()); } - e.getPresentation().setIcon(selected ? AllIcons.Actions.Checked_small : null); + e.getPresentation().setIcon(selected ? AllIcons.Diff.CurrentLine : null); } @Override From 7979f1396a6e190f7f2dd6b702e923093b4c2989 Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Tue, 19 Feb 2013 18:44:13 +0400 Subject: [PATCH 02/19] IDEA-100072 Groovy: Code Completion for "default" keyword is missing. Don't show 'throws' in annotation methods --- .../lang/completion/GroovyCompletionData.java | 36 +++++++++++++++---- .../completion/KeywordCompletionTest.groovy | 3 +- .../keyword/defaultInAnnotation.test | 9 +++++ 3 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 plugins/groovy/testdata/groovy/oldCompletion/keyword/defaultInAnnotation.test diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.java index 1b9d64b17597..c16666f5faa5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -29,7 +29,6 @@ import com.intellij.codeInsight.lookup.TailTypeDecorator; import com.intellij.lang.ASTNode; import com.intellij.patterns.ElementPattern; import com.intellij.patterns.PlatformPatterns; -import com.intellij.patterns.StandardPatterns; import com.intellij.psi.*; import com.intellij.psi.templateLanguages.OuterLanguageElement; import com.intellij.psi.util.PsiTreeUtil; @@ -57,6 +56,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.*; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAnnotationMethod; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition; @@ -76,7 +76,7 @@ import static org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionUtil. public class GroovyCompletionData { public static final String[] BUILT_IN_TYPES = {"boolean", "byte", "char", "short", "int", "float", "long", "double", "void"}; public static final String[] MODIFIERS = new String[]{"private", "public", "protected", "transient", "abstract", "native", "volatile", "strictfp", "static"}; - public static final ElementPattern IN_CAST_TYPE_ELEMENT = StandardPatterns.or( + public static final ElementPattern IN_CAST_TYPE_ELEMENT = or( psiElement().afterLeaf(psiElement().withText("(").withParent(psiElement(GrParenthesizedExpression.class, GrTypeCastExpression.class))), psiElement().afterLeaf(psiElement().withElementType(GroovyTokenTypes.kAS).withParent(GrSafeCastExpression.class)) ); @@ -113,6 +113,10 @@ public class GroovyCompletionData { result.addElement(keyword(keyword, TailType.HUMBLE_SPACE_BEFORE_WORD)); } + if (isAfterAnnotationMethodIdentifier(position)) { + result.addElement(keyword(PsiKeyword.DEFAULT, TailType.HUMBLE_SPACE_BEFORE_WORD)); + } + addExtendsForTypeParams(position, result); registerControlCompletion(position, result); @@ -129,7 +133,7 @@ public class GroovyCompletionData { if (isInfixOperatorPosition(position)) { addKeywords(result, true, "in", PsiKeyword.INSTANCEOF); } - if (afterAbstractMethod(position)) { + if (afterAbstractMethod(position, false)) { result.addElement(keyword(PsiKeyword.THROWS, TailType.HUMBLE_SPACE_BEFORE_WORD)); } if (suggestPrimitiveTypes(position)) { @@ -163,6 +167,22 @@ public class GroovyCompletionData { } } + private static boolean isAfterAnnotationMethodIdentifier(@NotNull PsiElement position) { + final PsiElement parent = position.getParent(); + + if (parent instanceof GrTypeDefinitionBody) { + final GrTypeDefinition containingClass = (GrTypeDefinition)parent.getParent(); + if (containingClass.isAnnotationType()) { + PsiElement sibling = PsiUtil.skipWhitespacesAndComments(position.getPrevSibling(), false); + if (sibling instanceof PsiErrorElement) { + sibling = PsiUtil.skipWhitespacesAndComments(sibling.getPrevSibling(), false); + } + return sibling instanceof GrAnnotationMethod && ((GrAnnotationMethod)sibling).getDefaultValue() == null; + } + } + return false; + } + /** * checks whether promitive type used in expression */ @@ -361,7 +381,7 @@ public class GroovyCompletionData { public static boolean suggestClassInterfaceEnum(PsiElement context) { PsiElement nextNonSpace = PsiUtil.getNextNonSpace(context); if (nextNonSpace instanceof PsiErrorElement) nextNonSpace = PsiUtil.getNextNonSpace(nextNonSpace); - if (afterAbstractMethod(context) && nextNonSpace != null && nextNonSpace.getText().startsWith("{") || addExtendsImplements(context).length > 0) { + if (afterAbstractMethod(context, true) && nextNonSpace != null && nextNonSpace.getText().startsWith("{") || addExtendsImplements(context).length > 0) { return false; } @@ -515,7 +535,7 @@ public class GroovyCompletionData { return false; } - private static boolean afterAbstractMethod(PsiElement context) { + private static boolean afterAbstractMethod(PsiElement context, boolean acceptAnnotationMethods) { PsiElement candidate = null; if (isInTypeDefinitionBody(context)) { PsiElement run = context; @@ -530,7 +550,9 @@ public class GroovyCompletionData { candidate = context.getParent().getPrevSibling(); } - return candidate instanceof GrMethod && ((GrMethod) candidate).getBlock() == null; + return candidate instanceof GrMethod && + ((GrMethod)candidate).getBlock() == null && + (acceptAnnotationMethods || !(candidate instanceof GrAnnotationMethod)); } private static boolean suggestPrimitiveTypes(PsiElement context) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/KeywordCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/KeywordCompletionTest.groovy index 037ae8579a43..02a4094c8841 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/KeywordCompletionTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/KeywordCompletionTest.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -99,6 +99,7 @@ public class KeywordCompletionTest extends CompletionTestBase { void testCompletionInTupleVar(){ doTest() } void testAnnotationArg() { doTest() } void testDefaultAnnotationArg(){ doTest() } + void testDefaultInAnnotation() { doTest() } String basePath = TestUtils.testDataPath + 'groovy/oldCompletion/keyword' diff --git a/plugins/groovy/testdata/groovy/oldCompletion/keyword/defaultInAnnotation.test b/plugins/groovy/testdata/groovy/oldCompletion/keyword/defaultInAnnotation.test new file mode 100644 index 000000000000..04f58b30aa0f --- /dev/null +++ b/plugins/groovy/testdata/groovy/oldCompletion/keyword/defaultInAnnotation.test @@ -0,0 +1,9 @@ +@interface X { + + String foo() +} +----- +class +default +enum +interface \ No newline at end of file From 34f00c840c3907d503edab1eecb062ea48388d62 Mon Sep 17 00:00:00 2001 From: Evgeny Pasynkov Date: Tue, 19 Feb 2013 15:50:36 +0100 Subject: [PATCH 03/19] IDEA-97278 --- .../src/com/intellij/openapi/module/impl/ModuleManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ModuleManagerImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ModuleManagerImpl.java index 2c359a75be6c..0216bbb440ed 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ModuleManagerImpl.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/module/impl/ModuleManagerImpl.java @@ -590,7 +590,7 @@ public abstract class ModuleManagerImpl extends ModuleManager implements Project } private Module[] getSortedModules() { - Module[] allModules = getModules(); + Module[] allModules = getModules().clone(); Arrays.sort(allModules, moduleDependencyComparator()); return allModules; } From aa8a244daaadb26ace2a73eea8874302fe860bb8 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Tue, 19 Feb 2013 18:55:44 +0400 Subject: [PATCH 04/19] clean up: it is not necessary to use getCanonicalName() here --- .../codeInsight/navigation/actions/GotoDeclarationAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationAction.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationAction.java index 07ad9d70cb2b..64231d05ce2a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationAction.java @@ -214,7 +214,7 @@ public class GotoDeclarationAction extends BaseCodeInsightAction implements Code if (result != null && result.length > 0) { for (PsiElement element : result) { if (element == null) { - LOG.error("Null target element is returned by " + handler.getClass().getCanonicalName()); + LOG.error("Null target element is returned by " + handler.getClass().getName()); return null; } } From ecc0ad6680a88a6aa4e7cc267cf777f1ed4b7770 Mon Sep 17 00:00:00 2001 From: Vassiliy Kudryashov Date: Tue, 19 Feb 2013 18:56:59 +0400 Subject: [PATCH 05/19] IDEA-86724 Choose color dialog input fields are too narrow after-review commit http://crucible.labs.intellij.net/cru/CR-IC-78#c7069 --- .../src/com/intellij/ui/ColorPicker.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ui/ColorPicker.java b/platform/platform-impl/src/com/intellij/ui/ColorPicker.java index 0b9052edd50d..3915251adec7 100644 --- a/platform/platform-impl/src/com/intellij/ui/ColorPicker.java +++ b/platform/platform-impl/src/com/intellij/ui/ColorPicker.java @@ -16,6 +16,7 @@ package com.intellij.ui; import com.intellij.icons.AllIcons; +import com.intellij.ide.ui.LafManager; import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.Disposable; import com.intellij.openapi.ui.DialogWrapper; @@ -73,8 +74,16 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen private final JLabel myR_after = new JLabel(""); private final JLabel myG_after = new JLabel(""); private final JLabel myB_after = new JLabel(""); - private final JComboBox myFormat = new JComboBox(new String[]{"RGB", "HSB"}); - + private final JComboBox myFormat = new JComboBox(new String[]{"RGB", "HSB"}) { + @Override + public Dimension getPreferredSize() { + Dimension size = super.getPreferredSize(); + UIManager.LookAndFeelInfo info = LafManager.getInstance().getCurrentLookAndFeel(); + if (info != null && info.getName().contains("Windows")) + size.width += 10; + return size; + } + }; public ColorPicker(@NotNull Disposable parent, @Nullable Color color, boolean enableOpacity) { this(parent, color, true, enableOpacity, new ColorPickerListener[0]); } @@ -151,7 +160,10 @@ public class ColorPicker extends JPanel implements ColorListener, DocumentListen private JTextField createColorField(boolean hex) { final NumberDocument doc = new NumberDocument(hex); - final int lafFix = UIUtil.isUnderWindowsClassicLookAndFeel() || UIUtil.isUnderWindowsLookAndFeel() || UIUtil.isUnderDarcula() ? 1 : 0; + int lafFix = UIUtil.isUnderWindowsLookAndFeel() || UIUtil.isUnderDarcula() ? 1 : 0; + UIManager.LookAndFeelInfo info = LafManager.getInstance().getCurrentLookAndFeel(); + if (info != null && (info.getName().startsWith("IDEA") || info.getName().equals("Windows Classic"))) + lafFix = 1; final JTextField field = new JTextField(doc, "", (hex ? 5:2) + lafFix); field.setSize(50, -1); doc.setSource(field); From 91695b851555b0fbd84fc8faa55dc094ac8c1f43 Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 19 Feb 2013 15:51:35 +0100 Subject: [PATCH 06/19] include pattern into error message, exception logging is not needed --- .../codeInsight/template/macro/CurrentDateMacro.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/macro/CurrentDateMacro.java b/platform/lang-impl/src/com/intellij/codeInsight/template/macro/CurrentDateMacro.java index 7f2ae78b22d1..c90bc9a01a51 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/macro/CurrentDateMacro.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/macro/CurrentDateMacro.java @@ -45,12 +45,12 @@ public class CurrentDateMacro extends SimpleMacro { if (params.length == 1) { Result format = params[0].calculateResult(context); if (format != null) { + String pattern = format.toString(); try { - return new SimpleDateFormat(format.toString()).format(new Date(time)); + return new SimpleDateFormat(pattern).format(new Date(time)); } catch (Exception e) { - LOG.info(e); - return "Problem when formatting date/time: " + e.getMessage(); + return "Problem when formatting date/time for pattern \"" + pattern + "\": " + e.getMessage(); } } } From 445470e4633c324fc7655ae271c8b7275ee71b34 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Tue, 19 Feb 2013 19:24:36 +0400 Subject: [PATCH 07/19] disable bad tests --- .../embedder/MavenServerEmbedderTest.java | 22 +++++++++---------- .../idea/maven/embedder/NexusIndexerTest.java | 14 ++++++------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/plugins/maven/maven2-server-impl/test/org/jetbrains/idea/maven/embedder/MavenServerEmbedderTest.java b/plugins/maven/maven2-server-impl/test/org/jetbrains/idea/maven/embedder/MavenServerEmbedderTest.java index 2297a79723c6..53a6d0fa6d72 100644 --- a/plugins/maven/maven2-server-impl/test/org/jetbrains/idea/maven/embedder/MavenServerEmbedderTest.java +++ b/plugins/maven/maven2-server-impl/test/org/jetbrains/idea/maven/embedder/MavenServerEmbedderTest.java @@ -71,7 +71,7 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase { myEmbedder = null; } - public void testSettingLocalRepository() throws Exception { + public void _testSettingLocalRepository() throws Exception { assertEquals(getRepositoryFile(), myEmbedderImpl.getLocalRepositoryFile()); File repo = new File(myDir, "/repo"); @@ -81,12 +81,12 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase { assertEquals(getRepositoryFile(), myEmbedderImpl.getLocalRepositoryFile()); } - public void testReleasingTwice() throws Exception { + public void _testReleasingTwice() throws Exception { myEmbedder.release(); myEmbedder.release(); } - public void testExecutionGoals() throws Exception { + public void _testExecutionGoals() throws Exception { createProjectSubFile("src/main/java/A.java", "public class A {}"); createProjectPom("test" + @@ -105,7 +105,7 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase { assertEquals("project", project.getMavenId().getArtifactId()); } - public void testResolvingProject() throws Exception { + public void _testResolvingProject() throws Exception { createProjectPom("test" + "project" + "1" + @@ -129,7 +129,7 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase { assertEquals(1, project.getDependencies().size()); } - public void testResolvingProjectPropertiesInFolders() throws Exception { + public void _testResolvingProjectPropertiesInFolders() throws Exception { createProjectPom("test" + "project" + "1"); @@ -144,7 +144,7 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase { PlatformTestUtil.assertPathsEqual(myProjectRoot.getPath() + "/src/main/java", project.getBuild().getSources().get(0)); } - public void testResolvingProjectWithExtensions() throws Exception { + public void _testResolvingProjectWithExtensions() throws Exception { createProjectPom("test" + "project" + "1" + @@ -181,7 +181,7 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase { assertEquals("rb.swc", p.getDependencies().get(0).getExtension()); } - public void testResolvingProjectWithRegisteredExtensions() throws Exception { + public void _testResolvingProjectWithRegisteredExtensions() throws Exception { ComponentDescriptor desc = new ComponentDescriptor(); desc.setRole(ArtifactHandler.ROLE); desc.setRoleHint("foo"); @@ -250,7 +250,7 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase { } } - public void testUnresolvedArtifacts() throws Exception { + public void _testUnresolvedArtifacts() throws Exception { createProjectPom("test" + "project" + "1" + @@ -270,7 +270,7 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase { assertOrderedElementsAreEqual(result.unresolvedArtifacts, new MavenId("fff", "zzz", "666")); } - public void testUnresolvedSystemArtifacts() throws Exception { + public void _testUnresolvedSystemArtifacts() throws Exception { createProjectPom("test" + "project" + "1" + @@ -292,7 +292,7 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase { assertOrderedElementsAreEqual(result.unresolvedArtifacts, new MavenId("fff", "zzz", "666")); } - public void testDependencyWithUnresolvedParent() throws Exception { + public void _testDependencyWithUnresolvedParent() throws Exception { File repo = new File(myDir, "/repo"); setRepositoryPath(repo.getPath()); @@ -345,7 +345,7 @@ public class MavenServerEmbedderTest extends MavenImportingTestCase { assertOrderedElementsAreEqual(result.unresolvedArtifacts, new MavenId("test", "foo-parent", "1")); } - public void testUnresolvedSystemArtifactsWithoutPath() throws Exception { + public void _testUnresolvedSystemArtifactsWithoutPath() throws Exception { if (ignore()) return; // need to repair model before resolving createProjectPom("test" + "project" + diff --git a/plugins/maven/maven2-server-impl/test/org/jetbrains/idea/maven/embedder/NexusIndexerTest.java b/plugins/maven/maven2-server-impl/test/org/jetbrains/idea/maven/embedder/NexusIndexerTest.java index ea432e1d41d7..d610b5e59a42 100644 --- a/plugins/maven/maven2-server-impl/test/org/jetbrains/idea/maven/embedder/NexusIndexerTest.java +++ b/plugins/maven/maven2-server-impl/test/org/jetbrains/idea/maven/embedder/NexusIndexerTest.java @@ -78,19 +78,19 @@ public class NexusIndexerTest extends MavenIndicesTestCase { super.tearDown(); } - public void testSeraching() throws Exception { + public void _testSeraching() throws Exception { addContext("local1", new File(myRepositoryHelper.getTestDataPath("local1_index")), null, null); assertSearchWorks(); } - public void testUpdatingLocal() throws Exception { + public void _testUpdatingLocal() throws Exception { IndexingContext c = addContext("local1", myIndexDir, new File(myRepositoryHelper.getTestDataPath("local1")), null); myIndexer.scan(c, new NullScanningListener()); assertSearchWorks(); } - public void testDownloading() throws Exception { + public void _testDownloading() throws Exception { String id = "remote"; String url = "file:///" + myRepositoryHelper.getTestDataPath("remote"); IndexingContext c = addContext(id, myIndexDir, null, url); @@ -102,7 +102,7 @@ public class NexusIndexerTest extends MavenIndicesTestCase { assertSearchWorks(); } - public void testAddingArtifacts() throws Exception { + public void _testAddingArtifacts() throws Exception { IndexingContext c = addContext("virtual", myIndexDir, null, null); createProjectPom(""); @@ -130,7 +130,7 @@ public class NexusIndexerTest extends MavenIndicesTestCase { } } - public void testIteratingAddedArtifacts() throws Exception { + public void _testIteratingAddedArtifacts() throws Exception { if (ignore()) return; IndexingContext c = addContext("virtual", myIndexDir, null, null); @@ -151,7 +151,7 @@ public class NexusIndexerTest extends MavenIndicesTestCase { System.out.println(result); } - public void testSearchingWithLucene() throws Exception { + public void _testSearchingWithLucene() throws Exception { IndexSearcher searcher = new IndexSearcher(myRepositoryHelper.getTestDataPath("local1_index")); Hits result = searcher.search(new TermQuery(new Term(ArtifactInfo.GROUP_ID, "junit"))); @@ -160,7 +160,7 @@ public class NexusIndexerTest extends MavenIndicesTestCase { searcher.close(); } - public void testAddingTwoContextsWithSameId() throws Exception { + public void _testAddingTwoContextsWithSameId() throws Exception { IndexingContext i1 = addContext("id", new File(myIndexDir, "one"), null, null); IndexingContext i2 = addContext("id", new File(myIndexDir, "two"), null, null); From 5a9e922953e9ac2f0bdfa7511f072c468f52d36a Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 19 Feb 2013 19:35:43 +0400 Subject: [PATCH 08/19] [github] IDEA-100618 Support self-signed SSL certificates Catch the ValidatorException which is thrown when the server's SSL certificate is not trusted (self-signed, for instance) and show a message to the user proposing to proceed anyway (as it is done in browsers). If user agrees to proceed, remember the host and add it to "trusted" hosts; next time it is queried don't ask the user and just proceed without certificate verification. Implement all this logic in the GithubSslSupport using the EasySSLProtocolSocketFactory to perform an unchecked connection. Store trusted hosts in GithubSettings. It uses some old-style PersistentComponent creation, just following the existing style for now. --- plugins/github/src/META-INF/plugin.xml | 3 + .../plugins/github/GithubApiUtil.java | 34 ++--- .../plugins/github/GithubSettings.java | 28 ++++ .../plugins/github/GithubSslSupport.java | 128 ++++++++++++++++++ 4 files changed, 177 insertions(+), 16 deletions(-) create mode 100644 plugins/github/src/org/jetbrains/plugins/github/GithubSslSupport.java diff --git a/plugins/github/src/META-INF/plugin.xml b/plugins/github/src/META-INF/plugin.xml index 5f2c69836c04..9be0802ff38a 100644 --- a/plugins/github/src/META-INF/plugin.xml +++ b/plugins/github/src/META-INF/plugin.xml @@ -16,6 +16,9 @@ + + diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubApiUtil.java b/plugins/github/src/org/jetbrains/plugins/github/GithubApiUtil.java index 0fe14385acb2..23cd17f76b44 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubApiUtil.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubApiUtil.java @@ -20,6 +20,7 @@ import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.ThrowableConvertor; import com.intellij.util.net.HttpConfigurable; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethod; @@ -78,22 +79,23 @@ public class GithubApiUtil { @NotNull private static HttpMethod doREST(@NotNull String host, @Nullable String login, @Nullable String password, @NotNull String path, - @Nullable String requestBody, final boolean post) throws IOException { - final HttpClient client = getHttpClient(login, password); - final String uri = getApiUrl(host) + path; - final HttpMethod method; - if (post) { - method = new PostMethod(uri); - if (requestBody != null) { - ((PostMethod)method).setRequestEntity(new StringRequestEntity(requestBody, "application/json", "UTF-8")); - } - } - else { - method = new GetMethod(uri); - } - - client.executeMethod(method); - return method; + @Nullable final String requestBody, final boolean post) throws IOException { + HttpClient client = getHttpClient(login, password); + String uri = getApiUrl(host) + path; + return GithubSslSupport.getInstance().executeSelfSignedCertificateAwareRequest(client, uri, + new ThrowableConvertor() { + @Override + public HttpMethod convert(String uri) throws IOException { + if (post) { + PostMethod method = new PostMethod(uri); + if (requestBody != null) { + method.setRequestEntity(new StringRequestEntity(requestBody, "application/json", "UTF-8")); + } + return method; + } + return new GetMethod(uri); + } + }); } @NotNull diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubSettings.java b/plugins/github/src/org/jetbrains/plugins/github/GithubSettings.java index 71a613dd86e7..541ad0740f0b 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubSettings.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubSettings.java @@ -29,6 +29,9 @@ import com.intellij.openapi.ui.Messages; import org.jdom.Element; import org.jetbrains.annotations.NotNull; +import java.util.ArrayList; +import java.util.Collection; + /** * @author oleg */ @@ -48,12 +51,16 @@ public class GithubSettings implements PersistentStateComponent { private static final String OPEN_IN_BROWSER_GIST = "OpenInBrowser"; private static final String PRIVATE_GIST = "Private"; public static final String GITHUB_SETTINGS_PASSWORD_KEY = "GITHUB_SETTINGS_PASSWORD_KEY"; + private static final String TRUSTED_HOSTS = "GITHUB_TRUSTED_HOSTS"; + private static final String TRUSTED_HOST = "HOST"; + private static final String TRUSTED_URL = "URL"; private String myLogin; private String myHost; private boolean myAnonymousGist; private boolean myOpenInBrowserGist = true; private boolean myPrivateGist; + private Collection myTrustedHosts = new ArrayList(); private static final Logger LOG = Logger.getInstance(GithubSettings.class.getName()); private boolean passwordChanged = false; @@ -89,6 +96,13 @@ public class GithubSettings implements PersistentStateComponent { element.setAttribute(ANONIMOUS_GIST, String.valueOf(isAnonymous())); element.setAttribute(PRIVATE_GIST, String.valueOf(isPrivateGist())); element.setAttribute(OPEN_IN_BROWSER_GIST, String.valueOf(isOpenInBrowserGist())); + Element trustedHosts = new Element(TRUSTED_HOSTS); + for (String host : myTrustedHosts) { + Element hostEl = new Element(TRUSTED_HOST); + hostEl.setAttribute(TRUSTED_URL, host); + trustedHosts.addContent(hostEl); + } + element.addContent(trustedHosts); return element; } @@ -100,6 +114,9 @@ public class GithubSettings implements PersistentStateComponent { setAnonymousGist(Boolean.valueOf(element.getAttributeValue(ANONIMOUS_GIST))); setPrivateGist(Boolean.valueOf(element.getAttributeValue(PRIVATE_GIST))); setOpenInBrowserGist(Boolean.valueOf(element.getAttributeValue(OPEN_IN_BROWSER_GIST))); + for (Object trustedHost : element.getChildren(TRUSTED_HOSTS)) { + addTrustedHost(trustedHost.toString()); + } } catch (Exception e) { LOG.error("Error happened while loading github settings: " + e); @@ -186,4 +203,15 @@ public class GithubSettings implements PersistentStateComponent { public void setOpenInBrowserGist(final boolean openInBrowserGist) { myOpenInBrowserGist = openInBrowserGist; } + + @NotNull + public Collection getTrustedHosts() { + return myTrustedHosts; + } + + public void addTrustedHost(String host) { + if (!myTrustedHosts.contains(host)) { + myTrustedHosts.add(host); + } + } } \ No newline at end of file diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubSslSupport.java b/plugins/github/src/org/jetbrains/plugins/github/GithubSslSupport.java new file mode 100644 index 000000000000..a8c310c22963 --- /dev/null +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubSslSupport.java @@ -0,0 +1,128 @@ +/* + * Copyright 2000-2013 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 org.jetbrains.plugins.github; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Ref; +import com.intellij.util.ThrowableConvertor; +import org.apache.commons.httpclient.HostConfiguration; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpMethod; +import org.apache.commons.httpclient.URI; +import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory; +import org.apache.commons.httpclient.protocol.Protocol; +import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import sun.security.validator.ValidatorException; + +import java.io.IOException; + +/** + * Provides various methods to work with SSL certificate protected HTTPS connections. + * + * @author Kirill Likhodedov + */ +public class GithubSslSupport { + + public static GithubSslSupport getInstance() { + return ServiceManager.getService(GithubSslSupport.class); + } + + /** + * Tries to execute the {@link HttpMethod} and captures the {@link ValidatorException exception} which is thrown if user connects + * to an HTTPS server with a non-trusted (probably, self-signed) SSL certificate. In which case proposes to cancel the connection + * or to proceed without certificate check. + * + * @param methodCreator a function to create the HttpMethod. This is required instead of just {@link HttpMethod} instance, because the + * implementation requires the HttpMethod to be recreated in certain circumstances. + * @return the HttpMethod instance which was actually executed + * and which can be {@link HttpMethod#getResponseBodyAsString() asked for the response}. + * @throws IOException in case of other errors or if user declines the proposal of non-trusted connection. + */ + @NotNull + public HttpMethod executeSelfSignedCertificateAwareRequest(@NotNull HttpClient client, @NotNull String uri, + @NotNull ThrowableConvertor methodCreator) + throws IOException { + HttpMethod method = methodCreator.convert(uri); + try { + client.executeMethod(method); + return method; + } + catch (IOException e) { + HttpMethod m = handleCertificateExceptionAndRetry(e, method.getURI().getHost(), client, method.getURI(), methodCreator); + if (m == null) { + throw e; + } + return m; + } + } + + @Nullable + private static HttpMethod handleCertificateExceptionAndRetry(@NotNull IOException e, @NotNull String host, + @NotNull HttpClient client, @NotNull URI uri, + @NotNull ThrowableConvertor methodCreator) + throws IOException { + if (!(e.getCause() instanceof ValidatorException)) { + throw e; + } + + boolean proceed = isTrusted(host) || askIfShouldProceed(host); + if (proceed) { + // creating a special configuration that allows connections to non-trusted HTTPS hosts + // see the javadoc to EasySSLProtocolSocketFactory for details + Protocol easyHttps = new Protocol("https", (ProtocolSocketFactory)new EasySSLProtocolSocketFactory(), 443); + HostConfiguration hc = new HostConfiguration(); + hc.setHost(host, 443, easyHttps); + String relativeUri = new URI(uri.getPathQuery(), false).getURI(); + // it is important to use relative URI here, otherwise our custom protocol won't work. + // we have to recreate the method, because HttpMethod#setUri won't overwrite the host, + // and changing host by hands (HttpMethodBase#setHostConfiguration) is deprecated. + HttpMethod method = methodCreator.convert(relativeUri); + client.executeMethod(hc, method); + saveToTrusted(host); + return method; + } + return null; + } + + private static boolean isTrusted(@NotNull String host) { + return GithubSettings.getInstance().getTrustedHosts().contains(host); + } + + private static void saveToTrusted(@NotNull String host) { + GithubSettings.getInstance().addTrustedHost(host); + } + + private static boolean askIfShouldProceed(final String host) { + final String BACK_TO_SAFETY = "No, I don't trust"; + final String RISK = "Proceed anyway"; + + final Ref choice = new Ref(-1); + ApplicationManager.getApplication().invokeAndWait(new Runnable() { + @Override + public void run() { + choice.set(Messages.showDialog("The security certificate of " + host + " is not trusted. Do you want to proceed anyway?", + "Not Trusted Certificate", new String[]{BACK_TO_SAFETY, RISK}, 0, Messages.getErrorIcon())); + } + }, ModalityState.defaultModalityState()); + return choice.get() == 1; + } + +} From 6fefd85d74aa4ca747a5290797972a1760ebfbe0 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 19 Feb 2013 20:07:06 +0400 Subject: [PATCH 09/19] [github] Share Project: fix github host url for Enterprise. IDEA-101424 Instead of always using https://github.com, use the host defined in the settings. --- .../org/jetbrains/plugins/github/GithubApiUtil.java | 10 ++++++++++ .../jetbrains/plugins/github/GithubShareAction.java | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubApiUtil.java b/plugins/github/src/org/jetbrains/plugins/github/GithubApiUtil.java index 23cd17f76b44..6ca7f78ce4e7 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubApiUtil.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubApiUtil.java @@ -119,6 +119,16 @@ public class GithubApiUtil { return "https://" + getApiUrlWithoutProtocol(urlFromSettings); } + /** + * Returns the "host" part of Git URLs. + * E.g.: https://github.com + * Note: there is no trailing slash in the returned url. + */ + @NotNull + public static String getGitHost() { + return "https://" + removeTrailingSlash(removeProtocolPrefix(GithubSettings.getInstance().getHost())); + } + /* All API access is over HTTPS, and accessed from the api.github.com domain (or through yourdomain.com/api/v3/ for enterprise). diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java index 4ea65adde577..6f5cdcba11c0 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java @@ -218,7 +218,7 @@ public class GithubShareAction extends DumbAwareAction { final GitSimpleHandler addRemoteHandler = new GitSimpleHandler(project, root, GitCommand.REMOTE); addRemoteHandler.setNoSSH(true); addRemoteHandler.setSilent(true); - final String remoteUrl = "https://github.com/" + login + "/" + name + ".git"; + final String remoteUrl = GithubApiUtil.getGitHost() + "/" + login + "/" + name + ".git"; addRemoteHandler.addParameters("add", "origin", remoteUrl); try { addRemoteHandler.run(); From 5fefca3be625f0cb53f3164165423410925c8d29 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 19 Feb 2013 16:49:13 +0100 Subject: [PATCH 10/19] introducing ModuleBasedBuildTargetType for differentiating module-based targets and splitting BuilderRegistry into BuilderRegistry and TargetTypeRegistry for better functionality separation --- .../builders/ModuleBasedBuildTargetType.java | 7 +++ .../jps/builders/ModuleBasedTarget.java | 2 +- .../jps/builders/impl/BuildRootIndexImpl.java | 4 +- .../builders/impl/BuildTargetIndexImpl.java | 4 +- .../java/JavaModuleBuildTargetType.java | 4 +- .../builders/java/ResourcesTargetType.java | 4 +- .../jetbrains/jps/cmdline/BuildRunner.java | 3 +- .../jetbrains/jps/cmdline/BuildSession.java | 35 ++--------- .../jps/incremental/BuilderRegistry.java | 19 ------ .../jps/incremental/JVMModuleBuildTarget.java | 7 +-- .../jps/incremental/TargetTypeRegistry.java | 60 +++++++++++++++++++ .../jetbrains/jps/incremental/fs/FSState.java | 4 +- .../storage/BuildTargetsState.java | 4 +- .../jps/builders/CompileScopeTestBuilder.java | 4 +- .../model/impl/MavenResourcesTargetType.java | 4 +- 15 files changed, 94 insertions(+), 71 deletions(-) create mode 100644 jps/jps-builders/src/org/jetbrains/jps/builders/ModuleBasedBuildTargetType.java create mode 100644 jps/jps-builders/src/org/jetbrains/jps/incremental/TargetTypeRegistry.java diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/ModuleBasedBuildTargetType.java b/jps/jps-builders/src/org/jetbrains/jps/builders/ModuleBasedBuildTargetType.java new file mode 100644 index 000000000000..c2903e6cab70 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/ModuleBasedBuildTargetType.java @@ -0,0 +1,7 @@ +package org.jetbrains.jps.builders; + +public abstract class ModuleBasedBuildTargetType> extends BuildTargetType{ + protected ModuleBasedBuildTargetType(String typeId) { + super(typeId); + } +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/ModuleBasedTarget.java b/jps/jps-builders/src/org/jetbrains/jps/builders/ModuleBasedTarget.java index a2d070990466..7d4c4b0de1dd 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/ModuleBasedTarget.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/ModuleBasedTarget.java @@ -25,7 +25,7 @@ import org.jetbrains.jps.model.module.JpsModule; public abstract class ModuleBasedTarget extends BuildTarget { protected final JpsModule myModule; - public ModuleBasedTarget(BuildTargetType targetType, @NotNull JpsModule module) { + public ModuleBasedTarget(ModuleBasedBuildTargetType targetType, @NotNull JpsModule module) { super(targetType); myModule = module; } diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootIndexImpl.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootIndexImpl.java index b40da51805a0..262f0e433def 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootIndexImpl.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootIndexImpl.java @@ -27,8 +27,8 @@ import org.jetbrains.jps.builders.*; import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor; import org.jetbrains.jps.builders.storage.BuildDataPaths; -import org.jetbrains.jps.incremental.BuilderRegistry; import org.jetbrains.jps.incremental.CompileContext; +import org.jetbrains.jps.incremental.TargetTypeRegistry; import org.jetbrains.jps.indices.IgnoredFileIndex; import org.jetbrains.jps.indices.ModuleExcludeIndex; import org.jetbrains.jps.model.JpsModel; @@ -57,7 +57,7 @@ public class BuildRootIndexImpl implements BuildRootIndex { myRootToDescriptors = new THashMap>(FileUtil.FILE_HASHING_STRATEGY); myFileFilters = new ConcurrentHashMap(); final Iterable rootsProviders = JpsServiceManager.getInstance().getExtensions(AdditionalRootsProviderService.class); - for (BuildTargetType targetType : BuilderRegistry.getInstance().getTargetTypes()) { + for (BuildTargetType targetType : TargetTypeRegistry.getInstance().getTargetTypes()) { for (BuildTarget target : targetIndex.getAllTargets(targetType)) { addRoots(dataPaths, rootsProviders, target, model, index, ignoredFileIndex); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildTargetIndexImpl.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildTargetIndexImpl.java index 245e39df571a..fd180142afb0 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildTargetIndexImpl.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildTargetIndexImpl.java @@ -25,8 +25,8 @@ import gnu.trove.TIntArrayList; import gnu.trove.TIntProcedure; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.builders.*; -import org.jetbrains.jps.incremental.BuilderRegistry; import org.jetbrains.jps.incremental.CompileContext; +import org.jetbrains.jps.incremental.TargetTypeRegistry; import org.jetbrains.jps.model.JpsModel; import org.jetbrains.jps.model.module.JpsModule; @@ -46,7 +46,7 @@ public class BuildTargetIndexImpl implements BuildTargetIndex { myTargets = new THashMap, List>>(); myModuleBasedTargets = new THashMap>(); List>> targetsByType = new ArrayList>>(); - for (BuildTargetType type : BuilderRegistry.getInstance().getTargetTypes()) { + for (BuildTargetType type : TargetTypeRegistry.getInstance().getTargetTypes()) { List> targets = type.computeAllTargets(model); myTargets.put(type, targets); targetsByType.add(targets); diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaModuleBuildTargetType.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaModuleBuildTargetType.java index 3136780252f4..e92414eaf067 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaModuleBuildTargetType.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaModuleBuildTargetType.java @@ -18,7 +18,7 @@ package org.jetbrains.jps.builders.java; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.builders.BuildTargetLoader; -import org.jetbrains.jps.builders.BuildTargetType; +import org.jetbrains.jps.builders.ModuleBasedBuildTargetType; import org.jetbrains.jps.incremental.ModuleBuildTarget; import org.jetbrains.jps.model.JpsModel; import org.jetbrains.jps.model.module.JpsModule; @@ -28,7 +28,7 @@ import java.util.*; /** * @author nik */ -public class JavaModuleBuildTargetType extends BuildTargetType { +public class JavaModuleBuildTargetType extends ModuleBasedBuildTargetType { public static final JavaModuleBuildTargetType PRODUCTION = new JavaModuleBuildTargetType("java-production", false); public static final JavaModuleBuildTargetType TEST = new JavaModuleBuildTargetType("java-test", true); public static final List ALL_TYPES = Arrays.asList(PRODUCTION, TEST); diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourcesTargetType.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourcesTargetType.java index 0e2219ccf249..abc982105fab 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourcesTargetType.java +++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourcesTargetType.java @@ -18,7 +18,7 @@ package org.jetbrains.jps.builders.java; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.builders.BuildTargetLoader; -import org.jetbrains.jps.builders.BuildTargetType; +import org.jetbrains.jps.builders.ModuleBasedBuildTargetType; import org.jetbrains.jps.incremental.ResourcesTarget; import org.jetbrains.jps.model.JpsModel; import org.jetbrains.jps.model.module.JpsModule; @@ -28,7 +28,7 @@ import java.util.*; /** * @author nik */ -public class ResourcesTargetType extends BuildTargetType { +public class ResourcesTargetType extends ModuleBasedBuildTargetType { public static final ResourcesTargetType PRODUCTION = new ResourcesTargetType("resources-production", false); public static final ResourcesTargetType TEST = new ResourcesTargetType("resources-test", true); public static final List ALL_TYPES = Arrays.asList(PRODUCTION, TEST); diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java index 0fd522e6053b..1c6edbf86772 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildRunner.java @@ -165,8 +165,9 @@ public class BuildRunner { Set> targets = new HashSet>(); Map, Set> files; + final TargetTypeRegistry typeRegistry = TargetTypeRegistry.getInstance(); for (TargetTypeBuildScope scope : scopes) { - BuildTargetType targetType = BuilderRegistry.getInstance().getTargetType(scope.getTypeId()); + final BuildTargetType targetType = typeRegistry.getTargetType(scope.getTypeId()); if (targetType == null) { LOG.info("Unknown target type: " + scope.getTypeId()); continue; diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java index 8e244ccad98a..e8e20e1b5d61 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java @@ -24,7 +24,6 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.concurrency.SequentialTaskExecutor; import com.intellij.util.io.DataOutputStream; -import gnu.trove.THashMap; import org.jboss.netty.channel.Channel; import org.jboss.netty.channel.Channels; import org.jetbrains.annotations.Nullable; @@ -32,20 +31,17 @@ import org.jetbrains.jps.api.*; import org.jetbrains.jps.builders.*; import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; import org.jetbrains.jps.builders.java.dependencyView.Callbacks; -import org.jetbrains.jps.incremental.BuilderService; import org.jetbrains.jps.incremental.MessageHandler; +import org.jetbrains.jps.incremental.TargetTypeRegistry; import org.jetbrains.jps.incremental.Utils; import org.jetbrains.jps.incremental.fs.BuildFSState; import org.jetbrains.jps.incremental.fs.FSState; import org.jetbrains.jps.incremental.messages.*; import org.jetbrains.jps.incremental.storage.Timestamps; import org.jetbrains.jps.model.module.JpsModule; -import org.jetbrains.jps.service.JpsServiceManager; import org.jetbrains.jps.service.SharedThreadPool; import java.io.*; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; import java.util.*; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @@ -231,23 +227,18 @@ final class BuildSession implements Runnable, CanceledStatus { } private static boolean scopeContainsModulesOnly(List scopes) { - Map> allTypes = null; + TargetTypeRegistry typeRegistry = null; for (TargetTypeBuildScope scope : scopes) { final String typeId = scope.getTypeId(); if (isJavaModuleBuildType(typeId)) { // fast check continue; } - if (allTypes == null) { + if (typeRegistry == null) { // lazy init - allTypes = new THashMap>(); - for (BuilderService builderService : JpsServiceManager.getInstance().getExtensions(BuilderService.class)) { - for (BuildTargetType targetType : builderService.getTargetTypes()) { - allTypes.put(targetType.getTypeId(), targetType); - } - } + typeRegistry = TargetTypeRegistry.getInstance(); } - final BuildTargetType targetType = allTypes.get(typeId); - if (targetType != null && !isModuleBasedTargetType(targetType)) { + final BuildTargetType targetType = typeRegistry.getTargetType(typeId); + if (targetType != null && !(targetType instanceof ModuleBasedBuildTargetType)) { return false; } } @@ -263,20 +254,6 @@ final class BuildSession implements Runnable, CanceledStatus { return false; } - private static boolean isModuleBasedTargetType(final BuildTargetType targetType) { - Class aClass = targetType.getClass(); - while (!BuildTargetType.class.equals(aClass.getSuperclass())) { - aClass = aClass.getSuperclass(); - } - final ParameterizedType generic = (ParameterizedType)aClass.getGenericSuperclass(); - for (Type type : generic.getActualTypeArguments()) { - if (type instanceof Class && ModuleBasedTarget.class.isAssignableFrom((Class)type)) { - return true; - } - } - return false; - } - private void saveData(final BuildFSState fsState, File dataStorageRoot) { final boolean wasInterrupted = Thread.interrupted(); try { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java index 7b2436ee58ac..fb466079dc38 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java @@ -20,8 +20,6 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.io.FileUtilRt; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jps.builders.BuildTargetType; import org.jetbrains.jps.service.JpsServiceManager; import java.io.File; @@ -39,7 +37,6 @@ public class BuilderRegistry { } private final Map> myModuleLevelBuilders = new HashMap>(); private final List> myTargetBuilders = new ArrayList>(); - private final Map> myTargetTypes = new LinkedHashMap>(); private final FileFilter myModuleBuilderFileFilter; public static BuilderRegistry getInstance() { @@ -66,13 +63,6 @@ public class BuilderRegistry { } myModuleLevelBuilders.get(builder.getCategory()).add(builder); } - for (BuildTargetType type : service.getTargetTypes()) { - String id = type.getTypeId(); - BuildTargetType old = myTargetTypes.put(id, type); - if (old != null) { - LOG.error("Two build target types (" + type + ", " + old + ") use same id (" + id + ")"); - } - } } if (compilableFileExtensions == null) { myModuleBuilderFileFilter = FileUtilRt.ALL_FILES; @@ -88,20 +78,11 @@ public class BuilderRegistry { } } - @Nullable - public BuildTargetType getTargetType(String typeId) { - return myTargetTypes.get(typeId); - } - @NotNull public FileFilter getModuleBuilderFileFilter() { return myModuleBuilderFileFilter; } - public Collection> getTargetTypes() { - return myTargetTypes.values(); - } - public int getModuleLevelBuilderCount() { int count = 0; for (BuilderCategory category : BuilderCategory.values()) { diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/JVMModuleBuildTarget.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/JVMModuleBuildTarget.java index 42afc58fcbc6..12c3c18cc20c 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/JVMModuleBuildTarget.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/JVMModuleBuildTarget.java @@ -19,10 +19,7 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jps.builders.BuildRootDescriptor; -import org.jetbrains.jps.builders.BuildRootIndex; -import org.jetbrains.jps.builders.BuildTargetType; -import org.jetbrains.jps.builders.ModuleBasedTarget; +import org.jetbrains.jps.builders.*; import org.jetbrains.jps.indices.ModuleExcludeIndex; import org.jetbrains.jps.model.module.JpsModule; @@ -38,7 +35,7 @@ import java.util.Set; */ public abstract class JVMModuleBuildTarget extends ModuleBasedTarget { - public JVMModuleBuildTarget(BuildTargetType> targetType, JpsModule module) { + public JVMModuleBuildTarget(ModuleBasedBuildTargetType> targetType, JpsModule module) { super(targetType, module); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/TargetTypeRegistry.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/TargetTypeRegistry.java new file mode 100644 index 000000000000..ab2b35d5bae8 --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/TargetTypeRegistry.java @@ -0,0 +1,60 @@ +/* + * Copyright 2000-2013 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 org.jetbrains.jps.incremental; + +import com.intellij.openapi.diagnostic.Logger; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.builders.BuildTargetType; +import org.jetbrains.jps.service.JpsServiceManager; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +public class TargetTypeRegistry { + private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.TargetTypeRegistry"); + private static class Holder { + static final TargetTypeRegistry ourInstance = new TargetTypeRegistry(); + } + private final Map> myTargetTypes = new LinkedHashMap>(); + + public static TargetTypeRegistry getInstance() { + return Holder.ourInstance; + } + + private TargetTypeRegistry() { + for (BuilderService service : JpsServiceManager.getInstance().getExtensions(BuilderService.class)) { + for (BuildTargetType type : service.getTargetTypes()) { + String id = type.getTypeId(); + BuildTargetType old = myTargetTypes.put(id, type); + if (old != null) { + LOG.error("Two build target types (" + type + ", " + old + ") use same id (" + id + ")"); + } + } + } + } + + @Nullable + public BuildTargetType getTargetType(String typeId) { + return myTargetTypes.get(typeId); + } + + + public Collection> getTargetTypes() { + return myTargetTypes.values(); + } + +} diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FSState.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FSState.java index cc16f3ac7539..dde4f12065db 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FSState.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FSState.java @@ -23,8 +23,8 @@ import gnu.trove.TObjectLongHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.builders.*; -import org.jetbrains.jps.incremental.BuilderRegistry; import org.jetbrains.jps.incremental.CompileContext; +import org.jetbrains.jps.incremental.TargetTypeRegistry; import org.jetbrains.jps.incremental.storage.Timestamps; import org.jetbrains.jps.model.JpsModel; @@ -63,7 +63,7 @@ public class FSState { } public void load(DataInputStream in, JpsModel model, final BuildRootIndex buildRootIndex) throws IOException { - BuilderRegistry registry = BuilderRegistry.getInstance(); + final TargetTypeRegistry registry = TargetTypeRegistry.getInstance(); int typeCount = in.readInt(); while (typeCount-- > 0) { final String typeId = IOUtil.readString(in); diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetsState.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetsState.java index 2c95168fc29d..b4294293dc86 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetsState.java +++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetsState.java @@ -23,7 +23,7 @@ import org.jetbrains.jps.builders.BuildTarget; import org.jetbrains.jps.builders.BuildTargetType; import org.jetbrains.jps.builders.impl.BuildRootIndexImpl; import org.jetbrains.jps.builders.storage.BuildDataPaths; -import org.jetbrains.jps.incremental.BuilderRegistry; +import org.jetbrains.jps.incremental.TargetTypeRegistry; import org.jetbrains.jps.model.JpsModel; import java.io.*; @@ -58,7 +58,7 @@ public class BuildTargetsState { catch (IOException e) { LOG.debug("Cannot load " + targetTypesFile + ":" + e.getMessage(), e); LOG.debug("Loading all target types to calculate max target id"); - for (BuildTargetType type : BuilderRegistry.getInstance().getTargetTypes()) { + for (BuildTargetType type : TargetTypeRegistry.getInstance().getTargetTypes()) { getTypeState(type); } } diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/CompileScopeTestBuilder.java b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/CompileScopeTestBuilder.java index 8e49ab4ef8cf..b8c901470e28 100644 --- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/CompileScopeTestBuilder.java +++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/CompileScopeTestBuilder.java @@ -17,10 +17,10 @@ package org.jetbrains.jps.builders; import org.jetbrains.jps.api.BuildType; import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; -import org.jetbrains.jps.incremental.BuilderRegistry; import org.jetbrains.jps.incremental.CompileScope; import org.jetbrains.jps.incremental.CompileScopeImpl; import org.jetbrains.jps.incremental.ModuleBuildTarget; +import org.jetbrains.jps.incremental.TargetTypeRegistry; import org.jetbrains.jps.incremental.artifacts.ArtifactBuildTarget; import org.jetbrains.jps.incremental.artifacts.ArtifactBuildTargetType; import org.jetbrains.jps.model.artifact.JpsArtifact; @@ -85,7 +85,7 @@ public class CompileScopeTestBuilder { } public CompileScopeTestBuilder all() { - myTargetTypes.addAll(BuilderRegistry.getInstance().getTargetTypes()); + myTargetTypes.addAll(TargetTypeRegistry.getInstance().getTargetTypes()); return this; } diff --git a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenResourcesTargetType.java b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenResourcesTargetType.java index a2358c0b5e96..5429a20910b8 100644 --- a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenResourcesTargetType.java +++ b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenResourcesTargetType.java @@ -18,7 +18,7 @@ package org.jetbrains.jps.maven.model.impl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jps.builders.BuildTargetLoader; -import org.jetbrains.jps.builders.BuildTargetType; +import org.jetbrains.jps.builders.ModuleBasedBuildTargetType; import org.jetbrains.jps.maven.model.JpsMavenExtensionService; import org.jetbrains.jps.model.JpsModel; import org.jetbrains.jps.model.module.JpsModule; @@ -32,7 +32,7 @@ import java.util.Map; * @author Eugene Zhuravlev * Date: 10/24/12 */ -public class MavenResourcesTargetType extends BuildTargetType { +public class MavenResourcesTargetType extends ModuleBasedBuildTargetType { public static final MavenResourcesTargetType PRODUCTION = new MavenResourcesTargetType("maven-resources-production", false); public static final MavenResourcesTargetType TEST = new MavenResourcesTargetType("maven-resources-test", true); From 194d4002769fa5d9191461dce33755acf77067e0 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 19 Feb 2013 20:24:25 +0400 Subject: [PATCH 11/19] [github] Create Gist: fix github host url for Enterprise. IDEA-101450 Instead of always using https://api.github.com, use the host defined in the settings. --- .../src/org/jetbrains/plugins/github/GithubApiUtil.java | 5 +++++ .../org/jetbrains/plugins/github/GithubCreateGistAction.java | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubApiUtil.java b/plugins/github/src/org/jetbrains/plugins/github/GithubApiUtil.java index 6ca7f78ce4e7..adc47bd8bf97 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubApiUtil.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubApiUtil.java @@ -119,6 +119,11 @@ public class GithubApiUtil { return "https://" + getApiUrlWithoutProtocol(urlFromSettings); } + @NotNull + public static String getApiUrl() { + return getApiUrl(GithubSettings.getInstance().getHost()); + } + /** * Returns the "host" part of Git URLs. * E.g.: https://github.com diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java index 8ee054fcc76a..b2143698a5cc 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java @@ -221,7 +221,7 @@ public class GithubCreateGistAction extends DumbAwareAction { } String requestBody = prepareJsonRequest(description, isPrivate, contents); try { - JsonElement jsonElement = GithubApiUtil.postRequest("https://api.github.com", login, password, "/gists", requestBody); + JsonElement jsonElement = GithubApiUtil.postRequest(GithubApiUtil.getApiUrl(), login, password, "/gists", requestBody); if (jsonElement == null) { LOG.info("Null JSON response returned by GitHub"); showError(project, "Failed to create gist", "Empty JSON response returned by GitHub", null, null); From 76fce8eae0a02f53889ed17da1d797832c9b6258 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Tue, 19 Feb 2013 20:29:22 +0400 Subject: [PATCH 12/19] fixed PY-8581 Fill Paragraph should not corrupt indentation PY-8937 fill paragraph works wrong on simple strings --- .../editorActions/fillParagraph/ParagraphFillHandler.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/fillParagraph/ParagraphFillHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/fillParagraph/ParagraphFillHandler.java index 61842e3bf750..548c16b2e47c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/fillParagraph/ParagraphFillHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/fillParagraph/ParagraphFillHandler.java @@ -40,7 +40,9 @@ public class ParagraphFillHandler { for (String string : subStrings) { final String startTrimmed = StringUtil.trimStart(string.trim(), prefix.trim()); final String str = StringUtil.trimEnd(startTrimmed, postfix.trim()); - stringBuilder.append(str.trim()).append(" "); + final String finalString = str.trim(); + if (!StringUtil.isEmptyOrSpaces(finalString)) + stringBuilder.append(finalString).append(" "); } appendPostfix(element, text, stringBuilder); From 5a6db176d891fb22ca6600f2e3b9cf567530b730 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 19 Feb 2013 20:34:35 +0400 Subject: [PATCH 13/19] [github] Add "Enterprise" to the list of possible user plans. It fixes IDEA-101433, since unknown plan is treated as "free". --- .../github/src/org/jetbrains/plugins/github/GithubUser.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubUser.java b/plugins/github/src/org/jetbrains/plugins/github/GithubUser.java index dbac8d7e6055..3bdf5eab63e7 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubUser.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubUser.java @@ -32,7 +32,8 @@ class GithubUser { BRONZE, SILVER, GOLD, - PLATINUM; + PLATINUM, + ENTERPRISE; public boolean isPrivateRepoAllowed() { return this != FREE; From 66023b99274c4cdc33e0a51450cd4f9acf90d312 Mon Sep 17 00:00:00 2001 From: Alexander Lobas Date: Tue, 19 Feb 2013 20:33:32 +0400 Subject: [PATCH 14/19] After-review cosmetics --- .../com/intellij/uiDesigner/compiler/AsmCodeGenerator.java | 4 ++-- .../compiler/instrumentation/InstrumentationClassFinder.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/AsmCodeGenerator.java b/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/AsmCodeGenerator.java index eda53383bd35..5e8de15421da 100644 --- a/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/AsmCodeGenerator.java +++ b/java/compiler/forms-compiler/src/com/intellij/uiDesigner/compiler/AsmCodeGenerator.java @@ -545,8 +545,8 @@ public class AsmCodeGenerator { } //componentClass.getMethod(property.getWriteMethodName(), new Class[] { setterClass } ); final String descriptor = "(L"+setterClass.getName().replace('.', '/') + ";)V"; - final InstrumentationClassFinder.PseudoMethod setter = componentClass.findMethodRecursive(property.getWriteMethodName(), - descriptor); + final InstrumentationClassFinder.PseudoMethod setter = componentClass.findMethodInHierarchy(property.getWriteMethodName(), + descriptor); if (setter == null) { continue; } diff --git a/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java b/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java index 29f7e03b8b1e..4eba0eee8bf8 100644 --- a/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java +++ b/java/compiler/instrumentation-util/src/com/intellij/compiler/instrumentation/InstrumentationClassFinder.java @@ -250,12 +250,12 @@ public class InstrumentationClassFinder { return null; } - public PseudoMethod findMethodRecursive(String name, String descriptor) throws IOException, ClassNotFoundException { + public PseudoMethod findMethodInHierarchy(String name, String descriptor) throws IOException, ClassNotFoundException { PseudoMethod method = findMethod(name, descriptor); if (method == null) { PseudoClass superClass = getSuperClass(); if (superClass != null) { - method = superClass.findMethodRecursive(name, descriptor); + method = superClass.findMethodInHierarchy(name, descriptor); } } return method; From afbf36aaf975dcdb713c2c6896512cd3fef83d53 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Tue, 19 Feb 2013 20:43:48 +0400 Subject: [PATCH 15/19] [github] Fix "Open in browser" and Rebase fork for Enterprise. Once again, use the special method to get the host URL. --- .../src/org/jetbrains/plugins/github/GithubRebaseAction.java | 2 +- .../plugins/github/GithubShowCommitInBrowserAction.java | 2 +- plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java index 30db79d4546d..9d41001a8133 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java @@ -153,7 +153,7 @@ public class GithubRebaseAction extends DumbAwareAction { final String parent = repositoryInfo.getParentName(); LOG.assertTrue(parent != null, "Parent repository not found!"); final String parentDotGit = parent + ".git"; - final String parentRepoUrl = "https://github.com/" + parentDotGit; + final String parentRepoUrl = GithubApiUtil.getGitHost() + "/" + parentDotGit; // Check that corresponding remote branch is configured for the fork origin repo final Ref remoteForForkParentRepo = new Ref(); diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java index b8fc3151dc4a..29f64d3b558a 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java @@ -44,7 +44,7 @@ abstract class GithubShowCommitInBrowserAction extends DumbAwareAction { return; } - String githubUrl = "https://github.com/" + userAndRepository + "/commit/" + revisionHash; + String githubUrl = GithubApiUtil.getGitHost() + "/" + userAndRepository + "/commit/" + revisionHash; BrowserUtil.launchBrowser(githubUrl); } diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java b/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java index c3e1d6dd39df..54ad781e8b03 100644 --- a/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java +++ b/plugins/github/src/org/jetbrains/plugins/github/GithubUtil.java @@ -366,7 +366,7 @@ public class GithubUtil { } public static boolean isGithubUrl(@NotNull String url) { - return url.contains("github.com"); + return url.contains(GithubApiUtil.getGitHost()); } static void setVisibleEnabled(AnActionEvent e, boolean visible, boolean enabled) { From 0e7b00f314405fb5bfdcc4f66deee14668317f3d Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Tue, 19 Feb 2013 20:41:26 +0400 Subject: [PATCH 16/19] WEB-6672 --- .../com/intellij/notification/EventLog.java | 15 ++--- .../com/intellij/util/IJSwingUtilities.java | 14 ++++ .../io/socketConnection/ConnectionStatus.java | 3 - .../SocketConnectionListener.java | 2 - .../com/intellij/xdebugger/XDebugProcess.java | 8 ++- .../frame/XDebuggerTreeNodeHyperlink.java | 30 +++++++-- .../xdebugger/impl/frame/XVariablesView.java | 16 ++++- .../impl/ui/tree/XDebuggerTreeRenderer.java | 7 +- .../impl/ui/tree/nodes/MessageTreeNode.java | 67 +++++++++++++++++-- .../impl/ui/tree/nodes/XDebuggerTreeNode.java | 14 +++- .../impl/ui/tree/nodes/XValueNodeImpl.java | 3 +- 11 files changed, 137 insertions(+), 42 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/notification/EventLog.java b/platform/platform-impl/src/com/intellij/notification/EventLog.java index b6c1abe67eba..ab55cdf111d5 100644 --- a/platform/platform-impl/src/com/intellij/notification/EventLog.java +++ b/platform/platform-impl/src/com/intellij/notification/EventLog.java @@ -33,15 +33,14 @@ import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.*; import com.intellij.ui.awt.RelativePoint; +import com.intellij.util.IJSwingUtilities; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.hash.LinkedHashMap; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.event.HyperlinkEvent; -import java.net.MalformedURLException; -import java.net.URL; +import javax.swing.*; import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Matcher; @@ -424,14 +423,8 @@ public class EventLog { public void navigate(Project project) { NotificationListener listener = myNotification.getListener(); if (listener != null) { - EventLogConsole console = EventLog.getProjectComponent(project).myConsole; - URL url = null; - try { - url = new URL(null, myHref); - } - catch (MalformedURLException ignored) { - } - listener.hyperlinkUpdate(myNotification, new HyperlinkEvent(console.getConsoleEditor().getContentComponent(), HyperlinkEvent.EventType.ACTIVATED, url, myHref)); + JComponent component = getProjectComponent(project).myConsole.getConsoleEditor().getContentComponent(); + listener.hyperlinkUpdate(myNotification, IJSwingUtilities.createHyperlinkEvent(myHref, component)); } } } diff --git a/platform/platform-impl/src/com/intellij/util/IJSwingUtilities.java b/platform/platform-impl/src/com/intellij/util/IJSwingUtilities.java index fadbcf72dd44..9458305d1aa0 100644 --- a/platform/platform-impl/src/com/intellij/util/IJSwingUtilities.java +++ b/platform/platform-impl/src/com/intellij/util/IJSwingUtilities.java @@ -23,10 +23,14 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.FilteringIterator; import com.intellij.util.ui.UIUtil; import gnu.trove.TIntStack; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.event.HyperlinkEvent; import java.awt.*; +import java.net.MalformedURLException; +import java.net.URL; import java.util.Iterator; public class IJSwingUtilities { @@ -201,4 +205,14 @@ public class IJSwingUtilities { } } } + + public static HyperlinkEvent createHyperlinkEvent(@Nullable String href, @NotNull Object source) { + URL url = null; + try { + url = new URL(href); + } + catch (MalformedURLException ignored) { + } + return new HyperlinkEvent(source, HyperlinkEvent.EventType.ACTIVATED, url, href); + } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/util/io/socketConnection/ConnectionStatus.java b/platform/platform-impl/src/com/intellij/util/io/socketConnection/ConnectionStatus.java index fb623dd5cd87..0be2bb928585 100644 --- a/platform/platform-impl/src/com/intellij/util/io/socketConnection/ConnectionStatus.java +++ b/platform/platform-impl/src/com/intellij/util/io/socketConnection/ConnectionStatus.java @@ -2,9 +2,6 @@ package com.intellij.util.io.socketConnection; import org.jetbrains.annotations.NotNull; -/** - * @author nik - */ public enum ConnectionStatus { NOT_CONNECTED("Not connected"), WAITING_FOR_CONNECTION("Waiting for connection"), CONNECTED("Connected"), DISCONNECTED("Disconnected"), CONNECTION_FAILED("Connection failed"); diff --git a/platform/platform-impl/src/com/intellij/util/io/socketConnection/SocketConnectionListener.java b/platform/platform-impl/src/com/intellij/util/io/socketConnection/SocketConnectionListener.java index c1af8d67dd76..d9ff887c4123 100644 --- a/platform/platform-impl/src/com/intellij/util/io/socketConnection/SocketConnectionListener.java +++ b/platform/platform-impl/src/com/intellij/util/io/socketConnection/SocketConnectionListener.java @@ -6,7 +6,5 @@ import java.util.EventListener; * @author nik */ public interface SocketConnectionListener extends EventListener { - void statusChanged(ConnectionStatus status); - } diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java index f40c0b90db7f..003d0b0a9dbf 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java @@ -29,6 +29,8 @@ import com.intellij.xdebugger.stepping.XSmartStepIntoHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.event.HyperlinkListener; + /** * Extends this class to provide debugging capabilities for custom language/framework. * @@ -190,4 +192,8 @@ public abstract class XDebugProcess { return mySession.isStopped() ? XDebuggerBundle.message("debugger.state.message.disconnected") : XDebuggerBundle.message("debugger.state.message.connected"); } -} + @Nullable + public HyperlinkListener getCurrentStateHyperlinkListener() { + return null; + } +} \ No newline at end of file diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XDebuggerTreeNodeHyperlink.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XDebuggerTreeNodeHyperlink.java index fa8d5aeee4a3..35c2af62e95b 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XDebuggerTreeNodeHyperlink.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XDebuggerTreeNodeHyperlink.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -16,25 +16,26 @@ package com.intellij.xdebugger.frame; import com.intellij.ui.SimpleTextAttributes; +import com.intellij.util.IJSwingUtilities; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import javax.swing.event.HyperlinkListener; import java.awt.event.MouseEvent; /** * Describes a hyperlink inside a debugger node - * - * @author nik */ public abstract class XDebuggerTreeNodeHyperlink { - private String myLinkText; + private final String linkText; protected XDebuggerTreeNodeHyperlink(@NotNull String linkText) { - myLinkText = linkText; + this.linkText = linkText; } @NotNull public String getLinkText() { - return myLinkText; + return linkText; } @NotNull @@ -43,4 +44,21 @@ public abstract class XDebuggerTreeNodeHyperlink { } public abstract void onClick(MouseEvent event); + + public static final class HyperlinkListenerDelegator extends XDebuggerTreeNodeHyperlink { + private final HyperlinkListener hyperlinkListener; + private final String href; + + public HyperlinkListenerDelegator(@NotNull String linkText, @Nullable String href, @NotNull HyperlinkListener hyperlinkListener) { + super(linkText); + + this.hyperlinkListener = hyperlinkListener; + this.href = href; + } + + @Override + public void onClick(MouseEvent event) { + hyperlinkListener.hyperlinkUpdate(IJSwingUtilities.createHyperlinkEvent(href, getLinkText())); + } + } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java index ceff94df6b9f..0d0bf79bd154 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XVariablesView.java @@ -17,6 +17,7 @@ package com.intellij.xdebugger.impl.frame; import com.intellij.ide.dnd.DnDManager; import com.intellij.openapi.Disposable; +import com.intellij.xdebugger.XDebugProcess; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; @@ -26,12 +27,14 @@ import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreePanel; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeRestorer; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTreeState; -import com.intellij.xdebugger.impl.ui.tree.nodes.MessageTreeNode; +import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode; import com.intellij.xdebugger.impl.ui.tree.nodes.XStackFrameNode; import org.jetbrains.annotations.NotNull; import javax.swing.*; +import static com.intellij.xdebugger.impl.ui.tree.nodes.MessageTreeNode.createInfoMessage; + /** * @author nik */ @@ -74,8 +77,15 @@ public class XVariablesView extends XDebugViewBase { } else { tree.setSourcePosition(null); - String message = !mySession.isStopped() && mySession.isPaused() ? "Frame is not available" : mySession.getDebugProcess().getCurrentStateMessage(); - tree.setRoot(MessageTreeNode.createInfoMessage(tree, null, message), true); + XDebugProcess debugProcess = mySession.getDebugProcess(); + XDebuggerTreeNode node; + if (!mySession.isStopped() && mySession.isPaused()) { + node = createInfoMessage(tree, "Frame is not available"); + } + else { + node = createInfoMessage(tree, debugProcess.getCurrentStateMessage(), debugProcess.getCurrentStateHyperlinkListener()); + } + tree.setRoot(node, true); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreeRenderer.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreeRenderer.java index b072e579b517..3970867313c7 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreeRenderer.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreeRenderer.java @@ -16,7 +16,6 @@ package com.intellij.xdebugger.impl.ui.tree; import com.intellij.ui.ColoredTreeCellRenderer; -import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink; import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode; import javax.swing.*; @@ -33,11 +32,7 @@ class XDebuggerTreeRenderer extends ColoredTreeCellRenderer { final int row, final boolean hasFocus) { XDebuggerTreeNode node = (XDebuggerTreeNode)value; - node.getText().appendToComponent(this); - final XDebuggerTreeNodeHyperlink link = node.getLink(); - if (link != null) { - append(link.getLinkText(), link.getTextAttributes(), link); - } + node.appendToComponent(this); setIcon(node.getIcon()); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/MessageTreeNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/MessageTreeNode.java index 434fb6be17d6..026f7e1d861b 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/MessageTreeNode.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/MessageTreeNode.java @@ -16,7 +16,9 @@ package com.intellij.xdebugger.impl.ui.tree.nodes; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.ui.SimpleColoredComponent; import com.intellij.ui.SimpleTextAttributes; +import com.intellij.util.SmartList; import com.intellij.xdebugger.XDebuggerBundle; import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink; import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants; @@ -25,10 +27,13 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.event.HyperlinkListener; import javax.swing.tree.TreeNode; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * @author nik @@ -37,7 +42,7 @@ public class MessageTreeNode extends XDebuggerTreeNode { private boolean myEllipsis; private XDebuggerTreeNodeHyperlink myLink; - private MessageTreeNode(XDebuggerTree tree, final XDebuggerTreeNode parent, final String message, final SimpleTextAttributes attributes, + private MessageTreeNode(XDebuggerTree tree, @Nullable final XDebuggerTreeNode parent, final String message, final SimpleTextAttributes attributes, @Nullable Icon icon) { this(tree, parent, message, attributes, icon, null); } @@ -56,7 +61,7 @@ public class MessageTreeNode extends XDebuggerTreeNode { myText.append(message, attributes); } - protected MessageTreeNode(XDebuggerTree tree, XDebuggerTreeNode parent, boolean leaf) { + protected MessageTreeNode(XDebuggerTree tree, @Nullable XDebuggerTreeNode parent, boolean leaf) { super(tree, parent, leaf); myEllipsis = false; } @@ -69,8 +74,9 @@ public class MessageTreeNode extends XDebuggerTreeNode { return myEllipsis; } + @Nullable @Override - public XDebuggerTreeNodeHyperlink getLink() { + protected XDebuggerTreeNodeHyperlink getLink() { return myLink; } @@ -105,7 +111,7 @@ public class MessageTreeNode extends XDebuggerTreeNode { public static List createMessages(XDebuggerTree tree, final XDebuggerTreeNode parent, @NotNull String errorMessage, XDebuggerTreeNodeHyperlink link, final Icon icon, final SimpleTextAttributes attributes) { - List messages = new ArrayList(1); + List messages = new SmartList(); final List lines = StringUtil.split(errorMessage, "\n", true, false); for (int i = 0; i < lines.size(); i++) { messages.add(new MessageTreeNode(tree, parent, lines.get(i), attributes, @@ -114,8 +120,55 @@ public class MessageTreeNode extends XDebuggerTreeNode { return messages; } - public static MessageTreeNode createInfoMessage(XDebuggerTree tree, final XDebuggerTreeNode parent, @NotNull String message) { - return new MessageTreeNode(tree, parent, message, SimpleTextAttributes.REGULAR_ATTRIBUTES, - XDebuggerUIConstants.INFORMATION_MESSAGE_ICON); + public static MessageTreeNode createInfoMessage(XDebuggerTree tree, @NotNull String message) { + return createInfoMessage(tree, message, null); + } + + public static MessageTreeNode createInfoMessage(XDebuggerTree tree, @NotNull String message, @Nullable HyperlinkListener hyperlinkListener) { + Matcher matcher = MessageTreeNodeWithLinks.HREF_PATTERN.matcher(message); + if (hyperlinkListener == null || !matcher.find()) { + return new MessageTreeNode(tree, null, message, SimpleTextAttributes.REGULAR_ATTRIBUTES, + XDebuggerUIConstants.INFORMATION_MESSAGE_ICON); + } + + List objects = new ArrayList(); + int prev = 0; + do { + if (matcher.start() != prev) { + objects.add(message.substring(prev, matcher.start())); + } + objects.add(new XDebuggerTreeNodeHyperlink.HyperlinkListenerDelegator(matcher.group(2), matcher.group(1), hyperlinkListener)); + prev = matcher.end(); + } + while (matcher.find()); + + if (prev < (message.length() - 1)) { + objects.add(message.substring(prev)); + } + return new MessageTreeNodeWithLinks(tree, objects); + } + + private static class MessageTreeNodeWithLinks extends MessageTreeNode { + private static final Pattern HREF_PATTERN = Pattern.compile("([^<]*)"); + private final List objects; + + private MessageTreeNodeWithLinks(XDebuggerTree tree, List objects) { + super(tree, null, true); + setIcon(XDebuggerUIConstants.INFORMATION_MESSAGE_ICON); + this.objects = objects; + } + + @Override + public void appendToComponent(SimpleColoredComponent component) { + for (Object object : objects) { + if (object instanceof String) { + component.append((String)object); + } + else { + XDebuggerTreeNodeHyperlink hyperlink = (XDebuggerTreeNodeHyperlink)object; + component.append(hyperlink.getLinkText(), SimpleTextAttributes.LINK_ATTRIBUTES, hyperlink); + } + } + } } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java index f5f2e0d26be3..372942e3c1a0 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java @@ -15,6 +15,7 @@ */ package com.intellij.xdebugger.impl.ui.tree.nodes; +import com.intellij.ui.SimpleColoredComponent; import com.intellij.ui.SimpleColoredText; import com.intellij.util.enumeration.EmptyEnumeration; import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink; @@ -38,7 +39,7 @@ public abstract class XDebuggerTreeNode implements TreeNode { private Icon myIcon; private TreePath myPath; - protected XDebuggerTreeNode(final XDebuggerTree tree, final XDebuggerTreeNode parent, final boolean leaf) { + protected XDebuggerTreeNode(final XDebuggerTree tree, final @Nullable XDebuggerTreeNode parent, final boolean leaf) { myParent = parent; myLeaf = leaf; myTree = tree; @@ -88,7 +89,7 @@ public abstract class XDebuggerTreeNode implements TreeNode { } @Nullable - public XDebuggerTreeNodeHyperlink getLink() { + protected XDebuggerTreeNodeHyperlink getLink() { return null; } @@ -168,4 +169,13 @@ public abstract class XDebuggerTreeNode implements TreeNode { public abstract List getLoadedChildren(); public abstract void clearChildren(); + + public void appendToComponent(SimpleColoredComponent component) { + getText().appendToComponent(component); + + XDebuggerTreeNodeHyperlink link = getLink(); + if (link != null) { + component.append(link.getLinkText(), link.getTextAttributes(), link); + } + } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java index f2ddaf9176a9..9375dab72367 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java @@ -170,8 +170,9 @@ public class XValueNodeImpl extends XValueContainerNode implements XValu return myFullValueEvaluator; } + @Nullable @Override - public XDebuggerTreeNodeHyperlink getLink() { + protected XDebuggerTreeNodeHyperlink getLink() { if (myFullValueEvaluator != null) { return new XDebuggerTreeNodeHyperlink(myFullValueEvaluator.getLinkText()) { @Override From 78f69c55a2c1cdf13e9fd8a65c086e4e9288cb0c Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Tue, 19 Feb 2013 18:54:14 +0100 Subject: [PATCH 17/19] debugger evaluator: handle autoboxing for constructor call arguments (IDEA-101465) --- .../expression/EvaluatorBuilderImpl.java | 80 +++++++++++-------- .../expression/MethodEvaluator.java | 10 +-- 2 files changed, 50 insertions(+), 40 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java index a596e30b5565..5af26dba2573 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java @@ -864,15 +864,16 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { } final PsiExpressionList argumentList = expression.getArgumentList(); final PsiExpression[] argExpressions = argumentList.getExpressions(); - List argumentEvaluators = new ArrayList(argExpressions.length); + final Evaluator[] argumentEvaluators = new Evaluator[argExpressions.length]; // evaluate arguments - for (PsiExpression psiExpression : argExpressions) { + for (int idx = 0; idx < argExpressions.length; idx++) { + final PsiExpression psiExpression = argExpressions[idx]; psiExpression.accept(this); if (myResult == null) { // cannot build evaluator throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", psiExpression.getText())); } - argumentEvaluators.add(new DisableGC(myResult)); + argumentEvaluators[idx] = new DisableGC(myResult); } PsiReferenceExpression methodExpr = expression.getMethodExpression(); @@ -953,35 +954,7 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { } if (psiMethod != null) { - // handle autoboxing - final PsiParameter[] declaredParams = psiMethod.getParameterList().getParameters(); - if (declaredParams.length > 0) { - final int paramCount = Math.max(declaredParams.length, argExpressions.length); - PsiType varargType = null; - for (int idx = 0; idx < paramCount; idx++) { - if (idx >= argExpressions.length) { - break; // actual arguments count is less than number of declared params - } - PsiType declaredParamType; - if (idx < declaredParams.length) { - declaredParamType = resolveResult.getSubstitutor().substitute(declaredParams[idx].getType()); - if (declaredParamType instanceof PsiEllipsisType) { - declaredParamType = varargType = ((PsiEllipsisType)declaredParamType).getComponentType(); - } - } - else if (varargType != null) { - declaredParamType = varargType; - } - else { - break; - } - final PsiType actualArgType = argExpressions[idx].getType(); - if (TypeConversionUtil.boxingConversionApplicable(declaredParamType, actualArgType)) { - final Evaluator argEval = argumentEvaluators.get(idx); - argumentEvaluators.set(idx, declaredParamType instanceof PsiPrimitiveType ? new UnBoxingEvaluator(argEval) : new BoxingEvaluator(argEval)); - } - } - } + processBoxingConversions(psiMethod.getParameterList().getParameters(), argExpressions, resolveResult.getSubstitutor(), argumentEvaluators); } myResult = new MethodEvaluator(objectEvaluator, contextClass, methodExpr.getReferenceName(), psiMethod != null ? JVMNameUtil.getJVMSignature(psiMethod) : null, argumentEvaluators); @@ -1163,8 +1136,9 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { if (argumentList == null) { throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", expression.getText())); return; } - PsiExpression[] argExpressions = argumentList.getExpressions(); - PsiMethod constructor = expression.resolveConstructor(); + final PsiExpression[] argExpressions = argumentList.getExpressions(); + final JavaResolveResult constructorResolveResult = expression.resolveMethodGenerics(); + final PsiMethod constructor = (PsiMethod)constructorResolveResult.getElement(); if (constructor == null && argExpressions.length > 0) { throw new EvaluateRuntimeException(new EvaluateException( DebuggerBundle.message("evaluation.error.cannot.resolve.constructor", expression.getText()), null)); @@ -1181,6 +1155,11 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", argExpression.getText())); } } + + if (constructor != null) { + processBoxingConversions(constructor.getParameterList().getParameters(), argExpressions, constructorResolveResult.getSubstitutor(), argumentEvaluators); + } + //noinspection HardCodedStringLiteral JVMName signature = constructor != null ? JVMNameUtil.getJVMSignature(constructor) : JVMNameUtil.getJVMRawText("()V"); myResult = new NewClassInstanceEvaluator( @@ -1251,4 +1230,37 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder { return new ExpressionEvaluatorImpl(myResult); } } + + private static void processBoxingConversions(final PsiParameter[] declaredParams, + final PsiExpression[] actualArgumentExpressions, + final PsiSubstitutor methodResolveSubstitutor, + final Evaluator[] argumentEvaluators) { + if (declaredParams.length > 0) { + final int paramCount = Math.max(declaredParams.length, actualArgumentExpressions.length); + PsiType varargType = null; + for (int idx = 0; idx < paramCount; idx++) { + if (idx >= actualArgumentExpressions.length) { + break; // actual arguments count is less than number of declared params + } + PsiType declaredParamType; + if (idx < declaredParams.length) { + declaredParamType = methodResolveSubstitutor.substitute(declaredParams[idx].getType()); + if (declaredParamType instanceof PsiEllipsisType) { + declaredParamType = varargType = ((PsiEllipsisType)declaredParamType).getComponentType(); + } + } + else if (varargType != null) { + declaredParamType = varargType; + } + else { + break; + } + final PsiType actualArgType = actualArgumentExpressions[idx].getType(); + if (TypeConversionUtil.boxingConversionApplicable(declaredParamType, actualArgType)) { + final Evaluator argEval = argumentEvaluators[idx]; + argumentEvaluators[idx] = declaredParamType instanceof PsiPrimitiveType ? new UnBoxingEvaluator(argEval) : new BoxingEvaluator(argEval); + } + } + } + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java index 257bad282949..a4f9a8d55d48 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/MethodEvaluator.java @@ -35,7 +35,6 @@ import com.sun.jdi.ObjectReference; import com.sun.jdi.ReferenceType; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; public class MethodEvaluator implements Evaluator { @@ -43,10 +42,10 @@ public class MethodEvaluator implements Evaluator { private final JVMName myClassName; private final JVMName myMethodSignature; private final String myMethodName; - private final List myArgumentEvaluators; + private final Evaluator[] myArgumentEvaluators; private final Evaluator myObjectEvaluator; - public MethodEvaluator(Evaluator objectEvaluator, JVMName className, String methodName, JVMName signature, List argumentEvaluators) { + public MethodEvaluator(Evaluator objectEvaluator, JVMName className, String methodName, JVMName signature, Evaluator[] argumentEvaluators) { myObjectEvaluator = new DisableGC(objectEvaluator); myClassName = className; myMethodName = methodName; @@ -76,9 +75,8 @@ public class MethodEvaluator implements Evaluator { if (!(object instanceof ObjectReference || object instanceof ClassType)) { throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.evaluating.method", myMethodName)); } - List args = new ArrayList(myArgumentEvaluators.size()); - for (Iterator it = myArgumentEvaluators.iterator(); it.hasNext();) { - Evaluator evaluator = (Evaluator)it.next(); + List args = new ArrayList(myArgumentEvaluators.length); + for (Evaluator evaluator : myArgumentEvaluators) { args.add(evaluator.evaluate(context)); } try { From 8f99a78d325d32c5d672da602d127e07df67deb7 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 19 Feb 2013 19:16:36 +0100 Subject: [PATCH 18/19] revert --- .../intellij/psi/impl/source/xml/XmlTokenImpl.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTokenImpl.java b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTokenImpl.java index cc3acb6d2a09..fa9a9c863fbd 100644 --- a/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTokenImpl.java +++ b/xml/impl/src/com/intellij/psi/impl/source/xml/XmlTokenImpl.java @@ -71,15 +71,12 @@ public class XmlTokenImpl extends LeafPsiElement implements XmlToken, Navigatabl (elementType == XmlTokenType.XML_TAG_CHARACTERS && getParent() instanceof XmlProcessingInstruction) ) { return ReferenceProvidersRegistry.getReferencesFromProviders(this, XmlToken.class); - } else if (elementType == XmlTokenType.XML_NAME) { - if (getParent() instanceof PsiErrorElement) { - final PsiElement element = getPrevSibling(); - - if (element instanceof XmlToken && ((XmlToken)element).getTokenType() == XmlTokenType.XML_END_TAG_START) { - return new PsiReference[]{TagNameReference.createTagNameReference(this, getNode(), false)}; - } + } else if (elementType == XmlTokenType.XML_NAME && getParent() instanceof PsiErrorElement) { + final PsiElement element = getPrevSibling(); + + if (element instanceof XmlToken && ((XmlToken)element).getTokenType() == XmlTokenType.XML_END_TAG_START) { + return new PsiReference[] {TagNameReference.createTagNameReference(this, getNode(), false)}; } - return ReferenceProvidersRegistry.getReferencesFromProviders(this, XmlToken.class); } return super.getReferences(); From f0f68b157c23c3bf80d1dc1b6e88721d596a1119 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 19 Feb 2013 20:47:10 +0100 Subject: [PATCH 19/19] javafx: very simple java class reference wrapper --- .../fxml/refs/FxmlReferencesContributor.java | 104 +++++++++++++++--- 1 file changed, 90 insertions(+), 14 deletions(-) diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/FxmlReferencesContributor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/FxmlReferencesContributor.java index f20e06168c17..93f6d5aa0e1e 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/FxmlReferencesContributor.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/FxmlReferencesContributor.java @@ -15,11 +15,14 @@ */ package org.jetbrains.plugins.javaFX.fxml.refs; +import com.intellij.openapi.util.TextRange; import com.intellij.patterns.*; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReferenceProvider; -import com.intellij.psi.xml.*; -import com.intellij.util.ArrayUtil; +import com.intellij.psi.xml.XmlElement; +import com.intellij.psi.xml.XmlTag; +import com.intellij.psi.xml.XmlTokenType; +import com.intellij.util.IncorrectOperationException; import com.intellij.util.ProcessingContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -48,18 +51,8 @@ public class FxmlReferencesContributor extends PsiReferenceContributor { .and(attributeValueInFxml), CLASS_REFERENCE_PROVIDER); - registrar.registerReferenceProvider(PlatformPatterns.psiElement(XmlTokenType.XML_NAME).inFile(inFxmlElementPattern()), - new JavaClassReferenceProvider(){ - @NotNull - @Override - public PsiReference[] getReferencesByString(String str, - @NotNull PsiElement position, - int offsetInPosition) { - final PsiReference[] references = super.getReferencesByString(str, position, offsetInPosition); - if (references.length <= 1) return PsiReference.EMPTY_ARRAY; - return ArrayUtil.remove(references, references.length - 1); - } - }); + registrar.registerReferenceProvider(XmlPatterns.xmlTag().with(inFxmlCondition()), + new MyJavaClassReferenceProvider()); registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName(FxmlConstants.FX_ID)) .and(attributeValueInFxml), @@ -131,4 +124,87 @@ public class FxmlReferencesContributor extends PsiReferenceContributor { } }; } + + private static class MyJavaClassReferenceProvider extends JavaClassReferenceProvider { + @NotNull + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element) { + return getReferencesByString(((XmlTag)element).getName(), element, 1); + } + + @NotNull + @Override + public PsiReference[] getReferencesByString(String str, + @NotNull final PsiElement position, + int offsetInPosition) { + final PsiReference[] references = super.getReferencesByString(str, position, offsetInPosition); + if (references.length <= 1) return PsiReference.EMPTY_ARRAY; + final PsiReference[] results = new PsiReference[references.length - 1]; + for (int i = 0; i < results.length; i++) { + results[i] = new JavaClassReferenceWrapper(references[i], position); + } + return results; + } + + private static class JavaClassReferenceWrapper implements PsiReference { + private final PsiReference myReference; + private final PsiElement myPosition; + + public JavaClassReferenceWrapper(PsiReference reference, PsiElement position) { + myReference = reference; + myPosition = position; + } + + @Override + public PsiElement getElement() { + return myReference.getElement(); + } + + @Override + public TextRange getRangeInElement() { + return myReference.getRangeInElement(); + } + + @Nullable + @Override + public PsiElement resolve() { + return myReference.resolve(); + } + + @NotNull + public String getCanonicalText() { + return myReference.getCanonicalText(); + } + + public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { + String oldText = ((XmlTag)myPosition).getName(); + final TextRange range = getRangeInElement(); + final String newText = + oldText.substring(0, range.getStartOffset() - 1) + newElementName + oldText.substring(range.getEndOffset() - 1); + return ((XmlTag)myPosition).setName(newText); + } + + public PsiElement bindToElement(@NotNull PsiElement element) + throws IncorrectOperationException { + String oldText = ((XmlTag)myPosition).getName(); + final TextRange range = getRangeInElement(); + final String newText = ((PsiPackage)element).getQualifiedName() + + oldText.substring(range.getEndOffset() - 1); + return ((XmlTag)myPosition).setName(newText); + } + + public boolean isReferenceTo(PsiElement element) { + return myReference.isReferenceTo(element); + } + + @NotNull + public Object[] getVariants() { + return myReference.getVariants(); + } + + public boolean isSoft() { + return true; + } + } + } }