diff options
author | Tor Norbye <tnorbye@google.com> | 2013-08-23 08:59:39 -0700 |
---|---|---|
committer | Tor Norbye <tnorbye@google.com> | 2013-08-23 09:01:04 -0700 |
commit | 926bc53d2e5f6a9f66c98baa1624ad809edb1456 (patch) | |
tree | d33f240d802ad99c2222c8a7f30ebf83f9c3de33 /plugins | |
parent | ce0245dfc4d045479a910a98a0f8655e1ed1419a (diff) | |
download | idea-926bc53d2e5f6a9f66c98baa1624ad809edb1456.tar.gz |
Snapshot c27b4f50fbcb2a71ca2c7f2d85e67debfea58f27 from master branch of git://git.jetbrains.org/idea/community.git
c27b4f5: 2013-08-23 Bas Leijdekkers - don't report on final fields because those will already be highlighted as error
3422c86: 2013-08-23 Alexey Kudravtsev - stress gc to force collection
6ab46dc: 2013-08-23 nik - jps model: serialization for custom module source roots
ab676f6: 2013-08-23 Alexey Kudravtsev - Merge remote-tracking branch 'origin/master'
6e02b38: 2013-08-23 Anna Kozlova - Merge remote-tracking branch 'origin/master'
c0c7f84: 2013-08-23 Maxim.Mossienko - fixed typo
832256e: 2013-08-23 Anna Kozlova - extract enum: ensure normalized fields (IDEA-112590)
d0fb95d: 2013-08-23 Anna Kozlova - override/implement: allow members to be in primary/secondary sets at the same time - filter them from the result; preselect first element when no selection was set before (IDEA-112563)
09e8df0: 2013-08-23 Anna Kozlova - IDEA-112551 "Expand lambda" does not add imports
f095c6d: 2013-08-23 nik - deprecated methods and classes removed from API
eab9f6d: 2013-08-23 Roman Shevchenko - Restore Windows FS loading for tests
b68f03b: 2013-08-23 Alexey Kudravtsev - sometimes weak references are not collected under linux, try to stress gc to force them
d005b15: 2013-08-23 Sergey Evdokimov - EA-48997 - UOE: MvcFramework.addJavaHome
67c6b67: 2013-08-23 Roman Shevchenko - Typo
ee9f323: 2013-08-23 Sergey Evdokimov - EA-48888 - NPE: MavenModelPropertiesPatcher.patch
3a303b4: 2013-08-23 Gregory.Shrago - move Editor-based cell renderer to platform
40d766c: 2013-08-23 Sergey Simonchik - WEB-1887 Error run node from command window
295a5d8: 2013-08-23 Alexey Kudravtsev - cleanup
06a1d59: 2013-08-23 Alexey Kudravtsev - renamed
6b35c9d: 2013-08-23 Roman Shevchenko - test diagnostic
3f7e6c6: 2013-08-23 Roman Shevchenko - platform: unified loading of system libraries
d0b8432: 2013-08-22 Roman Shevchenko - platform: URL class loader builder
2a785d2: 2013-08-22 Roman Shevchenko - platform: class cache logging centralized; obsolete timing dropped
1dc531f: 2013-08-22 Roman Shevchenko - platform: typos and cleanup
a2e1fb4: 2013-08-23 Oleg Sukhodolsky - RUBY-14033: setShowFlattenMode() propagated to ChangesViewI so we could you it
52bffa9: 2013-08-23 Mikhail Golubev - Merge remote-tracking branch 'origin/master'
766a3a0: 2013-08-23 nik - manifest extensions extracted to separate file and moved to 'manifest' module so tests which don't depend on manifest support won't try to load its extensions
0d23c76: 2013-08-23 nik - remote servers: java-dependent classes extracted to separate modules
268559e: 2013-08-23 nik - set 'test' scope for dependencies on testFramework
524db30: 2013-08-22 nik - use API instead of impl
8d7b831: 2013-08-23 Dmitry Avdeev - IDEA-60895 No completion for enumerated and boolean values of xml tags: XmlEnumerationDescriptor introduced
58b6aca: 2013-08-22 Bas Leijdekkers - Respect code style "Use fully qualified names in javadoc" setting (for IDEA-111023)
23338f1: 2013-08-22 Max Medvedev - fix test data
3e6b3ff: 2013-08-22 Sergey Simonchik - One big read lock is splitted into several small read locks. WEB-8936 Karma: read access throwable exception for Coverage (attempt#2)
425a1e0: 2013-08-22 Anna Kozlova - avoid warnings on super abstract methods that they try to assign weaker access (IDEA-67584)
5ee69d4: 2013-08-22 Anna Kozlova - check overridden methods with different type params numbers for thrown exceptions (IDEA-67860)
1c787f1: 2013-08-22 Max Medvedev - IDEA-111192 Groovy: In-Place Introduce Field: Throwable GrIntroduceHandlerBase$4$1.run()
5130a52: 2013-08-22 Max Medvedev - Groovy: shorten references in completed types in templates
2004de2: 2013-08-22 Max Medvedev - Groovy: correct type template for introduce variable
e8c1b32: 2013-08-22 Max Medvedev - shorten references in completed type elements in groovy files
ffcc5d1: 2013-08-22 Bas Leijdekkers - IDEA-47151 (Settings of "Result of method call ignored" inspection should have choosers and/or completion for class and method names)
a4d1018: 2013-08-22 Gregory.Shrago - EA-48983 - E: SwingUtilities.convertPoint
a3b7858: 2013-08-22 peter - completion should insert qualified names in javadoc according to the code style settings (IDEA-111023)
3182137: 2013-08-22 Dmitry Trofimov - Updated libs.
fb1408a: 2013-08-22 Dmitry Trofimov - Merge remote-tracking branch 'origin/master'
ec043d6: 2013-08-22 Denis Fokin - IDEA-112130 Cannot type '{', '}' and '>' in editor when using a Czech keyboard
a4b1aec: 2013-08-22 Dmitry Trofimov - Draw image override.
64059a6: 2013-08-22 Dmitry Trofimov - Action handling fixed.
471882a: 2013-08-22 Dmitry Avdeev - IDEA-112519 Do not check enumerated xml attribute value in case of injection
cc07980: 2013-08-22 peter - correct javadoc completion test
6b486fd: 2013-08-22 Dmitry Avdeev - IDEA-64561 Provide navigation for XSD enum values: fix RNG
fc9843e: 2013-08-22 Mikhail Golubev - IDEA-110012 Not all Redmine Issues Available on "Open Task" (Limited to 100?)
b37c6d0: 2013-08-22 Maxim.Mossienko - do check cancelled during building file map / scanning file
1ff158b: 2013-08-22 Dmitry Trofimov - Fixed font selection.
48580bd: 2013-08-22 Dmitry Trofimov - Merge remote-tracking branch 'origin/master'
e622120: 2013-08-22 Dmitry Trofimov - Updated lib.
814a6ac: 2013-08-22 Bas Leijdekkers - separate warning for constructors
81ff306: 2013-08-22 Maxim.Mossienko - synchronized collection
cc869b4: 2013-08-22 Mikhail Golubev - Remove unused method
7e971f2: 2013-08-22 Maxim.Mossienko - proper caret position update on bulk mode end
b2b87f5: 2013-08-22 Mikhail Golubev - Adjust completion to suggest variants not only on word boundaries
9d36545: 2013-08-22 Anton Makeev - Platform: restrict initial frame size to reasonable value (IDEA-96644) +review CR-IC @kb
9758bfe: 2013-08-22 Bas Leijdekkers - IDEA-112442 (False positive 'Result of method call ignored')
fa1879e: 2013-08-22 Dmitry Avdeev - IDEA-64561 Provide navigation for XSD enum values
6ec1eb8: 2013-08-22 Dmitry Batkovich - CompilerOutputIndexer is enabled only in corresponding tests
e33a3e8: 2013-08-22 Mikhail Golubev - Use JPasswordTextField for rendering values of hidden template variables
2405d26: 2013-08-22 Dmitry Avdeev - IDEA-64561 Provide navigation for XSD enum values: documentation
0aafeeb: 2013-08-22 Mikhail Golubev - Add EditorTextField as cell editor in HighlightedSelectorsTable
e38a6a3: 2013-08-22 Nadya Zabrodina - Cosmetics
2ef0358: 2013-08-22 Evgeny Pasynkov - +prepend(byte, byte[])
74932df: 2013-08-22 Denis Fokin - IDEA-108265. Multiple recent tasks at once could be provided. Minor issues are fixed. AppId is now one per process.
4860452: 2013-08-22 Mikhail Golubev - Merge remote-tracking branch 'origin/master'
bc29214: 2013-08-22 Oleg Sukhodolsky - testFramework should not depend on remote-servers-impl (which depends on testFramework-java)
1b24edc: 2013-08-22 Roman Shevchenko - CR-IC-2008 (mock JRE update)
36e54e9: 2013-08-22 Dmitry Trofimov - Updated libs.
279fd2e: 2013-08-22 Dmitry Trofimov - Use dump aware actions.
d73433c: 2013-08-22 Dmitry Trofimov - Merge remote-tracking branch 'origin/master'
100257e: 2013-08-22 Dmitry Trofimov - Libs updated.
0801a5f: 2013-08-22 Dmitry Trofimov - Use idea action system.
1a172fe: 2013-08-21 Mikhail Golubev - Remove remaining references to selector names via string literals
8330324: 2013-08-21 Mikhail Golubev - Add support of 'Download tasks in separate requests' feature in GenericRepository
0f241d4: 2013-08-21 Dmitry Trofimov - Actions should work while indexing.
38fc2f4: 2013-08-21 Mikhail Golubev - Refactored common handlers functionality to SelectorBasedResponse Handler. Add max parameter support to JsonPath and Regex response handlers.
98fb926: 2013-08-21 Dmitry Trofimov - Don't close tab on remote terminal logout.
e4d5ad3: 2013-08-21 Mikhail Golubev - Results number limiting in GenericRepository and ResponseHandlers
ec92ca6: 2013-08-21 Mikhail Golubev - NotNull check in TaskManagerImpl
0b9e2be: 2013-08-21 Mikhail Golubev - Update XPathResponseHandler: add lazy XPath expressions compiling, make selectors names constants
1614c5d: 2013-08-21 Dmitry Trofimov - Hide terminal view on last tab close.
e49aa6c: 2013-08-20 Mikhail Golubev - Merge branch 'generic'
d9fc248: 2013-08-20 Mikhail Golubev - Update response handlers of GenericRepository
Change-Id: I84fdb10c62c68bfcd45967e9fdc4245052c31928
Diffstat (limited to 'plugins')
78 files changed, 852 insertions, 597 deletions
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties index 694189a8ad01..f62b033c85c8 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties @@ -2034,4 +2034,6 @@ inner.class.referenced.via.subclass.quickfix=Rationalize inner class access boolean.parameter.display.name='public' method with 'boolean' parameter boolean.parameter.problem.descriptor='public' method <code>#ref</code> with 'boolean' parameter boolean.parameters.problem.descriptor='public' method <code>#ref</code> with 'boolean' parameters +boolean.parameter.constructor.problem.descriptor='public' constructor <code>#ref</code> with 'boolean' parameter +boolean.parameters.constructor.problem.descriptor='public' constructor <code>#ref</code> with 'boolean' parameters boolean.parameter.only.report.multiple.option=Only report methods with multiple boolean parameters
\ No newline at end of file diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/BooleanParameterInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/BooleanParameterInspection.java index 5513f421793b..d328f49b1cbf 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/BooleanParameterInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/BooleanParameterInspection.java @@ -45,11 +45,17 @@ public class BooleanParameterInspection extends BaseInspection { @NotNull @Override protected String buildErrorString(Object... infos) { - if (((Integer)infos[0]).intValue() == 1) { - return InspectionGadgetsBundle.message("boolean.parameter.problem.descriptor"); + final PsiMethod method = (PsiMethod)infos[0]; + final int booleanParameterCount = ((Integer)infos[1]).intValue(); + if (booleanParameterCount == 1) { + return method.isConstructor() + ? InspectionGadgetsBundle.message("boolean.parameter.constructor.problem.descriptor") + : InspectionGadgetsBundle.message("boolean.parameter.problem.descriptor"); } else { - return InspectionGadgetsBundle.message("boolean.parameters.problem.descriptor"); + return method.isConstructor() + ? InspectionGadgetsBundle.message("boolean.parameters.constructor.problem.descriptor") + : InspectionGadgetsBundle.message("boolean.parameters.problem.descriptor"); } } @@ -96,7 +102,7 @@ public class BooleanParameterInspection extends BaseInspection { if (count == 0 || onlyReportMultiple && count == 1) { return; } - registerMethodError(method, Integer.valueOf(count)); + registerMethodError(method, method, Integer.valueOf(count)); } } } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionBase.java index 7e197d9a167d..da52a98e6d70 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspectionBase.java @@ -47,17 +47,28 @@ public class IgnoreResultOfCallInspectionBase extends BaseInspection { /** * @noinspection PublicField */ - @NonNls public String callCheckString = "java.io.InputStream,read," + - "java.io.InputStream,skip," + - "java.lang.StringBuffer,toString," + - "java.lang.StringBuilder,toString," + + @NonNls public String callCheckString = "java.io.File,.*," + + "java.io.InputStream,read|skip|available|markSupported," + + "java.io.Writer,read|skip|ready|markSupported," + + "java.lang.Boolean,.*," + + "java.lang.Byte,.*," + + "java.lang.Character,.*," + + "java.lang.Double,.*," + + "java.lang.Float,.*," + + "java.lang.Integer,.*," + + "java.lang.Long,.*," + + "java.lang.Math,.*," + + "java.lang.Object,equals|hashCode|toString," + + "java.lang.Short,.*," + + "java.lang.StrictMath,.*," + "java.lang.String,.*," + "java.math.BigInteger,.*," + "java.math.BigDecimal,.*," + "java.net.InetAddress,.*," + - "java.io.File,.*," + - "java.lang.Object,equals|hashCode," + - "java.util.regex.Matcher,.*"; + "java.net.URI,.*," + + "java.util.UUID,.*," + + "java.util.regex.Matcher,pattern|toMatchResult|start|end|group|groupCount|matches|find|lookingAt|quoteReplacement|replaceAll|replaceFirst|regionStart|regionEnd|hasTransparantBounds|hasAnchoringBounds|hitEnd|requireEnd," + + "java.util.regex.Pattern,.*"; Map<String, Pattern> patternCache = null; public IgnoreResultOfCallInspectionBase() { diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/initialization/StaticVariableInitializationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/initialization/StaticVariableInitializationInspection.java index 9886f1c01c57..a1497d80c46d 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/initialization/StaticVariableInitializationInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/initialization/StaticVariableInitializationInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2009 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,22 +44,18 @@ public class StaticVariableInitializationInspection extends BaseInspection { @Override @NotNull public String getDisplayName() { - return InspectionGadgetsBundle.message( - "static.variable.may.not.be.initialized.display.name"); + return InspectionGadgetsBundle.message("static.variable.may.not.be.initialized.display.name"); } @Override @NotNull public String buildErrorString(Object... infos) { - return InspectionGadgetsBundle.message( - "static.variable.may.not.be.initialized.problem.descriptor"); + return InspectionGadgetsBundle.message("static.variable.may.not.be.initialized.problem.descriptor"); } @Override public JComponent createOptionsPanel() { - return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message( - "primitive.fields.ignore.option"), - this, "m_ignorePrimitives"); + return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("primitive.fields.ignore.option"), this, "m_ignorePrimitives"); } @Override @@ -77,17 +73,14 @@ public class StaticVariableInitializationInspection extends BaseInspection { @Override public void visitField(@NotNull PsiField field) { - if (!field.hasModifierProperty(PsiModifier.STATIC)) { + if (!field.hasModifierProperty(PsiModifier.STATIC) || field.hasModifierProperty(PsiModifier.FINAL)) { return; } if (field.getInitializer() != null) { return; } final PsiClass containingClass = field.getContainingClass(); - if (containingClass == null) { - return; - } - if (containingClass.isEnum()) { + if (containingClass == null || containingClass.isEnum()) { return; } if (m_ignorePrimitives) { @@ -96,15 +89,14 @@ public class StaticVariableInitializationInspection extends BaseInspection { return; } } - final PsiClassInitializer[] initializers = - containingClass.getInitializers(); + final PsiClassInitializer[] initializers = containingClass.getInitializers(); for (final PsiClassInitializer initializer : initializers) { - if (initializer.hasModifierProperty(PsiModifier.STATIC)) { - final PsiCodeBlock body = initializer.getBody(); - if (InitializationUtils.blockAssignsVariableOrFails(body, - field)) { - return; - } + if (!initializer.hasModifierProperty(PsiModifier.STATIC)) { + continue; + } + final PsiCodeBlock body = initializer.getBody(); + if (InitializationUtils.blockAssignsVariableOrFails(body, field)) { + return; } } registerFieldError(field); diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspection.java index 25f84464e89c..6360ab864427 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/bugs/IgnoreResultOfCallInspection.java @@ -26,8 +26,8 @@ import java.awt.*; import java.util.Arrays; public class IgnoreResultOfCallInspection extends IgnoreResultOfCallInspectionBase { - public IgnoreResultOfCallInspection() { - } + + public IgnoreResultOfCallInspection() {} @Override public JComponent createOptionsPanel() { @@ -35,7 +35,7 @@ public class IgnoreResultOfCallInspection extends IgnoreResultOfCallInspectionBa final ListTable table = new ListTable(new ListWrappingTableModel( Arrays.asList(classNames, methodNamePatterns), InspectionGadgetsBundle.message("result.of.method.call.ignored.class.column.title"), InspectionGadgetsBundle.message("result.of.method.call.ignored.method.column.title"))); - final JPanel tablePanel = UiUtils.createAddRemovePanel(table); + final JPanel tablePanel = UiUtils.createAddRemoveTreeClassChooserPanel(table, "Choose class"); final CheckBox checkBox = new CheckBox(InspectionGadgetsBundle.message("result.of.method.call.ignored.non.library.option"), this, "m_reportAllNonLibraryCalls"); panel.add(tablePanel, BorderLayout.CENTER); diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/initialization/InstanceVariableUninitializedUseInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/initialization/InstanceVariableUninitializedUseInspection.java index 8ff9de4b03d3..0e3ddd3a8723 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/initialization/InstanceVariableUninitializedUseInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/initialization/InstanceVariableUninitializedUseInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -129,7 +129,7 @@ public class InstanceVariableUninitializedUseInspection extends BaseInspection { @Override public void visitField(@NotNull PsiField field) { - if (field.hasModifierProperty(PsiModifier.STATIC)) { + if (field.hasModifierProperty(PsiModifier.STATIC) || field.hasModifierProperty(PsiModifier.FINAL)) { return; } if (field.getInitializer() != null) { diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspection.java index bdbfa99c99ce..de8c3bd65b78 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -76,17 +76,16 @@ public class TestMethodWithoutAssertionInspection extends BaseInspection { @Override @NotNull protected String buildErrorString(Object... infos) { - return InspectionGadgetsBundle.message( - "test.method.without.assertion.problem.descriptor"); + return InspectionGadgetsBundle.message("test.method.without.assertion.problem.descriptor"); } @Override public JComponent createOptionsPanel() { final JPanel panel = new JPanel(new BorderLayout()); final ListTable table = new ListTable( - new ListWrappingTableModel(Arrays.asList(classNames, methodNamePatterns), InspectionGadgetsBundle.message("class.name"), + new ListWrappingTableModel(Arrays.asList(classNames, methodNamePatterns), "Assertion class name", InspectionGadgetsBundle.message("method.name.pattern"))); - final JPanel tablePanel = UiUtils.createAddRemovePanel(table); + final JPanel tablePanel = UiUtils.createAddRemoveTreeClassChooserPanel(table, "Choose assertion class"); final CheckBox checkBox = new CheckBox(InspectionGadgetsBundle.message("assert.keyword.is.considered.an.assertion"), this, "assertKeywordIsAssertion"); panel.add(tablePanel, BorderLayout.CENTER); diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspection.java index 37619fedf9f3..e279a7a0070d 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2012 Bas Leijdekkers + * Copyright 2008-2013 Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -72,7 +72,7 @@ public class LoggerInitializedWithForeignClassInspection extends BaseInspection new ListWrappingTableModel(Arrays.asList(loggerFactoryClassNames, loggerFactoryMethodNames), InspectionGadgetsBundle.message("logger.factory.class.name"), InspectionGadgetsBundle.message("logger.factory.method.name"))); - return UiUtils.createAddRemovePanel(table); + return UiUtils.createAddRemoveTreeClassChooserPanel(table, "Choose logger factory class"); } @Override @@ -92,9 +92,7 @@ public class LoggerInitializedWithForeignClassInspection extends BaseInspection @Override @NotNull public String getName() { - return InspectionGadgetsBundle.message( - "logger.initialized.with.foreign.class.quickfix", - newClassName); + return InspectionGadgetsBundle.message("logger.initialized.with.foreign.class.quickfix", newClassName); } @NotNull @@ -130,7 +128,7 @@ public class LoggerInitializedWithForeignClassInspection extends BaseInspection if (!expression.equals(referenceExpression.getQualifierExpression())) { return; } - final String name = referenceExpression.getReferenceName(); + @NonNls final String name = referenceExpression.getReferenceName(); if (!"getName".equals(name)) { return; } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java index 7f8c7246a500..a9b44ac06699 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryFullyQualifiedNameInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2013 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ package com.siyeh.ig.style; import com.intellij.codeInspection.ProblemDescriptor; -import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.wm.StatusBar; @@ -35,19 +34,18 @@ import com.siyeh.ig.psiutils.HighlightUtils; import com.siyeh.ig.psiutils.ImportUtils; import org.jetbrains.annotations.NotNull; -import javax.swing.*; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; /** - * com.siyeh.ipp.fqnames.ReplaceFullyQualifiedNameWithImportIntention + * @see com.siyeh.ipp.fqnames.ReplaceFullyQualifiedNameWithImportIntention */ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection { @SuppressWarnings("PublicField") - public boolean m_ignoreJavadoc = false; + public boolean m_ignoreJavadoc = false; // left here to prevent changes to project files. @Override @NotNull @@ -56,12 +54,6 @@ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection { } @Override - public JComponent createOptionsPanel() { - return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("unnecessary.fully.qualified.name.ignore.option"), - this, "m_ignoreJavadoc"); - } - - @Override @NotNull public String buildErrorString(Object... infos) { final boolean inSameFile = ((Boolean)infos[0]).booleanValue(); @@ -183,7 +175,7 @@ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection { return new UnnecessaryFullyQualifiedNameVisitor(); } - private class UnnecessaryFullyQualifiedNameVisitor extends BaseInspectionVisitor { + private static class UnnecessaryFullyQualifiedNameVisitor extends BaseInspectionVisitor { @Override public void visitReferenceExpression(PsiReferenceExpression expression) { @@ -211,7 +203,8 @@ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection { if (element != null) { return; } - if (m_ignoreJavadoc) { + final CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(reference.getProject()); + if (styleSettings.USE_FQ_CLASS_NAMES_IN_JAVADOC) { final PsiElement containingComment = PsiTreeUtil.getParentOfType(reference, PsiDocComment.class); if (containingComment != null) { return; @@ -232,7 +225,6 @@ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection { } final List<PsiJavaCodeReferenceElement> references = new ArrayList(2); references.add(reference); - final CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(reference.getProject()); if (styleSettings.INSERT_INNER_CLASS_IMPORTS) { collectInnerClassNames(reference, references); } @@ -257,7 +249,7 @@ public class UnnecessaryFullyQualifiedNameInspection extends BaseInspection { } } - private void collectInnerClassNames(PsiJavaCodeReferenceElement reference, List<PsiJavaCodeReferenceElement> references) { + private static void collectInnerClassNames(PsiJavaCodeReferenceElement reference, List<PsiJavaCodeReferenceElement> references) { PsiElement rParent = reference.getParent(); while (rParent instanceof PsiJavaCodeReferenceElement) { final PsiJavaCodeReferenceElement parentReference = (PsiJavaCodeReferenceElement)rParent; diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/ui/UiUtils.java b/plugins/InspectionGadgets/src/com/siyeh/ig/ui/UiUtils.java index fb7b8dab1738..0adb02b76f42 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/ui/UiUtils.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/ui/UiUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2011 Bas Leijdekkers + * Copyright 2010-2013 Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,13 +41,6 @@ public class UiUtils { private UiUtils() { } - public static void setScrollPaneSize(JScrollPane scrollPane, int rows, int columns) { - final Component view = scrollPane.getViewport().getView(); - final FontMetrics fontMetrics = view.getFontMetrics(view.getFont()); - final int width = fontMetrics.charWidth('m') * columns; - scrollPane.setPreferredSize(new Dimension(width, fontMetrics.getHeight() * rows)); - } - public static void setComponentSize(Component component, int rows, int columns) { final FontMetrics fontMetrics = component.getFontMetrics(component.getFont()); final int width = fontMetrics.charWidth('m') * columns; @@ -65,14 +58,7 @@ public class UiUtils { @Override public void run() { final int lastRowIndex = tableModel.getRowCount() - 1; - final Rectangle rectangle = table.getCellRect(lastRowIndex, 0, true); - table.scrollRectToVisible(rectangle); - table.editCellAt(lastRowIndex, 0); - final ListSelectionModel selectionModel = table.getSelectionModel(); - selectionModel.setSelectionInterval(lastRowIndex, lastRowIndex); - final TableCellEditor editor = table.getCellEditor(); - final Component component = editor.getTableCellEditorComponent(table, null, true, lastRowIndex, 0); - component.requestFocus(); + editTableCell(table, lastRowIndex, 0); } }); } @@ -80,8 +66,7 @@ public class UiUtils { .disableUpDownActions().createPanel(); } - public static JPanel createAddRemoveTreeClassChooserPanel(final ListTable table, - final String chooserTitle, + public static JPanel createAddRemoveTreeClassChooserPanel(final ListTable table, final String chooserTitle, @NonNls String... ancestorClasses) { final ClassFilter filter; if (ancestorClasses.length == 0) { @@ -96,43 +81,55 @@ public class UiUtils { public void run(AnActionButton button) { final DataContext dataContext = DataManager.getInstance().getDataContext(table); final Project project = PlatformDataKeys.PROJECT.getData(dataContext); - if (project == null) { - return; - } - final TreeClassChooserFactory chooserFactory = TreeClassChooserFactory.getInstance(project); - final TreeClassChooser classChooser = - chooserFactory.createWithInnerClassesScopeChooser(chooserTitle, GlobalSearchScope.allScope(project), filter, null); - classChooser.showDialog(); - final PsiClass selectedClass = classChooser.getSelected(); - if (selectedClass == null) { - return; - } - final String qualifiedName = selectedClass.getQualifiedName(); - final ListWrappingTableModel tableModel = table.getModel(); - final int index = tableModel.indexOf(qualifiedName, 0); final int rowIndex; - if (index < 0) { - tableModel.addRow(qualifiedName); + final ListWrappingTableModel tableModel = table.getModel(); + if (project == null) { + tableModel.addRow(); rowIndex = tableModel.getRowCount() - 1; } else { - rowIndex = index; - } - final ListSelectionModel selectionModel = - table.getSelectionModel(); - selectionModel.setSelectionInterval(rowIndex, rowIndex); - EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - final Rectangle rectangle = table.getCellRect(rowIndex, 0, true); - table.scrollRectToVisible(rectangle); + final TreeClassChooserFactory chooserFactory = TreeClassChooserFactory.getInstance(project); + final TreeClassChooser classChooser = + chooserFactory.createWithInnerClassesScopeChooser(chooserTitle, GlobalSearchScope.allScope(project), filter, null); + classChooser.showDialog(); + final PsiClass selectedClass = classChooser.getSelected(); + if (selectedClass == null) { + return; } - }); + final String qualifiedName = selectedClass.getQualifiedName(); + final int index = tableModel.indexOf(qualifiedName, 0); + if (index < 0) { + tableModel.addRow(qualifiedName); + rowIndex = tableModel.getRowCount() - 1; + } + else { + rowIndex = index; + } + } + editTableCell(table, rowIndex, table.getColumnCount() > 1 && project != null ? 1 : 0); } }).setRemoveAction(new RemoveAction(table)) .disableUpDownActions().createPanel(); } + private static void editTableCell(final ListTable table, final int row, final int column) { + final ListSelectionModel selectionModel = table.getSelectionModel(); + selectionModel.setSelectionInterval(row, row); + EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + final ListWrappingTableModel tableModel = table.getModel(); + table.requestFocus(); + final Rectangle rectangle = table.getCellRect(row, column, true); + table.scrollRectToVisible(rectangle); + table.editCellAt(row, column); + final TableCellEditor editor = table.getCellEditor(); + final Component component = editor.getTableCellEditorComponent(table, tableModel.getValueAt(row, column), true, row, column); + component.requestFocus(); + } + }); + } + public static JPanel createTreeClassChooserList(final Collection<String> collection, String borderTitle, final String chooserTitle, @@ -179,8 +176,7 @@ public class UiUtils { .setRemoveAction(new AnActionButtonRunnable() { @Override public void run(AnActionButton anActionButton) { - final Object selectedValue = list.getSelectedValue(); - collection.remove(selectedValue); + collection.remove(list.getSelectedValue()); ListUtil.removeSelectedItems(list); } }).createPanel(); diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/UnnecessaryFullyQualifiedName.html b/plugins/InspectionGadgets/src/inspectionDescriptions/UnnecessaryFullyQualifiedName.html index 874c4107ba4b..0ee3585affe9 100644 --- a/plugins/InspectionGadgets/src/inspectionDescriptions/UnnecessaryFullyQualifiedName.html +++ b/plugins/InspectionGadgets/src/inspectionDescriptions/UnnecessaryFullyQualifiedName.html @@ -4,6 +4,8 @@ Reports on fully qualified class names which can be shortened. The quick fix for inspection will shorten the fully qualified names, adding import statements as necessary. <!-- tooltip end --> <p> - +In <code>Settings | Code Style | Java | Imports</code> two settings can be found which influence this inspection. +Use the settings there to specify if references to inner classes +should be qualified with the outer class and if fully qualified names are allowed in javadoc. </body> </html>
\ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/instance_variable_uninitialized_use/InstanceVariableUninitializedUse.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/instance_variable_uninitialized_use/InstanceVariableUninitializedUse.java index 58d468da93f0..f43884c69be6 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/instance_variable_uninitialized_use/InstanceVariableUninitializedUse.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/instance_variable_uninitialized_use/InstanceVariableUninitializedUse.java @@ -24,5 +24,12 @@ class InstanceFieldVsDoWhile { object = new Object(); } while (object.hashCode() < 1000); // Instance field used before initialization } +} +class FinalField { + private final Object object; -}
\ No newline at end of file + FinalField() { + System.out.println(object); + object = null; + } +} diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/static_variable_initialization/StaticVariableInitializationInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/static_variable_initialization/StaticVariableInitializationInspection.java index eb8714e964f1..85385b8dd8b6 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/static_variable_initialization/StaticVariableInitializationInspection.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/static_variable_initialization/StaticVariableInitializationInspection.java @@ -36,3 +36,11 @@ public class StaticVariableInitializationInspection } } } +class FinalField { + public static final Object o; + + static { + System.out.println("o = " + o); + o = null; + } +} diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/BooleanParameterInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/BooleanParameterInspectionTest.java index 486037702326..b0c134fc7ca8 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/BooleanParameterInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/BooleanParameterInspectionTest.java @@ -32,6 +32,12 @@ public class BooleanParameterInspectionTest extends LightInspectionTestCase { "}"); } + public void testConstructor() { + doTest("class X {" + + " public /*'public' constructor 'X' with 'boolean' parameter*/X/**/(boolean x) {}" + + "}"); + } + @Override protected LocalInspectionTool getInspection() { return new BooleanParameterInspection(); diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/resources/JDBCResourceInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/resources/JDBCResourceInspectionTest.java index d834557e401b..cf5f1d7aa1ae 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/resources/JDBCResourceInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/resources/JDBCResourceInspectionTest.java @@ -38,25 +38,23 @@ public class JDBCResourceInspectionTest extends LightInspectionTestCase { } public void testARM() { - // doesn't work with mock jdk - /*doTest("import java.sql.*;" + - "class X {" + - " void m(Driver driver) throws SQLException {" + - " try (Connection connection = driver.connect(\"asdf\", null);" + - " PreparedStatement statement = connection.prepareStatement(\"SELECT *\");" + - " ResultSet resultSet = statement.executeQuery()) {" + - " while (resultSet.next()) {" + - " }" + - " }" + - " }" + - "}");*/ + doTest("import java.sql.*;\n" + + "class X {\n" + + " void m(Driver driver) throws SQLException {\n" + + " try (Connection connection = driver.connect(\"jdbc\", null);\n" + + " PreparedStatement statement = connection.prepareStatement(\"SELECT *\");\n" + + " ResultSet resultSet = statement.executeQuery()) {\n" + + " while (resultSet.next()) { resultSet.getMetaData(); }\n" + + " }\n" + + " }\n" + + "}"); } public void testSimple() { doTest("import java.sql.*;" + "class X {" + " void m(Driver driver) throws SQLException {" + - " /*'Connection' should be opened in front of a 'try' block and closed in the corresponding 'finally' block*/driver.connect(\"asdf\", null)/**/;" + + " /*'Connection' should be opened in front of a 'try' block and closed in the corresponding 'finally' block*/driver.connect(\"jdbc\", null)/**/;" + " }" + "}"); } diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/InferLambdaParameterTypeIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/InferLambdaParameterTypeIntention.java index 9e9658f0f354..ca1dc575fe1b 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/InferLambdaParameterTypeIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/InferLambdaParameterTypeIntention.java @@ -16,7 +16,9 @@ package com.siyeh.ipp.types; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.IncorrectOperationException; @@ -46,13 +48,14 @@ public class InferLambdaParameterTypeIntention extends Intention { final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class); LOG.assertTrue(lambdaExpression != null); final PsiType functionalInterfaceType = lambdaExpression.getFunctionalInterfaceType(); - final String buf = getInferredTypes(functionalInterfaceType, lambdaExpression); - lambdaExpression.getParameterList().replace(JavaPsiFacade.getElementFactory(element.getProject()).createMethodFromText("void foo" + buf, - element).getParameterList()); + final String buf = getInferredTypes(functionalInterfaceType, lambdaExpression, true); + final Project project = element.getProject(); + final PsiMethod methodFromText = JavaPsiFacade.getElementFactory(project).createMethodFromText("void foo" + buf, element); + JavaCodeStyleManager.getInstance(project).shortenClassReferences(lambdaExpression.getParameterList().replace(methodFromText.getParameterList())); } @Nullable - private static String getInferredTypes(PsiType functionalInterfaceType, final PsiLambdaExpression lambdaExpression) { + private static String getInferredTypes(PsiType functionalInterfaceType, final PsiLambdaExpression lambdaExpression, boolean useFQN) { final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType); final StringBuilder buf = new StringBuilder(); buf.append("("); @@ -65,7 +68,7 @@ public class InferLambdaParameterTypeIntention extends Intention { PsiParameter parameter = parameters[i]; final PsiType psiType = GenericsUtil.eliminateWildcards(LambdaUtil.getSubstitutor(interfaceMethod, resolveResult).substitute(parameter.getType())); if (psiType != null) { - buf.append(psiType.getPresentableText()).append(" ").append(lambdaParameters[i].getName()); + buf.append(useFQN ? psiType.getCanonicalText() : psiType.getPresentableText()).append(" ").append(lambdaParameters[i].getName()); } else { buf.append(lambdaParameters[i].getName()); @@ -94,7 +97,7 @@ public class InferLambdaParameterTypeIntention extends Intention { if (PsiTreeUtil.isAncestor(lambdaExpression.getParameterList(), element, false)) { final PsiType functionalInterfaceType = lambdaExpression.getFunctionalInterfaceType(); if (functionalInterfaceType != null && LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType) != null && LambdaUtil.isLambdaFullyInferred(lambdaExpression, functionalInterfaceType)) { - myInferredTypesText = getInferredTypes(functionalInterfaceType, lambdaExpression); + myInferredTypesText = getInferredTypes(functionalInterfaceType, lambdaExpression, false); return myInferredTypesText != null; } } diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/inferLambdaParameterType/File.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/inferLambdaParameterType/File.java new file mode 100644 index 000000000000..d6536bdca71c --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/inferLambdaParameterType/File.java @@ -0,0 +1,5 @@ +class X { + { + Comparable<java.io.File> c = <caret>o -> 1; + } +} diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/inferLambdaParameterType/File_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/inferLambdaParameterType/File_after.java new file mode 100644 index 000000000000..d99ddf4dccdc --- /dev/null +++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/inferLambdaParameterType/File_after.java @@ -0,0 +1,7 @@ +import java.io.File; + +class X { + { + Comparable<java.io.File> c = (File o) -> 1; + } +} diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/InferLambdaParameterTypeIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/InferLambdaParameterTypeIntentionTest.java index 94bf41b59cb7..6253144de70f 100644 --- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/InferLambdaParameterTypeIntentionTest.java +++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/InferLambdaParameterTypeIntentionTest.java @@ -23,6 +23,10 @@ public class InferLambdaParameterTypeIntentionTest extends IPPTestCase { doTest("Expand lambda to (String o) -> {...}"); } + public void testFile() { + doTest("Expand lambda to (File o) -> {...}"); + } + public void testTwoParams() { doTest("Expand lambda to (String o1, String o2) -> {...}"); } diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntInstallation.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntInstallation.java index 3b4a28971f13..f07283b52347 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntInstallation.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntInstallation.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -30,7 +30,6 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; -import java.util.Collections; import java.util.Comparator; import java.util.Properties; @@ -117,11 +116,11 @@ public class AntInstallation { public String getVersion() { return VERSION.get(myProperties); } - + public String getHomeDir() { return HOME_DIR.get(myProperties); } - + public AbstractProperty.AbstractPropertyContainer getProperties() { return myProperties; } @@ -134,7 +133,7 @@ public class AntInstallation { public void updateClasspath() { myClassLoaderHolder.updateClasspath(); } - + public static AntInstallation fromHome(String homePath) throws ConfigurationException { File antHome = new File(homePath); String antPath = "'" + antHome.getAbsolutePath() + "'"; @@ -166,7 +165,7 @@ public class AntInstallation { Properties properties = new Properties(); InputStream stream = null; try { - stream = new UrlClassLoader(Collections.singletonList(antJar.toURL()), null, false, false, true, false).getResourceAsStream(VERSION_RESOURCE); + stream = UrlClassLoader.build().urls(antJar.toURI().toURL()).allowUnescaped().noPreload().get().getResourceAsStream(VERSION_RESOURCE); properties.load(stream); } catch (MalformedURLException e) { diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntResourcesClassLoader.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntResourcesClassLoader.java index feb9356add33..c5ee60111e04 100644 --- a/plugins/ant/src/com/intellij/lang/ant/config/impl/AntResourcesClassLoader.java +++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/AntResourcesClassLoader.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -31,7 +31,7 @@ public class AntResourcesClassLoader extends UrlClassLoader { private final Set<String> myMisses = new THashSet<String>(); public AntResourcesClassLoader(final List<URL> urls, final ClassLoader parentLoader, final boolean canLockJars, final boolean canUseCache) { - super(urls, parentLoader, canLockJars, canUseCache, true, false); + super(build().urls(urls).parent(parentLoader).allowLock(canLockJars).useCache(canUseCache).allowUnescaped().noPreload()); } protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException { diff --git a/plugins/devkit/src/actions/ShowSerializedXmlAction.java b/plugins/devkit/src/actions/ShowSerializedXmlAction.java index e6280912535c..9de4276ddefb 100644 --- a/plugins/devkit/src/actions/ShowSerializedXmlAction.java +++ b/plugins/devkit/src/actions/ShowSerializedXmlAction.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. @@ -99,9 +99,9 @@ public class ShowSerializedXmlAction extends DumbAwareAction { LOG.info(e1); } } - + final Project project = module.getProject(); - UrlClassLoader loader = new UrlClassLoader(urls, XmlSerializer.class.getClassLoader()); + UrlClassLoader loader = UrlClassLoader.build().urls(urls).parent(XmlSerializer.class.getClassLoader()).get(); final Class<?> aClass; try { aClass = Class.forName(className, true, loader); diff --git a/plugins/google-app-engine/google-app-engine.iml b/plugins/google-app-engine/google-app-engine.iml index ab104003fd25..956452da42a5 100644 --- a/plugins/google-app-engine/google-app-engine.iml +++ b/plugins/google-app-engine/google-app-engine.iml @@ -24,7 +24,7 @@ <orderEntry type="module" module-name="compiler-impl" /> <orderEntry type="module" module-name="dom-openapi" /> <orderEntry type="module" module-name="java-impl" /> - <orderEntry type="module" module-name="remote-servers-api" /> + <orderEntry type="module" module-name="remote-servers-java-api" /> </component> </module> diff --git a/plugins/google-app-engine/source/com/intellij/appengine/cloud/AppEngineCloudType.java b/plugins/google-app-engine/source/com/intellij/appengine/cloud/AppEngineCloudType.java index 5d9207635be7..6ebdc4951ac1 100644 --- a/plugins/google-app-engine/source/com/intellij/appengine/cloud/AppEngineCloudType.java +++ b/plugins/google-app-engine/source/com/intellij/appengine/cloud/AppEngineCloudType.java @@ -130,7 +130,7 @@ public class AppEngineCloudType extends ServerType<AppEngineServerConfiguration> @Override public List<DeploymentSource> getAvailableDeploymentSources() { List<Artifact> artifacts = AppEngineUtil.collectWebArtifacts(myProject, true); - return DeploymentSourceUtil.getInstance().createArtifactDeploymentSources(myProject, artifacts); + return JavaDeploymentSourceUtil.getInstance().createArtifactDeploymentSources(myProject, artifacts); } @NotNull diff --git a/plugins/google-app-engine/source/com/intellij/appengine/sdk/impl/AppEngineSdkUtil.java b/plugins/google-app-engine/source/com/intellij/appengine/sdk/impl/AppEngineSdkUtil.java index 15400345eae1..645c6f7ba2f8 100644 --- a/plugins/google-app-engine/source/com/intellij/appengine/sdk/impl/AppEngineSdkUtil.java +++ b/plugins/google-app-engine/source/com/intellij/appengine/sdk/impl/AppEngineSdkUtil.java @@ -98,7 +98,8 @@ public class AppEngineSdkUtil { public static Map<String, Set<String>> computeWhiteList(final File toolsApiJarFile) { try { final THashMap<String, Set<String>> map = new THashMap<String, Set<String>>(); - ClassLoader loader = new UrlClassLoader(Collections.singletonList(toolsApiJarFile.toURI().toURL()), AppEngineSdkUtil.class.getClassLoader()); + final ClassLoader loader = UrlClassLoader.build().urls(toolsApiJarFile.toURI().toURL()).parent( + AppEngineSdkUtil.class.getClassLoader()).get(); final Class<?> whiteListClass = Class.forName("com.google.apphosting.runtime.security.WhiteList", true, loader); final Set<String> classes = (Set<String>) whiteListClass.getMethod("getWhiteList").invoke(null); for (String qualifiedName : classes) { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradlePositionManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradlePositionManager.java index d01a931cb5a2..771260eb84d8 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradlePositionManager.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradlePositionManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -149,7 +149,7 @@ public class GradlePositionManager extends ScriptPositionManagerHelper { } } - return new UrlClassLoader(urls, null); + return UrlClassLoader.build().urls(urls).get(); } private class ScriptSourceMapCalculator implements CachedValueProvider<FactoryMap<File, String>> { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/AntTasksProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/AntTasksProvider.java index d74aa376831c..d08cd9535062 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/AntTasksProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/AntTasksProvider.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. @@ -144,7 +144,7 @@ public class AntTasksProvider { private final Future<Map<String, Class>> myFuture; public AntClassLoader(ArrayList<URL> urls) { - super(urls, null, false, false, true, false); + super(build().urls(urls).allowUnescaped().noPreload()); myFuture = ApplicationManager.getApplication().executeOnPooledThread(new Callable<Map<String, Class>>() { @Override public Map<String, Class> call() throws Exception { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java index bbbd9a5c363c..2d706a6d08df 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java @@ -25,9 +25,11 @@ import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.ui.NonFocusableCheckBox; import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; -import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SubtypeConstraint; +import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.SupertypeConstraint; import org.jetbrains.plugins.groovy.lang.psi.expectedTypes.TypeConstraint; +import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.refactoring.introduce.GrFinalListener; import org.jetbrains.plugins.groovy.refactoring.introduce.GrInplaceIntroducer; import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext; @@ -99,9 +101,10 @@ public class GrInplaceVariableIntroducer extends GrInplaceIntroducer { protected void addAdditionalVariables(TemplateBuilderImpl builder) { GrVariable variable = getVariable(); assert variable != null; - TypeConstraint[] constraints = {SubtypeConstraint.create(variable.getType())}; + TypeConstraint[] constraints = {SupertypeConstraint.create(variable.getType())}; ChooseTypeExpression typeExpression = new ChooseTypeExpression(constraints, variable.getManager(), true, variable.getResolveScope()); - builder.replaceElement(variable.getTypeElementGroovy(), "Variable_type", typeExpression, true, true); + PsiElement element = variable.getTypeElementGroovy() != null ? variable.getTypeElementGroovy() + : PsiUtil.findModifierInList(variable.getModifierList(), GrModifier.DEF); + builder.replaceElement(element, "Variable_type", typeExpression, true, true); } - } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceLocalVariableProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceLocalVariableProcessor.java index 8c8058a309e5..ff941bec3e06 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceLocalVariableProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceLocalVariableProcessor.java @@ -17,21 +17,22 @@ package org.jetbrains.plugins.groovy.refactoring.introduce.variable; import com.intellij.diagnostic.LogMessageEx; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.*; -import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReference; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.util.PsiUtilCore; import com.intellij.refactoring.util.RefactoringUtil; +import com.intellij.util.ArrayUtilRt; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.statements.*; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrStringInjection; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod; import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; @@ -72,69 +73,19 @@ public class GrIntroduceLocalVariableProcessor { preprocessOccurrences(); - boolean isExpressionFirstOccurrence = myOccurrences[0] == myExpression; - + int expressionIndex = ArrayUtilRt.find(myOccurrences, myExpression); final PsiElement[] replaced = processOccurrences(); - GrStatement anchor = getAnchor(replaced); - if (isControlStatementBranch(anchor)) { - anchor = insertBraces(replaced, anchor); - } - - GrVariable variable = insertVariableDefinition(declaration, anchor); - - if (isExpressionFirstOccurrence) { - final PsiElement expressionSkipped = PsiUtil.skipParentheses(replaced[0], true); - if (PsiUtil.isExpressionStatement(expressionSkipped) && - expressionSkipped.getParent() == variable.getParent().getParent()) { - expressionSkipped.delete(); - refreshPositionMarker(variable); - } - } RefactoringUtil.highlightAllOccurrences(myContext.getProject(), replaced, myContext.getEditor()); - return variable; - } - - private GrStatement insertBraces(PsiElement[] replaced, GrStatement anchor) { - List<SmartPsiElementPointer<PsiElement>> replacedPointers = ContainerUtil.newArrayList(); - final SmartPointerManager pointerManager = SmartPointerManager.getInstance(myContext.getProject()); - for (PsiElement element : replaced) { - replacedPointers.add(pointerManager.createSmartPsiElementPointer(element)); - } - SmartPsiElementPointer<GrStatement> anchorPointer = pointerManager.createSmartPsiElementPointer(anchor); - - final Document document = myContext.getEditor().getDocument(); - final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myContext.getProject()); - documentManager.doPostponedOperationsAndUnblockDocument(document); - final TextRange range = anchor.getTextRange(); - document.insertString(range.getEndOffset(), "}"); - document.insertString(skipSpacesBackward(document, range.getStartOffset()), "{"); - documentManager.commitDocument(document); - - for (int i = 0; i < replacedPointers.size(); i++) { - SmartPsiElementPointer<PsiElement> pointer = replacedPointers.get(i); - replaced[i] = pointer.getElement(); - } - anchor = anchorPointer.getElement(); - CodeStyleManager.getInstance(myContext.getProject()).reformat(anchor.getParent()); - return anchor; + return insertVariableDefinition(declaration, anchor, replaced[expressionIndex]); } private void refreshPositionMarker(PsiElement e) { myHandler.refreshPositionMarker(myContext.getEditor().getDocument().createRangeMarker(e.getTextRange())); } - private static int skipSpacesBackward(Document document, int offset) { - if (offset == 0) return offset; - final CharSequence sequence = document.getCharsSequence(); - while (Character.isSpaceChar(sequence.charAt(offset - 1))) { - offset--; - } - return offset; - } - private static boolean isControlStatementBranch(GrStatement statement) { return statement.getParent() instanceof GrLoopStatement && statement == ((GrLoopStatement)statement.getParent()).getBody() || statement.getParent() instanceof GrIfStatement && @@ -157,10 +108,6 @@ public class GrIntroduceLocalVariableProcessor { final GrExpression replaced = ((GrExpression)occurrence).replaceWithExpression(templateRef, true); result.add(replaced); - - if (isOriginal) { - refreshPositionMarker(replaced); - } } return PsiUtilCore.toPsiElementArray(result); @@ -198,21 +145,67 @@ public class GrIntroduceLocalVariableProcessor { } @NotNull - private GrVariable insertVariableDefinition(@NotNull GrVariableDeclaration declaration, final GrStatement anchor) throws IncorrectOperationException { + private GrVariable insertVariableDefinition(@NotNull GrVariableDeclaration declaration, @NotNull GrStatement anchor, PsiElement expression) throws IncorrectOperationException { + boolean deleteExpression = expression != null && PsiUtil.isExpressionStatement(expression) && !isSingleGStringInjectionExpr(expression); + boolean anchorEqualsExpression = anchor == expression; + + if (deleteExpression && !anchorEqualsExpression) { + expression.delete(); + } + + boolean isInsideLoop = isControlStatementBranch(anchor); + if (isInsideLoop) { + anchor = insertBraces(anchor); + } + LOG.assertTrue(myOccurrences.length > 0); + declaration = doInsertDefinition(declaration, anchor, deleteExpression, anchorEqualsExpression); + + final GrVariable variable = declaration.getVariables()[0]; + JavaCodeStyleManager.getInstance(declaration.getProject()).shortenClassReferences(declaration); + + + PsiElement markerPlace = deleteExpression ? variable : + isInsideLoop ? declaration.getParent() + : expression; + refreshPositionMarker(markerPlace); + + return variable; + } + + private GrVariableDeclaration doInsertDefinition(GrVariableDeclaration declaration, + GrStatement anchor, + boolean deleteExpression, + boolean anchorEqualsExpression) { PsiElement realContainer = anchor.getParent(); GrStatementOwner block = (GrStatementOwner)realContainer; - declaration = (GrVariableDeclaration)block.addStatementBefore(declaration, anchor); - final GrVariable variable = declaration.getVariables()[0]; - variable.setType(mySettings.getSelectedType()); + if (deleteExpression && anchorEqualsExpression) { + declaration = (GrVariableDeclaration)anchor.replace(declaration); + } + else { + declaration = (GrVariableDeclaration)block.addStatementBefore(declaration, anchor); + } + return declaration; + } - JavaCodeStyleManager.getInstance(declaration.getProject()).shortenClassReferences(declaration); - return variable; + private GrStatement insertBraces(GrStatement anchor) { + GrBlockStatement blockStatement = GroovyPsiElementFactory.getInstance(myContext.getProject()).createBlockStatement(); + + blockStatement.getBlock().addStatementBefore(anchor, null); + GrBlockStatement newBlockStatement = ((GrBlockStatement)anchor.replace(blockStatement)); + anchor = newBlockStatement.getBlock().getStatements()[0]; + return anchor; } + private static boolean isSingleGStringInjectionExpr(PsiElement expression) { + PsiElement parent = expression.getParent(); + return parent instanceof GrClosableBlock && parent.getParent() instanceof GrStringInjection; + } + + @NotNull private GrStatement getAnchor(PsiElement[] replaced) { PsiElement anchor = GrIntroduceHandlerBase.findAnchor(replaced, myContext.getScope()); if (!(anchor instanceof GrStatement)) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java index d5fb69eb7b80..5ce7a0985305 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java @@ -22,6 +22,7 @@ import com.intellij.psi.PsiModifier; import com.intellij.psi.PsiType; import com.intellij.refactoring.HelpID; import com.intellij.refactoring.introduce.inplace.OccurrencesChooser; +import com.intellij.refactoring.util.CanonicalTypes; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; @@ -144,6 +145,24 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase<GroovyInt @Override protected GroovyIntroduceVariableSettings getSettingsForInplace(final GrIntroduceContext context, final OccurrencesChooser.ReplaceChoice choice) { return new GroovyIntroduceVariableSettings() { + private final CanonicalTypes.Type myType; + private final String myName; + + + { + GrExpression expression = context.getExpression(); + StringPartInfo stringPart = context.getStringPart(); + GrVariable var = context.getVar(); + PsiType type = expression != null ? expression.getType() : + var != null ? var.getType() : + stringPart != null ? stringPart.getLiteral().getType() : + null; + myType = type != null ?CanonicalTypes.createTypeWrapper(type) : null; + + myName = new GrVariableNameSuggester(context, new GroovyVariableValidator(context)).suggestNames().iterator().next(); + } + + @Override public boolean isDeclareFinal() { return false; @@ -152,7 +171,7 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase<GroovyInt @Nullable @Override public String getName() { - return new GrVariableNameSuggester(context, new GroovyVariableValidator(context)).suggestNames().iterator().next(); + return myName; } @Override @@ -163,13 +182,7 @@ public class GrIntroduceVariableHandler extends GrIntroduceHandlerBase<GroovyInt @Nullable @Override public PsiType getSelectedType() { - GrExpression expression = context.getExpression(); - StringPartInfo stringPart = context.getStringPart(); - GrVariable var = context.getVar(); - return expression != null ? expression.getType() : - var != null ? var.getType() : - stringPart != null ? stringPart.getLiteral().getType() : - null; + return myType != null ? myType.getType(context.getPlace(), context.getPlace().getManager()) : null; } }; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/template/expressions/ChooseTypeExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/template/expressions/ChooseTypeExpression.java index 57d54cc34f90..4db70097ad5c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/template/expressions/ChooseTypeExpression.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/template/expressions/ChooseTypeExpression.java @@ -21,6 +21,7 @@ import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.codeInsight.lookup.PsiTypeLookupItem; import com.intellij.codeInsight.template.*; +import com.intellij.codeInsight.template.impl.JavaTemplateUtil; import com.intellij.openapi.editor.Document; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; @@ -117,11 +118,23 @@ public class ChooseTypeExpression extends Expression { type = TypesUtil.unboxPrimitiveTypeWrapper(type); if (type == null) return null; - return new PsiTypeResult(type, context.getProject()) { + final PsiType finalType = type; + return new PsiTypeResult(finalType, context.getProject()) { @Override public void handleRecalc(PsiFile psiFile, Document document, int segmentStart, int segmentEnd) { - if (myItems.length <= 1) super.handleRecalc(psiFile, document, segmentStart, segmentEnd); + if (myItems.length <= 1) { + super.handleRecalc(psiFile, document, segmentStart, segmentEnd); + } + else { + JavaTemplateUtil.updateTypeBindings(getType(), psiFile, document, segmentStart, segmentEnd, true); + } } + + @Override + public String toString() { + return myItems.length == 1 ? super.toString() : finalType.getPresentableText(); + } + }; } diff --git a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/abs.test b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/abs.test index 92581cf81fb7..d19519fde385 100644 --- a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/abs.test +++ b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/abs.test @@ -1,3 +1,3 @@ <begin>0.abs()<end> ----- -def preved = 0.abs()<caret> +def preved = 0.abs()<caret>
\ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/call1.test b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/call1.test index 0886271c68b2..1c1333a80f70 100644 --- a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/call1.test +++ b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/call1.test @@ -1,3 +1,3 @@ <begin>foo 1,2,3<end> ----- -def preved = foo(1, 2, 3)<caret> +def preved = foo(1, 2, 3)<caret>
\ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/call2.test b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/call2.test index c96db207a109..2d2c232172c9 100644 --- a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/call2.test +++ b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/call2.test @@ -4,9 +4,8 @@ foo 1,2,3 foo 1,2,3 foo 1,2,3 ----- -def preved = foo(1, 2, 3) +def preved = foo(1, 2, 3)<caret> preved preved -preved<caret> preved preved
\ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/charArray.test b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/charArray.test index 43789fa9e26c..04861f676d47 100644 --- a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/charArray.test +++ b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/charArray.test @@ -1,3 +1,3 @@ <begin>"abc".toCharArray()<end> ----- -char[] preved = "abc".toCharArray()<caret> +char[] preved = "abc".toCharArray()<caret>
\ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/fqn.test b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/fqn.test index 9dcc4d73f3f9..7bbe8d07b0da 100644 --- a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/fqn.test +++ b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/fqn.test @@ -4,4 +4,4 @@ import p.Foo ----- import p.Foo -def preved = Foo.foo()<caret> +def preved = Foo.foo()<caret>
\ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/loop5.test b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/loop5.test index ddf85d24dc33..960a392a2a16 100644 --- a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/loop5.test +++ b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/loop5.test @@ -3,5 +3,5 @@ foo <begin>foo<end> ----- while (true) { def preved = foo - foo preved<caret> -}
\ No newline at end of file + foo preved +}<caret>
\ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/loop6.test b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/loop6.test index 26deb67c231d..9bef9bf595cd 100644 --- a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/loop6.test +++ b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/loop6.test @@ -3,5 +3,5 @@ foo <all>foo<end> ----- while (true) { def preved = foo - preved preved<caret> -}
\ No newline at end of file + preved preved +}<caret>
\ No newline at end of file diff --git a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/loop8.test b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/loop8.test index 004246285d53..fb8cb92bdd5e 100644 --- a/plugins/groovy/testdata/groovy/refactoring/introduceVariable/loop8.test +++ b/plugins/groovy/testdata/groovy/refactoring/introduceVariable/loop8.test @@ -2,5 +2,5 @@ while (true) return <begin>1<end> ----- while (true) { def preved = 1 - return preved<caret> -}
\ No newline at end of file + return preved +}<caret>
\ No newline at end of file diff --git a/plugins/groovy/testdata/intentions/introduceLocalVariable/Constructor-after.groovy b/plugins/groovy/testdata/intentions/introduceLocalVariable/Constructor-after.groovy index d5925e60d0d6..8bd13e4b07d3 100644 --- a/plugins/groovy/testdata/intentions/introduceLocalVariable/Constructor-after.groovy +++ b/plugins/groovy/testdata/intentions/introduceLocalVariable/Constructor-after.groovy @@ -1 +1 @@ -def varName = new Hoge() +def varName = new Hoge()
\ No newline at end of file diff --git a/plugins/groovy/testdata/intentions/introduceLocalVariable/MethodCall1-after.groovy b/plugins/groovy/testdata/intentions/introduceLocalVariable/MethodCall1-after.groovy index 011acc5fa43d..b72bc1c8158f 100644 --- a/plugins/groovy/testdata/intentions/introduceLocalVariable/MethodCall1-after.groovy +++ b/plugins/groovy/testdata/intentions/introduceLocalVariable/MethodCall1-after.groovy @@ -1 +1 @@ -def varName = Calendar.getInstance() +def varName = Calendar.getInstance()
\ No newline at end of file diff --git a/plugins/groovy/testdata/intentions/introduceLocalVariable/MethodCall2-after.groovy b/plugins/groovy/testdata/intentions/introduceLocalVariable/MethodCall2-after.groovy index 7cded4fd4b7b..bd4e3e290fa7 100644 --- a/plugins/groovy/testdata/intentions/introduceLocalVariable/MethodCall2-after.groovy +++ b/plugins/groovy/testdata/intentions/introduceLocalVariable/MethodCall2-after.groovy @@ -1 +1 @@ -def varName = 'fuga'.length() +def varName = 'fuga'.length()
\ No newline at end of file diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgExecutableValidator.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgExecutableValidator.java index 2850867d5784..5a5da6febf10 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgExecutableValidator.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgExecutableValidator.java @@ -42,6 +42,6 @@ public class HgExecutableValidator extends ExecutableValidator { @Override public boolean isExecutableValid(@NotNull String executable) { - return HgUtil.isValid(executable); + return HgUtil.isExecutableValid(executable); } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.java index e9abbc4d4e78..3e301d972058 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.java @@ -71,7 +71,7 @@ public class HgConfigurationProjectPanel { public void validate() throws ConfigurationException { String hgExecutable; hgExecutable = getCurrentPath(); - if (!HgUtil.isValid(hgExecutable)) { + if (!HgUtil.isExecutableValid(hgExecutable)) { throw new ConfigurationException( HgVcsMessages.message("hg4idea.configuration.executable.error", hgExecutable) ); diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutablePathPanel.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutablePathPanel.java index a7f7eea6f015..6ed3936dcacd 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutablePathPanel.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgSetExecutablePathPanel.java @@ -24,7 +24,7 @@ class HgSetExecutablePathPanel extends TextFieldWithBrowseButton { FileChooserDescriptor descriptor = new FileChooserDescriptor(true, false, false, false, false, false) { public void validateSelectedFiles(VirtualFile[] files) throws Exception { String path = files[0].getPath(); - if (!HgUtil.isValid(path)) { + if (!HgUtil.isExecutableValid(path)) { throw new ConfigurationException(HgVcsMessages.message("hg4idea.configuration.executable.error", path)); } for (ActionListener okListener : myOkListeners) { diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java index 6ac0bc7ad6e0..ac5e5a4e165d 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java @@ -12,9 +12,6 @@ // limitations under the License. package org.zmlx.hg4idea.util; -import com.intellij.execution.configurations.GeneralCommandLine; -import com.intellij.execution.process.CapturingProcessHandler; -import com.intellij.execution.process.ProcessOutput; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; @@ -48,6 +45,9 @@ import org.zmlx.hg4idea.*; import org.zmlx.hg4idea.command.HgRemoveCommand; import org.zmlx.hg4idea.command.HgStatusCommand; import org.zmlx.hg4idea.command.HgWorkingCopyRevisionsCommand; +import org.zmlx.hg4idea.execution.HgCommandResult; +import org.zmlx.hg4idea.execution.ShellCommand; +import org.zmlx.hg4idea.execution.ShellCommandException; import org.zmlx.hg4idea.provider.HgChangeProvider; import org.zmlx.hg4idea.repo.HgRepository; import org.zmlx.hg4idea.repo.HgRepositoryManager; @@ -593,22 +593,29 @@ public abstract class HgUtil { return hgRepository.getRepositoryConfig().getPaths(); } - public static boolean isValid(@Nullable String executable) { + public static boolean isExecutableValid(@Nullable String executable) { try { if (StringUtil.isEmptyOrSpaces(executable)) { return false; } - GeneralCommandLine commandLine = new GeneralCommandLine(); - //noinspection ConstantConditions - commandLine.setExePath(executable); - commandLine.addParameter("--version"); - commandLine.addParameter("-q"); - CapturingProcessHandler handler = new CapturingProcessHandler(commandLine.createProcess(), CharsetToolkit.getDefaultSystemCharset()); - ProcessOutput result = handler.runProcess(30 * 1000); - return !result.isTimeout() && result.getStderr().isEmpty(); + HgCommandResult result = getVersionOutput(executable); + return result.getRawError().isEmpty(); } catch (Throwable e) { + LOG.info("Error during hg executable validation: ", e); return false; } } + + @NotNull + public static HgCommandResult getVersionOutput(@NotNull String executable) throws ShellCommandException, InterruptedException { + String hgExecutable = executable.trim(); + ShellCommand shellCommand = new ShellCommand(false); + List<String> cmdArgs = new ArrayList<String>(); + cmdArgs.add(hgExecutable); + cmdArgs.add("version"); + cmdArgs.add("-q"); + return shellCommand + .execute(cmdArgs, null, CharsetToolkit.getDefaultSystemCharset()); + } } diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java index 849305a49105..e613ac7cde50 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java @@ -21,13 +21,9 @@ import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.zmlx.hg4idea.execution.HgCommandResult; -import org.zmlx.hg4idea.execution.ShellCommand; import org.zmlx.hg4idea.execution.ShellCommandException; -import java.nio.charset.Charset; import java.text.ParseException; -import java.util.ArrayList; -import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -46,10 +42,10 @@ public final class HgVersion implements Comparable<HgVersion> { * The minimal supported version */ public static final HgVersion MIN = new HgVersion(1, 9, 1); - public static final HgVersion AMENDSUPPORTED = new HgVersion(2, 2, 0); + public static final HgVersion AMEND_SUPPORTED = new HgVersion(2, 2, 0); /** - * Special version with a special Type which indicates, that Hg version information is unavailable. + * Special version which indicates, that Hg version information is unavailable. */ public static final HgVersion NULL = new HgVersion(0, 0, 0); @@ -57,13 +53,10 @@ public final class HgVersion implements Comparable<HgVersion> { private final int myMiddle; private final int myMinor; - private final int myHashCode; - public HgVersion(int major, int middle, int minor) { myMajor = major; myMiddle = middle; myMinor = minor; - myHashCode = Objects.hashCode(myMajor, myMiddle, myMinor); } /** @@ -100,14 +93,7 @@ public final class HgVersion implements Comparable<HgVersion> { @NotNull public static HgVersion identifyVersion(@NotNull String executable) throws ShellCommandException, InterruptedException, ParseException { - String hgExecutable = executable.trim(); - ShellCommand shellCommand = new ShellCommand(false); - List<String> cmdArgs = new ArrayList<String>(); - cmdArgs.add(hgExecutable); - cmdArgs.add("version"); - cmdArgs.add("-q"); - HgCommandResult versionResult = shellCommand - .execute(cmdArgs, null, Charset.defaultCharset()); + HgCommandResult versionResult = HgUtil.getVersionOutput(executable); return parseVersion(versionResult.getRawOutput()); } @@ -119,33 +105,24 @@ public final class HgVersion implements Comparable<HgVersion> { } public boolean isAmendSupported() { - return !isNull() && compareTo(AMENDSUPPORTED) >= 0; + return !isNull() && compareTo(AMEND_SUPPORTED) >= 0; } /** * Note: this class has a natural ordering that is inconsistent with equals. - * Two HgVersions are equal if their number versions are equal and if their types are equal. - * Types are considered equal also if one of them is undefined. Otherwise they are compared. + * Two HgVersions are equal if their number versions are equal. */ @Override public boolean equals(final Object obj) { if (!(obj instanceof HgVersion)) { return false; } - HgVersion other = (HgVersion)obj; - if (compareTo(other) != 0) { - return false; - } - return true; + return compareTo((HgVersion)obj) == 0; } - /** - * Hashcode is computed from numbered components of the version. Thus HgVersions with the same numbered components will be compared - * by equals, and there the type will be taken into consideration). - */ @Override public int hashCode() { - return myHashCode; + return Objects.hashCode(myMajor, myMiddle, myMinor); } /** @@ -156,9 +133,6 @@ public final class HgVersion implements Comparable<HgVersion> { * {@link HgVersion#NULL} is less than any other not-NULL version. */ public int compareTo(@NotNull HgVersion o) { - if (o.isNull()) { - return isNull() ? 0 : 1; - } int d = myMajor - o.myMajor; if (d != 0) { return d; diff --git a/plugins/hg4idea/testSrc/hg4idea/test/version/HgVersionTest.java b/plugins/hg4idea/testSrc/hg4idea/test/version/HgVersionTest.java index a28f3b3cfa49..86bc7a88fc7c 100644 --- a/plugins/hg4idea/testSrc/hg4idea/test/version/HgVersionTest.java +++ b/plugins/hg4idea/testSrc/hg4idea/test/version/HgVersionTest.java @@ -70,7 +70,7 @@ public class HgVersionTest extends HgPlatformTest { assertEquals(middle, expected.middle); assertEquals(minor, expected.minor); HgVersion versionFromTest = new HgVersion(expected.major, expected.middle, expected.minor); - assertEquals(versionFromTest, actual); //test equals meth + assertEquals(versionFromTest, actual); //test equals method } private static class TestHgVersion { diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/intentions/JavaFxInjectPageLanguageIntention.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/intentions/JavaFxInjectPageLanguageIntention.java index 0b82c99e9241..9c3fe6914a73 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/intentions/JavaFxInjectPageLanguageIntention.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/intentions/JavaFxInjectPageLanguageIntention.java @@ -80,7 +80,7 @@ public class JavaFxInjectPageLanguageIntention extends PsiElementBaseIntentionAc } } - return new UrlClassLoader(urls, null); + return UrlClassLoader.build().urls(urls).get(); } @Override diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyAttributeDescriptor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyAttributeDescriptor.java index 41d10e4a9c75..60d7a433d421 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyAttributeDescriptor.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxPropertyAttributeDescriptor.java @@ -101,13 +101,13 @@ public class JavaFxPropertyAttributeDescriptor extends BasicXmlAttributeDescript } @Override - protected PsiElement getEnumeratedValueDeclaration(XmlAttributeValue attributeValue, String value) { + public PsiElement getEnumeratedValueDeclaration(XmlElement xmlElement, String value) { final PsiClass aClass = getEnum(); if (aClass != null) { final PsiField fieldByName = aClass.findFieldByName(value, false); return fieldByName != null ? fieldByName : aClass.findFieldByName(value.toUpperCase(), false); } - return attributeValue; + return xmlElement; } @Nullable diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java index ad92707e8f01..2aa35156a91d 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java @@ -144,7 +144,7 @@ public class MavenExternalParameters { params.getClassPath().add(path); } - params.setEnv(Collections.unmodifiableMap(runnerSettings.getEnvironmentProperties())); + params.setEnv(new HashMap<String, String>(runnerSettings.getEnvironmentProperties())); params.setPassParentEnvs(runnerSettings.isPassParentEnv()); params.setMainClass(MAVEN_LAUNCHER_CLASS); diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenModelPropertiesPatcher.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenModelPropertiesPatcher.java index 71243eb945ad..defe2bf99d6c 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenModelPropertiesPatcher.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/api/MavenModelPropertiesPatcher.java @@ -28,12 +28,13 @@ public class MavenModelPropertiesPatcher { Map<String, Map<String, List<MavenPluginDescriptor>>> groupMap = map.get(plugin.getArtifactId()); if (groupMap != null) { Map<String, List<MavenPluginDescriptor>> goalsMap = groupMap.get(plugin.getGroupId()); + if (goalsMap != null) { + patch(modelProperties, goalsMap.get(null), null, plugin.getConfigurationElement(), plugin); - patch(modelProperties, goalsMap.get(null), null, plugin.getConfigurationElement(), plugin); - - for (MavenPlugin.Execution execution : plugin.getExecutions()) { - for (String goal : execution.getGoals()) { - patch(modelProperties, goalsMap.get(goal), goal, execution.getConfigurationElement(), plugin); + for (MavenPlugin.Execution execution : plugin.getExecutions()) { + for (String goal : execution.getGoals()) { + patch(modelProperties, goalsMap.get(goal), goal, execution.getConfigurationElement(), plugin); + } } } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepository.java index 7177d4425179..f3ed0f92b411 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepository.java @@ -71,6 +71,7 @@ public class GenericRepository extends BaseRepositoryImpl { private List<TemplateVariable> myTemplateVariables = new ArrayList<TemplateVariable>(); private String mySubtypeName; + private boolean myDownloadTasksInSeparateRequests; /** * Serialization constructor @@ -100,8 +101,9 @@ public class GenericRepository extends BaseRepositoryImpl { myResponseType = other.getResponseType(); myTemplateVariables = other.getTemplateVariables(); + mySubtypeName = other.getSubtypeName(); + myDownloadTasksInSeparateRequests = other.getDownloadTasksInSeparateRequests(); myResponseHandlersMap = new EnumMap<ResponseType, ResponseHandler>(ResponseType.class); - mySubtypeName = other.mySubtypeName; for (Map.Entry<ResponseType, ResponseHandler> e : other.myResponseHandlersMap.entrySet()) { ResponseHandler handler = e.getValue().clone(); handler.setRepository(this); @@ -113,6 +115,7 @@ public class GenericRepository extends BaseRepositoryImpl { myLoginURL = ""; myTasksListUrl = ""; mySingleTaskUrl = ""; + myDownloadTasksInSeparateRequests = false; myLoginMethodType = HTTPMethod.GET; myTasksListMethodType = HTTPMethod.GET; mySingleTaskMethodType = HTTPMethod.GET; @@ -144,6 +147,7 @@ public class GenericRepository extends BaseRepositoryImpl { if (!Comparing.equal(getResponseType(), that.getResponseType())) return false; if (!Comparing.equal(getTemplateVariables(), that.getTemplateVariables())) return false; if (!Comparing.equal(getResponseHandlers(), that.getResponseHandlers())) return false; + if (!Comparing.equal(getDownloadTasksInSeparateRequests(), that.getDownloadTasksInSeparateRequests())) return false; return true; } @@ -160,6 +164,9 @@ public class GenericRepository extends BaseRepositoryImpl { @Override public Task[] getIssues(@Nullable final String query, final int max, final long since) throws Exception { + if (StringUtil.isEmpty(myTasksListUrl)) { + throw new Exception("'Task list URL' configuration parameter is mandatory"); + } if (!isLoginAnonymously() && !isUseHttpAuthentication()) { executeMethod(getLoginMethod()); } @@ -168,8 +175,11 @@ public class GenericRepository extends BaseRepositoryImpl { new TemplateVariable("since", since)); String requestUrl = GenericRepositoryUtil.substituteTemplateVariables(getTasksListUrl(), variables); String responseBody = executeMethod(getHttpMethod(requestUrl, myTasksListMethodType)); - Task[] tasks = getActiveResponseHandler().parseIssues(responseBody); - if (!StringUtil.isEmpty(mySingleTaskUrl) && !(myResponseType == ResponseType.TEXT)) { + Task[] tasks = getActiveResponseHandler().parseIssues(responseBody, max); + if (myResponseType == ResponseType.TEXT) { + return tasks; + } + if (StringUtil.isNotEmpty(mySingleTaskUrl) && myDownloadTasksInSeparateRequests) { for (int i = 0; i < tasks.length; i++) { tasks[i] = findTask(tasks[i].getId()); } @@ -380,4 +390,12 @@ public class GenericRepository extends BaseRepositoryImpl { public void setSubtypeName(String subtypeName) { mySubtypeName = subtypeName; } + + public boolean getDownloadTasksInSeparateRequests() { + return myDownloadTasksInSeparateRequests; + } + + public void setDownloadTasksInSeparateRequests(boolean downloadTasksInSeparateRequests) { + myDownloadTasksInSeparateRequests = downloadTasksInSeparateRequests; + } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.form b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.form index 0e8695752594..6922f2aa280e 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.form +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.form @@ -3,7 +3,7 @@ <grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="6" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="8"> <margin top="0" left="0" bottom="0" right="0"/> <constraints> - <xy x="20" y="20" width="500" height="438"/> + <xy x="20" y="20" width="514" height="438"/> </constraints> <properties/> <border type="none"/> @@ -16,7 +16,7 @@ <text value="Response Type:"/> </properties> </component> - <grid id="d68b9" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> + <grid id="d68b9" layout-manager="GridLayoutManager" row-count="1" column-count="6" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <margin top="0" left="0" bottom="0" right="0"/> <constraints> <grid row="3" column="1" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/> @@ -44,13 +44,6 @@ <text value="&Text"/> </properties> </component> - <hspacer id="cebcb"> - <constraints> - <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"> - <preferred-size width="14" height="44"/> - </grid> - </constraints> - </hspacer> <component id="71bfc" class="javax.swing.JRadioButton" binding="myJsonRadioButton"> <constraints> <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"> @@ -61,6 +54,26 @@ <text value="JS&ON"/> </properties> </component> + <component id="b8210" class="javax.swing.JLabel"> + <constraints> + <grid row="0" column="4" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> + </constraints> + <properties> + <horizontalTextPosition value="4"/> + <text value="Each task in separate request:"/> + </properties> + </component> + <component id="69199" class="com.intellij.ui.components.JBCheckBox" binding="myDownloadTasksInSeparateRequests"> + <constraints> + <grid row="0" column="5" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> + </constraints> + <properties/> + </component> + <hspacer id="b7318"> + <constraints> + <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/> + </constraints> + </hspacer> </children> </grid> <grid id="2e934" layout-manager="GridLayoutManager" row-count="1" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.java index 0a6b9a1d1d98..6ddb8da103b5 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryEditor.java @@ -1,5 +1,6 @@ package com.intellij.tasks.generic; +import com.intellij.codeInsight.completion.CompletionParameters; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.util.Condition; @@ -7,12 +8,14 @@ import com.intellij.tasks.TaskManager; import com.intellij.tasks.config.BaseRepositoryEditor; import com.intellij.ui.EditorTextField; import com.intellij.ui.TextFieldWithAutoCompletion; +import com.intellij.ui.components.JBCheckBox; import com.intellij.ui.components.JBLabel; import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.net.HTTPMethod; import com.intellij.util.ui.FormBuilder; import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -26,6 +29,7 @@ import java.util.Map; import static com.intellij.tasks.generic.GenericRepositoryUtil.concat; import static com.intellij.tasks.generic.GenericRepositoryUtil.createPlaceholdersList; import static com.intellij.tasks.generic.GenericRepositoryUtil.prettifyVariableName; +import static com.intellij.ui.TextFieldWithAutoCompletion.StringsCompletionProvider; /** * @author Evgeny.Zakrevsky @@ -49,6 +53,7 @@ public class GenericRepositoryEditor<T extends GenericRepository> extends BaseRe private JButton myResetToDefaultsButton; private JPanel myCardPanel; private JBLabel mySingleTaskURLLabel; + private JBCheckBox myDownloadTasksInSeparateRequests; private Map<JTextField, TemplateVariable> myField2Variable; private Map<JRadioButton, ResponseType> myRadio2ResponseType; @@ -100,6 +105,7 @@ public class GenericRepositoryEditor<T extends GenericRepository> extends BaseRe installListener(myLoginURLText); installListener(myTasksListURLText); installListener(mySingleTaskURLText); + installListener(myDownloadTasksInSeparateRequests); myTabbedPane.addTab("Server configuration", myPanel); // Put appropriate configuration components on the card panel @@ -147,7 +153,7 @@ public class GenericRepositoryEditor<T extends GenericRepository> extends BaseRe @Override public void actionPerformed(final ActionEvent e) { myRepository.resetToDefaults(); - // XXX: Why clone() here? + // TODO: look closely reset(myRepository.clone()); } }); @@ -156,6 +162,7 @@ public class GenericRepositoryEditor<T extends GenericRepository> extends BaseRe selectCardByResponseType(); loginUrlEnablingChanged(); singleTaskUrlEnablingChanged(); + myDownloadTasksInSeparateRequests.setSelected(myRepository.getDownloadTasksInSeparateRequests()); } private void singleTaskUrlEnablingChanged() { @@ -202,6 +209,7 @@ public class GenericRepositoryEditor<T extends GenericRepository> extends BaseRe selectRadioButtonByResponseType(); selectCardByResponseType(); loginUrlEnablingChanged(); + myDownloadTasksInSeparateRequests.setSelected(myRepository.getDownloadTasksInSeparateRequests()); } private void selectRadioButtonByResponseType() { @@ -227,6 +235,7 @@ public class GenericRepositoryEditor<T extends GenericRepository> extends BaseRe myRepository.setTasksListMethodType(HTTPMethod.valueOf((String)myTasksListMethodTypeComboBox.getSelectedItem())); myRepository.setSingleTaskMethodType(HTTPMethod.valueOf((String)mySingleTaskMethodComboBox.getSelectedItem())); + myRepository.setDownloadTasksInSeparateRequests(myDownloadTasksInSeparateRequests.isSelected()); for (Map.Entry<JTextField, TemplateVariable> entry : myField2Variable.entrySet()) { TemplateVariable variable = entry.getValue(); JTextField field = entry.getKey(); @@ -243,14 +252,24 @@ public class GenericRepositoryEditor<T extends GenericRepository> extends BaseRe private void createUIComponents() { List<String> placeholders = createPlaceholdersList(myRepository); myLoginURLText = createTextFieldWithCompletion(myRepository.getLoginUrl(), placeholders); - myTasksListURLText = createTextFieldWithCompletion(myRepository.getTasksListUrl(), - concat(placeholders, "{max}", "{since}")); - mySingleTaskURLText = createTextFieldWithCompletion(myRepository.getSingleTaskUrl(), - concat(placeholders, "{id}")); + myTasksListURLText = createTextFieldWithCompletion(myRepository.getTasksListUrl(), concat(placeholders, "{max}", "{since}")); + mySingleTaskURLText = createTextFieldWithCompletion(myRepository.getSingleTaskUrl(), concat(placeholders, "{id}")); } - private TextFieldWithAutoCompletion<String> createTextFieldWithCompletion(String text, List<String> variants) { - return TextFieldWithAutoCompletion.create(myProject, variants, true, text); + private TextFieldWithAutoCompletion<String> createTextFieldWithCompletion(String text, final List<String> variants) { + final StringsCompletionProvider provider = new StringsCompletionProvider(variants, null) { + @Nullable + @Override + public String getPrefix(@NotNull CompletionParameters parameters) { + final String text = parameters.getOriginalFile().getText(); + final int i = text.lastIndexOf('{', parameters.getOffset() - 1); + if (i < 0) { + return ""; + } + return text.substring(i, parameters.getOffset()); + } + }; + return new TextFieldWithAutoCompletion<String>(myProject, provider, true, text); } @Override diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryUtil.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryUtil.java index b90bfb839fcf..ce1fa3ec69dc 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryUtil.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryUtil.java @@ -7,12 +7,10 @@ import com.intellij.util.containers.HashMap; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.methods.PostMethod; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -21,9 +19,6 @@ import java.util.regex.Pattern; */ public class GenericRepositoryUtil { private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\{(\\w[-\\w]*)\\}"); - private static SimpleDateFormat ISO8601_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); - private static Pattern ISO8601_DATE_PATTERN = Pattern.compile( - "(\\d{4}-\\d{2}-\\d{2})[ T](\\d{2}:\\d{2}:\\d{2})(.\\d{3,})?([+-]\\d{2}:\\d{2}|[+-]\\d{4}|[+-]\\d{2}|Z)"); public static HttpMethod getPostMethodFromURL(final String requestUrl) { int n = requestUrl.indexOf('?'); @@ -72,38 +67,6 @@ public class GenericRepositoryUtil { }); } - @Nullable - public static Date parseISO8601Date(@NotNull String s) { - // SimpleDateFormat prior JDK7 doesn't support 'X' specifier for ISO 8601 timezone format. - // Because some bug trackers and task servers e.g. send dates ending with 'Z' (that stands for UTC), - // dates should be preprocessed before parsing. - Matcher m = ISO8601_DATE_PATTERN.matcher(s); - if (!m.matches()) { - return null; - } - String datePart = m.group(1); - String timePart = m.group(2); - String milliseconds = m.group(3); - milliseconds = milliseconds == null? "000" : milliseconds.substring(1, 4); - String timezone = m.group(4); - if (timezone.equals("Z")) { - timezone = "+0000"; - } else if (timezone.length() == 3) { - // [+-]HH - timezone += "00"; - } else if (timezone.length() == 6) { - // [+-]HH:MM - timezone = timezone.substring(0, 3) + timezone.substring(4, 6); - } - String canonicalForm = String.format("%sT%s.%s%s", datePart, timePart, milliseconds, timezone); - try { - return ISO8601_DATE_FORMAT.parse(canonicalForm); - } - catch (ParseException e) { - return null; - } - } - public static String prettifyVariableName(String variableName) { String prettyName = variableName.replace('_', ' '); return StringUtil.capitalizeWords(prettyName, true); diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/HighlightedSelectorsTable.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/HighlightedSelectorsTable.java index 48d7b1bba651..ab65c32fa823 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/HighlightedSelectorsTable.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/HighlightedSelectorsTable.java @@ -15,19 +15,18 @@ */ package com.intellij.tasks.generic; -import com.intellij.lang.Language; import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.project.Project; -import com.intellij.ui.LanguageTextField; +import com.intellij.ui.EditorTextField; import com.intellij.ui.table.TableView; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.AbstractTableCellEditor; import com.intellij.util.ui.ColumnInfo; import com.intellij.util.ui.ListTableModel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; import java.awt.*; import java.util.List; @@ -35,14 +34,9 @@ import java.util.List; class HighlightedSelectorsTable extends TableView<Selector> { - private final FileType myValueFileType; - private final Project myProject; - - public HighlightedSelectorsTable(@NotNull FileType valueFileType, @NotNull Project project) { - this(valueFileType, project, ContainerUtil.<Selector>emptyList()); - } - - public HighlightedSelectorsTable(@NotNull final FileType valueFileType, @NotNull final Project project, @NotNull final List<Selector> selectors) { + public HighlightedSelectorsTable(@NotNull final FileType valueFileType, + @NotNull final Project project, + @NotNull final List<Selector> selectors) { super(new ListTableModel<Selector>(new ColumnInfo[]{ new ColumnInfo<Selector, String>("Name") { @Nullable @@ -52,6 +46,7 @@ class HighlightedSelectorsTable extends TableView<Selector> { } }, new ColumnInfo<Selector, String>("Path") { + @Nullable @Override public String valueOf(Selector selector) { @@ -71,29 +66,40 @@ class HighlightedSelectorsTable extends TableView<Selector> { @Nullable @Override public TableCellRenderer getRenderer(Selector selector) { - return new LanguageTextFieldRenderer(((LanguageFileType)valueFileType).getLanguage(), project); + return new EditorTableCellViewer(valueFileType, project); + } + + @Nullable + @Override + public TableCellEditor getEditor(Selector o) { + return new EditorTableCellViewer(valueFileType, project); } } }, selectors, 0)); - myValueFileType = valueFileType; - myProject = project; - } - public List<Selector> getSelectors() { - return getItems(); } - private static class LanguageTextFieldRenderer implements TableCellRenderer { - private final Project myProject; - private final Language myLanguage; + private static class EditorTableCellViewer extends AbstractTableCellEditor implements TableCellRenderer { + private final EditorTextField myEditorField; + + private EditorTableCellViewer(FileType fileType, Project project) { + myEditorField = new EditorTextField("", project, fileType); + } - private LanguageTextFieldRenderer(Language language, Project project) { - myProject = project; - myLanguage = language; + @Override + public Object getCellEditorValue() { + return myEditorField.getText(); + } + + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + myEditorField.setText((String)value); + return myEditorField; } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - return new LanguageTextField(myLanguage, myProject, (String)value); + myEditorField.setText((String)value); + return myEditorField; } } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/JsonPathResponseHandler.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/JsonPathResponseHandler.java index e2f1ea8ce00f..cc80ed29e5ba 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/JsonPathResponseHandler.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/JsonPathResponseHandler.java @@ -4,16 +4,15 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.PlainTextFileType; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.tasks.Task; +import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.HashMap; import com.intellij.util.xmlb.annotations.Tag; import com.jayway.jsonpath.InvalidPathException; import com.jayway.jsonpath.JsonPath; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.Date; import java.util.List; import java.util.Map; @@ -32,6 +31,8 @@ public final class JsonPathResponseHandler extends SelectorBasedResponseHandler new Pair<Class<?>, String>(Boolean.class, "JSON boolean") ); + private final Map<String, JsonPath> myCompiledCache = new HashMap<String, JsonPath>(); + /** * Serialization constructor */ @@ -48,111 +49,95 @@ public final class JsonPathResponseHandler extends SelectorBasedResponseHandler return PlainTextFileType.INSTANCE; } - @SuppressWarnings("unchecked") - @NotNull - @Override - public Task[] doParseIssues(String response) throws Exception { - Object tasksMatch = JsonPath.read(response, getSelectorPath("tasks")); - if (!(tasksMatch instanceof List)) { - throw new Exception("Selector 'task' should match array of tasks. Got " + tasksMatch.toString() + " instead"); - } - List<Object> tasks = (List<Object>)tasksMatch; - List<GenericTask> result = new ArrayList<GenericTask>(tasks.size()); - for (Object rawTask : tasks) { - String taskText = rawTask.toString(); - String id = extractId(taskText, getSelector("id")); - String summary = extractString(taskText, getSelector("summary")); - assert summary != null; - GenericTask task = new GenericTask(id, summary, myRepository); - task.setDescription(extractString(response, getSelector("description"))); - task.setIssueUrl(extractString(response, getSelector("issueUrl"))); - Boolean closed = extractBoolean(response, getSelector("closed")); - if (closed != null) { - task.setClosed(closed); - } - task.setUpdated(extractDate(response, getSelector("updated"))); - task.setCreated(extractDate(response, getSelector("created"))); - result.add(task); - } - return result.toArray(new Task[result.size()]); - } - @Nullable - @Override - public Task doParseIssue(String response) throws Exception { - String id = extractId(response, getSelector("singleTask-id")); - String summary = extractString(response, getSelector("singleTask-summary")); - GenericTask task = new GenericTask(id, summary, myRepository); - task.setDescription(extractString(response, getSelector("singleTask-description"))); - task.setIssueUrl(extractString(response, getSelector("singleTask-issueUrl"))); - Boolean closed = extractBoolean(response, getSelector("singleTask-closed")); - if (closed != null) { - task.setClosed(closed); - } - task.setUpdated(extractDate(response, getSelector("singleTask-updated"))); - task.setCreated(extractDate(response, getSelector("singleTask-created"))); - return task; - } - - @SuppressWarnings({"unchecked", "MethodMayBeStatic"}) - @Nullable - private <T> T extractValueAndCheckType(String source, Selector selector, Class<T> cls) throws Exception { - if (selector == null || StringUtil.isEmpty(selector.getPath())) { + private Object extractRawValue(@NotNull Selector selector, @NotNull String source) throws Exception { + if (StringUtil.isEmpty(selector.getPath())) { return null; } + JsonPath jsonPath = lazyCompile(selector.getPath()); Object value; try { - value = JsonPath.read(source, selector.getPath()); + value = jsonPath.read(source); } catch (InvalidPathException e) { - // NOTE: could be thrown when selector is actually invalid or just not matched - throw new Exception(String.format("JsonPath expression '%s' is malformed or didn't match", selector.getPath()), e); + throw new Exception(String.format("JsonPath expression '%s' doesn't match", selector.getPath()), e); } if (value == null) { return null; } - if (!(cls.isInstance(value))) { - throw new Exception( - String.format("Selector '%s' should match %s. Got '%s' instead", selector.getName(), JSON_TYPES.get(cls), value.toString())); - } - return (T)value; + return value; } - @SuppressWarnings("MethodMayBeStatic") @Nullable - private String extractId(String task, Selector idSelector) throws Exception { - Object rawId; - try { - rawId = JsonPath.read(task, idSelector.getPath()); - } - catch (InvalidPathException e) { - throw new Exception(String.format("JsonPath expression '%s' is malformed or didn't match", idSelector.getPath()), e); + private <T> T extractValueAndCheckType(@NotNull Selector selector, @NotNull String source, Class<T> cls) throws Exception { + final Object value = extractRawValue(selector, source); + if (value == null) { + return null; } - if (!(rawId instanceof String) && !(rawId instanceof Long)) { + if (!(cls.isInstance(value))) { throw new Exception( - String.format("Selector 'id' should match either JSON string or JSON number value. Got '%s' instead", rawId.toString())); + String.format("JsonPath expression '%s' should match %s. Got '%s' instead", + selector.getPath(), JSON_TYPES.get(cls), value)); + } + @SuppressWarnings("unchecked") + T casted = (T)value; + return casted; + } + + @NotNull + @Override + protected List<Object> selectTasksList(@NotNull String response, int max) throws Exception { + @SuppressWarnings("unchecked") + List<Object> list = (List<Object>)extractValueAndCheckType(getSelector(TASKS), response, List.class); + if (list == null) { + return ContainerUtil.emptyList(); } - return String.valueOf(rawId); + return ContainerUtil.map2List(list, new Function<Object, Object>() { + @Override + public Object fun(Object o) { + return o.toString(); + } + }).subList(0, Math.min(list.size(), max)); } - private String extractString(String source, Selector selector) throws Exception { - return extractValueAndCheckType(source, selector, String.class); + @Nullable + @Override + protected String selectString(@NotNull Selector selector, @NotNull Object context) throws Exception { + //return extractValueAndCheckType((String)context, selector, String.class); + final Object value = extractRawValue(selector, (String)context); + if (value == null) { + return null; + } + if (value instanceof String || value instanceof Long || value instanceof Boolean) { + return value.toString(); + } + throw new Exception(String.format("JsonPath expression '%s' should match string value. Got '%s' instead", + selector.getPath(), value)); } - private Boolean extractBoolean(String source, Selector selector) throws Exception { - return extractValueAndCheckType(source, selector, Boolean.class); + @Nullable + @Override + protected Boolean selectBoolean(@NotNull Selector selector, @NotNull Object context) throws Exception { + return extractValueAndCheckType(selector, (String)context, Boolean.class); } - private Long extractLong(String source, Selector selector) throws Exception { - return extractValueAndCheckType(source, selector, Long.class); + @Nullable + private Long selectLong(@NotNull Selector selector, @NotNull String source) throws Exception { + return extractValueAndCheckType(selector, source, Long.class); } - private Date extractDate(String response, Selector selector) throws Exception { - String dateString = extractString(response, selector); - if (dateString == null) { - return null; + @NotNull + private JsonPath lazyCompile(@NotNull String path) throws Exception { + if (!myCompiledCache.containsKey(path)) { + try { + final JsonPath jsonPath = JsonPath.compile(path); + myCompiledCache.put(path, jsonPath); + } + catch (InvalidPathException e) { + throw new Exception(String.format("Malformed JsonPath expression '%s'", path)); + } } - return GenericRepositoryUtil.parseISO8601Date(dateString); + return myCompiledCache.get(path); } @Override diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ManageTemplateVariablesDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ManageTemplateVariablesDialog.java index fca6b21eeb41..e9e6d5e8460f 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ManageTemplateVariablesDialog.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ManageTemplateVariablesDialog.java @@ -2,12 +2,14 @@ package com.intellij.tasks.generic; import com.intellij.execution.util.ListTableWithButtons; import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.util.ui.AbstractTableCellEditor; import com.intellij.util.ui.ColumnInfo; import com.intellij.util.ui.ListTableModel; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; +import javax.swing.table.TableCellEditor; import javax.swing.table.TableCellRenderer; import java.awt.*; import java.util.List; @@ -109,6 +111,27 @@ public class ManageTemplateVariablesDialog extends DialogWrapper { @Nullable @Override + public TableCellEditor getEditor(final TemplateVariable variable) { + if (variable.getIsHidden()) { + return new AbstractTableCellEditor() { + private JPasswordField myPasswordField; + @Override + public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { + myPasswordField = new JPasswordField(variable.getValue()); + return myPasswordField; + } + + @Override + public Object getCellEditorValue() { + return myPasswordField.getText(); + } + }; + } + return super.getEditor(variable); + } + + @Nullable + @Override protected String getDescription(TemplateVariable templateVariable) { return templateVariable.getDescription(); } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/RegExResponseHandler.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/RegExResponseHandler.java index 45332b5de037..c08085194712 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/RegExResponseHandler.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/RegExResponseHandler.java @@ -86,7 +86,7 @@ public final class RegExResponseHandler extends ResponseHandler { @NotNull @Override - public Task[] parseIssues(String response) throws Exception { + public Task[] parseIssues(String response, int max) throws Exception { final List<String> placeholders = getPlaceholders(myTaskRegex); if (!placeholders.contains(ID_PLACEHOLDER) || !placeholders.contains(SUMMARY_PLACEHOLDER)) { throw new Exception("Incorrect Task Pattern"); @@ -99,7 +99,7 @@ public final class RegExResponseHandler extends ResponseHandler { .matcher(response); List<Task> tasks = new ArrayList<Task>(); - while (matcher.find()) { + for (int i = 0; i < max && matcher.find(); i++) { String id = matcher.group(placeholders.indexOf(ID_PLACEHOLDER) + 1); String summary = matcher.group(placeholders.indexOf(SUMMARY_PLACEHOLDER) + 1); // temporary workaround to make AssemblaIntegrationTestPass diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ResponseHandler.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ResponseHandler.java index 94bdd979cfcd..d51c38ac1bf7 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ResponseHandler.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/ResponseHandler.java @@ -45,7 +45,7 @@ public abstract class ResponseHandler implements Cloneable { public abstract ResponseType getResponseType(); @NotNull - public abstract Task[] parseIssues(String response) throws Exception; + public abstract Task[] parseIssues(String response, int max) throws Exception; @Nullable public abstract Task parseIssue(String response) throws Exception; diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/SelectorBasedResponseHandler.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/SelectorBasedResponseHandler.java index 5ef8809a39c5..865e43db81a2 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/SelectorBasedResponseHandler.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/SelectorBasedResponseHandler.java @@ -4,16 +4,19 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.tasks.Task; +import com.intellij.tasks.impl.TaskUtil; import com.intellij.ui.components.JBScrollPane; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.xmlb.annotations.AbstractCollection; import com.intellij.util.xmlb.annotations.Property; import com.intellij.util.xmlb.annotations.Tag; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.ArrayList; +import java.util.Date; import java.util.LinkedHashMap; import java.util.List; @@ -22,6 +25,25 @@ import java.util.List; */ public abstract class SelectorBasedResponseHandler extends ResponseHandler { + // Supported selector names + @NonNls protected static final String TASKS = "tasks"; + + @NonNls protected static final String SUMMARY = "summary"; + @NonNls protected static final String DESCRIPTION = "description"; + @NonNls protected static final String ISSUE_URL = "issueUrl"; + @NonNls protected static final String CLOSED = "closed"; + @NonNls protected static final String UPDATED = "updated"; + @NonNls protected static final String CREATED = "created"; + + @NonNls protected static final String SINGLE_TASK_ID = "singleTask-id"; + @NonNls protected static final String SINGLE_TASK_SUMMARY = "singleTask-summary"; + @NonNls protected static final String SINGLE_TASK_DESCRIPTION = "singleTask-description"; + @NonNls protected static final String SINGLE_TASK_ISSUE_URL = "singleTask-issueUrl"; + @NonNls protected static final String SINGLE_TASK_CLOSED = "singleTask-closed"; + @NonNls protected static final String SINGLE_TASK_UPDATED = "singleTask-updated"; + @NonNls protected static final String SINGLE_TASK_CREATED = "singleTask-created"; + @NonNls protected static final String ID = "id"; + protected LinkedHashMap<String, Selector> mySelectors = new LinkedHashMap<String, Selector>(); /** @@ -37,25 +59,25 @@ public abstract class SelectorBasedResponseHandler extends ResponseHandler { // standard selectors setSelectors(ContainerUtil.newArrayList( // matched against list of tasks at whole downloaded from "taskListUrl" - new Selector("tasks", ""), + new Selector(TASKS), // matched against single tasks extracted from the list downloaded from "taskListUrl" - new Selector("id"), - new Selector("summary"), - new Selector("description"), - new Selector("updated"), - new Selector("created"), - new Selector("closed"), - new Selector("issueUrl"), + new Selector(ID), + new Selector(SUMMARY), + new Selector(DESCRIPTION), + new Selector(UPDATED), + new Selector(CREATED), + new Selector(CLOSED), + new Selector(ISSUE_URL), // matched against single task downloaded from "singleTaskUrl" - new Selector("singleTask-id"), - new Selector("singleTask-summary"), - new Selector("singleTask-description"), - new Selector("singleTask-updated"), - new Selector("singleTask-created"), - new Selector("singleTask-closed"), - new Selector("singleTask-issueUrl") + new Selector(SINGLE_TASK_ID), + new Selector(SINGLE_TASK_SUMMARY), + new Selector(SINGLE_TASK_DESCRIPTION), + new Selector(SINGLE_TASK_UPDATED), + new Selector(SINGLE_TASK_CREATED), + new Selector(SINGLE_TASK_CLOSED), + new Selector(SINGLE_TASK_ISSUE_URL) )); } @@ -76,15 +98,18 @@ public abstract class SelectorBasedResponseHandler extends ResponseHandler { } } - @Nullable - public Selector getSelector(@NotNull String name) { + /** + * Only predefined selectors should be accessed. + */ + @NotNull + protected Selector getSelector(@NotNull String name) { return mySelectors.get(name); } - @Nullable - public String getSelectorPath(@NotNull String name) { + @NotNull + protected String getSelectorPath(@NotNull String name) { Selector s = getSelector(name); - return s == null ? null : s.getPath(); + return s.getPath(); } @Override @@ -107,10 +132,10 @@ public abstract class SelectorBasedResponseHandler extends ResponseHandler { @Override public boolean isConfigured() { - Selector idSelector = getSelector("id"); - if (idSelector == null || StringUtil.isEmpty(idSelector.getPath())) return false; - Selector summarySelector = getSelector("summary"); - if (summarySelector == null || StringUtil.isEmpty(summarySelector.getPath())) return false; + Selector idSelector = getSelector(ID); + if (StringUtil.isEmpty(idSelector.getPath())) return false; + Selector summarySelector = getSelector(SUMMARY); + if (StringUtil.isEmpty(summarySelector.getPath())) return false; return true; } @@ -133,26 +158,109 @@ public abstract class SelectorBasedResponseHandler extends ResponseHandler { @NotNull @Override - public final Task[] parseIssues(String response) throws Exception { - if (StringUtil.isEmpty(getSelectorPath("tasks")) || - StringUtil.isEmpty(getSelectorPath("id")) || - StringUtil.isEmpty(getSelectorPath("summary"))) { + public final Task[] parseIssues(String response, int max) throws Exception { + if (StringUtil.isEmpty(getSelectorPath(TASKS)) || + StringUtil.isEmpty(getSelectorPath(ID)) || + StringUtil.isEmpty(getSelectorPath(SUMMARY))) { throw new Exception("Selectors 'tasks', 'id' and 'summary' are mandatory"); } - return doParseIssues(response); + List<Object> tasks = selectTasksList(response, max); + List<Task> result = new ArrayList<Task>(tasks.size()); + for (Object context : tasks) { + String id = selectString(getSelector(ID), context); + String summary = selectString(getSelector(SUMMARY), context); + assert id != null && summary != null; + GenericTask task = new GenericTask(id, summary, myRepository); + if (!myRepository.getDownloadTasksInSeparateRequests()) { + String description = selectString(getSelector(DESCRIPTION), context); + if (description != null) { + task.setDescription(description); + } + String issueUrl = selectString(getSelector(ISSUE_URL), context); + if (issueUrl != null) { + task.setIssueUrl(issueUrl); + } + Boolean closed = selectBoolean(getSelector(CLOSED), context); + if (closed != null) { + task.setClosed(closed); + } + Date updated = selectDate(getSelector(UPDATED), context); + if (updated != null) { + task.setUpdated(updated); + } + Date created = selectDate(getSelector(CREATED), context); + if (created != null) { + task.setCreated(created); + } + } + result.add(task); + } + return result.toArray(new Task[result.size()]); } - protected abstract Task[] doParseIssues(String response) throws Exception; + @Nullable + private Date selectDate(@NotNull Selector selector, @NotNull Object context) throws Exception { + String s = selectString(selector, context); + if (s == null) { + return null; + } + return TaskUtil.parseDate(s); + } + + @Nullable + protected Boolean selectBoolean(@NotNull Selector selector, @NotNull Object context) throws Exception { + String s = selectString(selector, context); + if (s == null) { + return null; + } + s = s.trim().toLowerCase(); + if (s.equals("true")) { + return true; + } + else if (s.equals("false")) { + return false; + } + throw new Exception( + String.format("Expression '%s' should match boolean value. Got '%s' instead", selector.getName(), s)); + } + + @NotNull + protected abstract List<Object> selectTasksList(@NotNull String response, int max) throws Exception; + + @Nullable + protected abstract String selectString(@NotNull Selector selector, @NotNull Object context) throws Exception; @Nullable @Override public final Task parseIssue(String response) throws Exception { - if (StringUtil.isEmpty(getSelectorPath("singleTask-id")) || - StringUtil.isEmpty(getSelectorPath("singleTask-summary"))) { + if (StringUtil.isEmpty(getSelectorPath(SINGLE_TASK_ID)) || + StringUtil.isEmpty(getSelectorPath(SINGLE_TASK_SUMMARY))) { throw new Exception("Selectors 'singleTask-id' and 'singleTask-summary' are mandatory"); } - return doParseIssue(response); + String id = selectString(getSelector(SINGLE_TASK_ID), response); + String summary = selectString(getSelector(SINGLE_TASK_SUMMARY), response); + assert id != null && summary != null; + GenericTask task = new GenericTask(id, summary, myRepository); + String description = selectString(getSelector(SINGLE_TASK_DESCRIPTION), response); + if (description != null) { + task.setDescription(description); + } + String issueUrl = selectString(getSelector(SINGLE_TASK_ISSUE_URL), response); + if (issueUrl != null) { + task.setIssueUrl(issueUrl); + } + Boolean closed = selectBoolean(getSelector(SINGLE_TASK_CLOSED), response); + if (closed != null) { + task.setClosed(closed); + } + Date updated = selectDate(getSelector(SINGLE_TASK_UPDATED), response); + if (updated != null) { + task.setUpdated(updated); + } + Date created = selectDate(getSelector(SINGLE_TASK_CREATED), response); + if (created != null) { + task.setCreated(created); + } + return task; } - - protected abstract Task doParseIssue(String response) throws Exception; } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/XPathResponseHandler.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/XPathResponseHandler.java index 97dfc0731fc4..f768258d817d 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/XPathResponseHandler.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/XPathResponseHandler.java @@ -1,42 +1,28 @@ package com.intellij.tasks.generic; import com.intellij.openapi.fileTypes.FileType; -import com.intellij.tasks.Task; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.containers.HashMap; import com.intellij.util.xmlb.annotations.Tag; import org.intellij.lang.xpath.XPathFileType; +import org.jdom.Document; +import org.jdom.Element; +import org.jdom.JDOMException; +import org.jdom.input.SAXBuilder; +import org.jdom.xpath.XPath; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.w3c.dom.Document; -import org.w3c.dom.NodeList; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.xpath.XPathConstants; -import javax.xml.xpath.XPathExpression; -import javax.xml.xpath.XPathFactory; -import java.io.ByteArrayInputStream; -import java.util.ArrayList; +import java.io.StringReader; +import java.util.List; +import java.util.Map; /** * @author Mikhail Golubev */ @Tag("XPathResponseHandler") public final class XPathResponseHandler extends SelectorBasedResponseHandler { - private final static DocumentBuilder ourDocumentBuilder = createDocumentBuilder(); - private static DocumentBuilder createDocumentBuilder() { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - try { - return factory.newDocumentBuilder(); - } catch (ParserConfigurationException e) { - throw new AssertionError("Can't create DocumentBuilder"); - } - } - - private final static XPathFactory ourXPathFactory = createXPathFactory(); - private static XPathFactory createXPathFactory() { - return XPathFactory.newInstance(); - } + private final Map<String, XPath> myCompiledCache = new HashMap<String, XPath>(); /** * Serialization constructor @@ -50,44 +36,52 @@ public final class XPathResponseHandler extends SelectorBasedResponseHandler { super(repository); } + @NotNull @Override - public FileType getSelectorFileType() { - return XPathFileType.XPATH2; + protected List<Object> selectTasksList(@NotNull String response, int max) throws Exception { + Document document = new SAXBuilder(false).build(new StringReader(response)); + Element root = document.getRootElement(); + XPath xPath = lazyCompile(getSelector(TASKS).getPath()); + @SuppressWarnings("unchecked") + List<Object> rawTaskElements = xPath.selectNodes(root); + if (!rawTaskElements.isEmpty() && !(rawTaskElements.get(0) instanceof Element)) { + throw new Exception(String.format("Expression '%s' should match list of XML elements. Got '%s' instead.", + xPath.getXPath(), rawTaskElements.toString())); + } + return rawTaskElements.subList(0, Math.min(rawTaskElements.size(), max)); } + @Nullable @Override - public Task[] doParseIssues(String response) throws Exception { - String idSelector = getSelectorPath("id"), summarySelector = getSelectorPath("summary"); - if (idSelector == null || summarySelector == null) { - throw new IllegalArgumentException("Selectors 'task', 'id' and 'summary' are mandatory"); + protected String selectString(@NotNull Selector selector, @NotNull Object context) throws Exception { + if (StringUtil.isEmpty(selector.getPath())) { + return null; } - - Document document = ourDocumentBuilder.parse(new ByteArrayInputStream(response.getBytes())); - - XPathExpression idPath = ourXPathFactory.newXPath().compile(idSelector); - NodeList idNodes = (NodeList)idPath.evaluate(document, XPathConstants.NODESET); - - XPathExpression summaryPath = ourXPathFactory.newXPath().compile(summarySelector); - NodeList summaryNodes = (NodeList)summaryPath.evaluate(document, XPathConstants.NODESET); - - if (summaryNodes.getLength() != idNodes.getLength()) { - // popup will be shown to the user - throw new IllegalArgumentException("Number of tasks selected by 'id' and 'summary' XPath expressions is not the same."); + XPath xPath = lazyCompile(selector.getPath()); + String s = xPath.valueOf(context); + if (s == null) { + throw new Exception(String.format("XPath expression '%s' doesn't match", xPath.getXPath())); } + return s; + } - ArrayList<Task> tasks = new ArrayList<Task>(idNodes.getLength()); - for (int i = 0; i < idNodes.getLength(); i++) { - String id = idNodes.item(i).getNodeValue(); - String summary = summaryNodes.item(i).getNodeValue(); - tasks.add(new GenericTask(id, summary, myRepository)); + @NotNull + private XPath lazyCompile(@NotNull String path) throws Exception { + if (!myCompiledCache.containsKey(path)) { + try { + final XPath compiled = XPath.newInstance(path); + myCompiledCache.put(path, compiled); + } + catch (JDOMException e) { + throw new Exception(String.format("Malformed XPath expression '%s'", path)); + } } - return tasks.toArray(new Task[tasks.size()]); + return myCompiledCache.get(path); } - @Nullable @Override - public Task doParseIssue(String response) throws Exception { - return null; + public FileType getSelectorFileType() { + return XPathFileType.XPATH; } @Override diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/connectors/asana.xml b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/connectors/asana.xml index b374b7f8e51f..942ca6f7f68a 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/connectors/asana.xml +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/connectors/asana.xml @@ -1,13 +1,14 @@ <Generic shared="false" url="https://app.asana.com/api/1.0"> <commitMessageFormat>{id} {summary}</commitMessageFormat> <password/> + <option name="downloadTasksInSeparateRequests" value="true" /> <option name="loginAnonymously" value="false"/> <option name="loginMethodType" value="GET"/> <option name="loginUrl" value=""/> <option name="responseHandlers"> <XPathResponseHandler> <selectors> - <selector name="tasks" path="foo"/> + <selector name="tasks" path=""/> <selector name="id" path=""/> <selector name="summary" path=""/> <selector name="description" path=""/> @@ -30,7 +31,7 @@ <selector name="description" path=""/> <selector name="updated" path=""/> <selector name="created" path=""/> - <selector name="completed" path=""/> + <selector name="closed" path=""/> <selector name="issueUrl" path=""/> <selector name="singleTask-id" path="data.id"/> <selector name="singleTask-summary" path="data.name"/> diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java index fb2c776406ec..4c939830e4f4 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java @@ -771,7 +771,7 @@ public class TaskManagerImpl extends TaskManager implements ProjectComponent, Pe Task[] tasks = repository.getIssues(request, max, since, cancelled); myBadRepositories.remove(repository); if (issues == null) issues = new ArrayList<Task>(tasks.length); - if (!repository.isSupported(TaskRepository.NATIVE_SEARCH)) { + if (!repository.isSupported(TaskRepository.NATIVE_SEARCH) && request != null) { List<Task> filteredTasks = TaskSearchSupport.filterTasks(request, ContainerUtil.list(tasks)); ContainerUtil.addAll(issues, filteredTasks); } else { diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUtil.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUtil.java index 6a386f9760c0..b37a07a1628f 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUtil.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUtil.java @@ -22,7 +22,6 @@ import com.intellij.tasks.TaskRepository; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; @@ -33,9 +32,10 @@ import java.util.regex.Pattern; * @author Dmitry Avdeev */ public class TaskUtil { - - private static final Pattern DATE_PATTERN = Pattern.compile("(\\d\\d\\d\\d[/-]\\d\\d[/-]\\d\\d).*(\\d\\d:\\d\\d:\\d\\d).*"); - private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); + private static SimpleDateFormat ISO8601_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + // Almost ISO-8601 strict except date parts may be separated by '/' as well + private static Pattern ISO8601_DATE_PATTERN = Pattern.compile( + "(\\d{4}[/-]\\d{2}[/-]\\d{2})[ T](\\d{2}:\\d{2}:\\d{2})(.\\d{3,})?([+-]\\d{2}:\\d{2}|[+-]\\d{4}|[+-]\\d{2}|Z)?"); public static String formatTask(@NotNull Task task, String format) { return format.replace("{id}", task.getId()).replace("{number}", task.getNumber()) @@ -62,11 +62,34 @@ public class TaskUtil { } @Nullable - public static Date parseDate(String date) throws ParseException { - final Matcher m = DATE_PATTERN.matcher(date); - if (m.find()) { - return DATE_FORMAT.parse(m.group(1).replace('-', '/') + " " + m.group(2)); + public static Date parseDate(@NotNull String s) { + // SimpleDateFormat prior JDK7 doesn't support 'X' specifier for ISO 8601 timezone format. + // Because some bug trackers and task servers e.g. send dates ending with 'Z' (that stands for UTC), + // dates should be preprocessed before parsing. + Matcher m = ISO8601_DATE_PATTERN.matcher(s); + if (!m.matches()) { + return null; + } + String datePart = m.group(1).replace('/', '-'); + String timePart = m.group(2); + String milliseconds = m.group(3); + milliseconds = milliseconds == null? "000" : milliseconds.substring(1, 4); + String timezone = m.group(4); + if (timezone == null || timezone.equals("Z")) { + timezone = "+0000"; + } else if (timezone.length() == 3) { + // [+-]HH + timezone += "00"; + } else if (timezone.length() == 6) { + // [+-]HH:MM + timezone = timezone.substring(0, 3) + timezone.substring(4, 6); + } + String canonicalForm = String.format("%sT%s.%s%s", datePart, timePart, milliseconds, timezone); + try { + return ISO8601_DATE_FORMAT.parse(canonicalForm); + } + catch (ParseException e) { + return null; } - return null; } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java index 847d7b17d4cb..f1571fb61447 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java @@ -9,6 +9,7 @@ import com.intellij.tasks.TaskRepository; import com.intellij.tasks.TaskType; import com.intellij.tasks.impl.BaseRepository; import com.intellij.tasks.impl.BaseRepositoryImpl; +import com.intellij.tasks.impl.TaskUtil; import com.intellij.util.NullableFunction; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.xmlb.annotations.Tag; @@ -172,6 +173,7 @@ public class RedmineRepository extends BaseRepositoryImpl { }; } + @Nullable private static Date parseDate(Element element, String name) throws ParseException { final String date = element.getChildText(name); if (date.matches(".*\\+\\d\\d:\\d\\d")) { @@ -180,7 +182,16 @@ public class RedmineRepository extends BaseRepositoryImpl { format.setTimeZone(TimeZone.getTimeZone("GMT" + date.substring(timeZoneIndex))); return format.parse(date.substring(0, timeZoneIndex)); } - return (new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.US)).parse(date); + // Ad-hoc fix for IDEA-110012 + Date parsed; + try { + parsed = (new SimpleDateFormat("EEE MMM dd HH:mm:ss Z yyyy", Locale.US)).parse(date); + } + catch (ParseException e) { + LOG.warn("Unparseable date: " + date, e); + parsed = TaskUtil.parseDate(date); + } + return parsed; } @Override diff --git a/plugins/tasks/tasks-tests/tasks-tests.iml b/plugins/tasks/tasks-tests/tasks-tests.iml index a1d500107e02..deeddccdb91f 100644 --- a/plugins/tasks/tasks-tests/tasks-tests.iml +++ b/plugins/tasks/tasks-tests/tasks-tests.iml @@ -18,8 +18,6 @@ <orderEntry type="module" module-name="xslt-debugger" /> <orderEntry type="module" module-name="xdebugger-impl" scope="TEST" /> <orderEntry type="module" module-name="git4idea" scope="TEST" /> - <orderEntry type="module" module-name="remote-servers-impl" scope="TEST" /> - <orderEntry type="module" module-name="manifest" scope="TEST" /> </component> </module> diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AsanaGenericIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AsanaGenericIntegrationTest.java index 1a6d3bf41035..8bb2fec45f40 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AsanaGenericIntegrationTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AsanaGenericIntegrationTest.java @@ -53,7 +53,7 @@ public class AsanaGenericIntegrationTest extends TaskManagerTestCase { } public void testParsing() throws Exception { - Task[] tasks = myRepository.getActiveResponseHandler().parseIssues(RESPONSE); + Task[] tasks = myRepository.getActiveResponseHandler().parseIssues(RESPONSE, 50); List<Task> expected = ContainerUtil.<Task>newArrayList( new GenericTask("5479650606120", "Task #1", myRepository), new GenericTask("5202014833559", "Task #2", myRepository) diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java index 43a8af6043ff..28723a65d587 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java @@ -63,7 +63,7 @@ public class AssemblaIntegrationTest extends TaskManagerTestCase { public void testParseCyrillic() throws Exception { AssemblaRepository repository = new AssemblaRepository(new AssemblaRepositoryType()); - Task[] tasks = repository.getActiveResponseHandler().parseIssues(RESPONSE); + Task[] tasks = repository.getActiveResponseHandler().parseIssues(RESPONSE, 50); assertEquals(1, tasks.length); assertEquals("\u041F\u0440\u0438\u0432\u0435\u0442", tasks[0].getSummary()); } diff --git a/plugins/terminal/lib/jediterm-pty-0.08.jar b/plugins/terminal/lib/jediterm-pty-0.08.jar Binary files differindex e9bf3366fd6e..0e3c22395e8e 100644 --- a/plugins/terminal/lib/jediterm-pty-0.08.jar +++ b/plugins/terminal/lib/jediterm-pty-0.08.jar diff --git a/plugins/terminal/lib/pty4j-0.3.jar b/plugins/terminal/lib/pty4j-0.3.jar Binary files differindex a4d2cb998c44..67200e1203af 100644 --- a/plugins/terminal/lib/pty4j-0.3.jar +++ b/plugins/terminal/lib/pty4j-0.3.jar diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/AbstractTerminalRunner.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/AbstractTerminalRunner.java index 0ddfd9f18b6f..c1ceb923a569 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/AbstractTerminalRunner.java +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/AbstractTerminalRunner.java @@ -19,6 +19,7 @@ import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.util.ui.UIUtil; +import com.jediterm.pty.PtyProcessTtyConnector; import com.jediterm.terminal.TtyConnector; import com.jediterm.terminal.emulator.ColorPalette; import com.jediterm.terminal.ui.AbstractSystemSettingsProvider; @@ -30,6 +31,7 @@ import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.util.ArrayList; +import java.util.List; import java.util.concurrent.ExecutionException; /** @@ -191,7 +193,7 @@ public abstract class AbstractTerminalRunner<T extends Process> { } private KeyStroke[] getKeyStrokesByActionId(String actionId) { - java.util.List<KeyStroke> keyStrokes = new ArrayList<KeyStroke>(); + List<KeyStroke> keyStrokes = new ArrayList<KeyStroke>(); Shortcut[] shortcuts = KeymapManager.getInstance().getActiveKeymap().getShortcuts(actionId); for (Shortcut sc : shortcuts) { if (sc instanceof KeyboardShortcut) { @@ -202,6 +204,11 @@ public abstract class AbstractTerminalRunner<T extends Process> { return keyStrokes.toArray(new KeyStroke[keyStrokes.size()]); } + + @Override + public boolean shouldCloseTabOnLogout(TtyConnector ttyConnector) { + return ttyConnector instanceof PtyProcessTtyConnector; //close tab only on logout of local pty, not remote + } } public void openSession(TerminalWidget terminalWidget) { diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTabbedTerminalWidget.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTabbedTerminalWidget.java index 53d52f89e5da..051a5a54359d 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTabbedTerminalWidget.java +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTabbedTerminalWidget.java @@ -1,16 +1,43 @@ package org.jetbrains.plugins.terminal; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.project.DumbAwareAction; import com.jediterm.terminal.ui.JediTermWidget; import com.jediterm.terminal.ui.SystemSettingsProvider; import com.jediterm.terminal.ui.TabbedTerminalWidget; +import com.jediterm.terminal.ui.TerminalAction; import org.jetbrains.annotations.NotNull; +import javax.swing.*; +import java.awt.event.KeyEvent; +import java.util.List; + /** * @author traff */ public class JBTabbedTerminalWidget extends TabbedTerminalWidget { public JBTabbedTerminalWidget(@NotNull SystemSettingsProvider settingsProvider) { super(settingsProvider); + + convertActions(this, getActions()); + } + + public static void convertActions(JComponent component, List<TerminalAction> actions) { + for (final TerminalAction action : actions) { + AnAction a = new DumbAwareAction() { + @Override + public void actionPerformed(AnActionEvent e) { + if (e.getInputEvent() instanceof KeyEvent) { + action.perform((KeyEvent)e.getInputEvent()); + } + else { + action.perform(null); + } + } + }; + a.registerCustomShortcutSet(action.getKeyCode(), action.getModifiers(), component); + } } @Override diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalPanel.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalPanel.java index 7a83c324fba1..e5b6e533e705 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalPanel.java +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalPanel.java @@ -62,6 +62,8 @@ public class JBTerminalPanel extends TerminalPanel { TerminalColor.awt(myColorScheme.getColor(EditorColors.SELECTION_BACKGROUND_COLOR)))); setLineSpace(myColorScheme.getConsoleLineSpacing()); + + JBTabbedTerminalWidget.convertActions(this, getActions()); } protected Font createFont() { @@ -116,6 +118,11 @@ public class JBTerminalPanel extends TerminalPanel { protected BufferedImage createBufferedImage(int width, int height) { return UIUtil.createImage(width, height, BufferedImage.TYPE_INT_ARGB); } + + @Override + protected void drawImage(Graphics2D g, BufferedImage image) { + UIUtil.drawImage(g, image, null, 0, 0); + } public String getFontName() { List<String> fonts = myColorScheme.getConsoleFontPreferences().getEffectiveFontFamilies(); @@ -125,7 +132,7 @@ public class JBTerminalPanel extends TerminalPanel { return font; } } - return "Monospaced-14"; + return super.getFontName(); } private static boolean isApplicable(String font) { diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalWidget.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalWidget.java index 1701a18926a7..6f2e49da3f27 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalWidget.java +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalWidget.java @@ -28,6 +28,8 @@ public class JBTerminalWidget extends JediTermWidget { public JBTerminalWidget(SystemSettingsProvider settingsProvider) { super(settingsProvider); + + JBTabbedTerminalWidget.convertActions(this, getActions()); } @Override diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalView.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalView.java index 73c8d69ea2e6..bd7cfd23675e 100644 --- a/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalView.java +++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/TerminalView.java @@ -4,12 +4,15 @@ import com.intellij.icons.AllIcons; import com.intellij.notification.EventLog; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.SimpleToolWindowPanel; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentFactory; +import com.jediterm.terminal.ui.JediTermWidget; +import com.jediterm.terminal.ui.TabbedTerminalWidget; import com.jediterm.terminal.ui.TerminalWidget; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; @@ -26,7 +29,7 @@ public class TerminalView { private JBTabbedTerminalWidget myTerminalWidget; private Project myProject; - public void initTerminal(Project project, ToolWindow toolWindow) { + public void initTerminal(Project project, final ToolWindow toolWindow) { myProject = project; LocalTerminalDirectRunner terminalRunner = OpenLocalTerminalAction.createTerminalRunner(project); @@ -34,6 +37,12 @@ public class TerminalView { if (terminalRunner != null) { myTerminalWidget = terminalRunner.createTerminalWidget(); + myTerminalWidget.addTabListener(new TabbedTerminalWidget.TabListener() { + @Override + public void tabClosed(JediTermWidget terminal) { + hideIfNoActiveSessions(toolWindow, myTerminalWidget); + } + }); } Content content = createToolWindowContentPanel(terminalRunner, myTerminalWidget, toolWindow); @@ -142,7 +151,20 @@ public class TerminalView { }, true); } - private static class NewSession extends AnAction { + private void hideIfNoActiveSessions(final ToolWindow toolWindow, JBTabbedTerminalWidget terminal) { + if (terminal.isNoActiveSessions()) { + toolWindow.getContentManager().removeAllContents(true); + + toolWindow.getActivation().doWhenDone(new Runnable() { + @Override + public void run() { + initTerminal(myProject, toolWindow); + } + }); + } + } + + private static class NewSession extends DumbAwareAction { private final LocalTerminalDirectRunner myTerminalRunner; private final TerminalWidget myTerminal; @@ -158,7 +180,7 @@ public class TerminalView { } } - private class CloseSession extends AnAction { + private class CloseSession extends DumbAwareAction { private final JBTabbedTerminalWidget myTerminal; private ToolWindow myToolWindow; @@ -170,20 +192,9 @@ public class TerminalView { @Override public void actionPerformed(AnActionEvent e) { - boolean singleSession = myTerminal.isSingleSession(); - myTerminal.closeCurrentSession(); - - if (singleSession) { - myToolWindow.getContentManager().removeAllContents(true); - - myToolWindow.getActivation().doWhenDone(new Runnable() { - @Override - public void run() { - initTerminal(myProject, myToolWindow); - } - }); - } + + hideIfNoActiveSessions(myToolWindow, myTerminal); } } } diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/LoaderFactory.java b/plugins/ui-designer/src/com/intellij/uiDesigner/LoaderFactory.java index 66d349a79bd4..4b95eefa8976 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/LoaderFactory.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/LoaderFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 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. @@ -55,7 +55,7 @@ public final class LoaderFactory { public static LoaderFactory getInstance(final Project project) { return ServiceManager.getService(project, LoaderFactory.class); } - + public LoaderFactory(final Project project) { myProject = project; myModule2ClassLoader = new ConcurrentWeakHashMap<Module, ClassLoader>(); @@ -155,7 +155,7 @@ public final class LoaderFactory { private final String myModuleName; public DesignTimeClassLoader(final List<URL> urls, final ClassLoader parent, final String moduleName) { - super(urls, parent); + super(build().urls(urls).parent(parent)); myModuleName = moduleName; } |