diff --git a/.idea/libraries/junit5_rt.xml b/.idea/libraries/junit5_rt.xml
new file mode 100644
index 000000000000..5a0fe646a47b
--- /dev/null
+++ b/.idea/libraries/junit5_rt.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/opentest4j.xml b/.idea/libraries/opentest4j.xml
new file mode 100644
index 000000000000..a950465a1404
--- /dev/null
+++ b/.idea/libraries/opentest4j.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 15c4ae1ce18a..98246cf2ab4c 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -151,6 +151,7 @@
+
diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant
index e7cc2e2458d8..8a75218a72ca 100644
--- a/build/scripts/layouts.gant
+++ b/build/scripts/layouts.gant
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2015 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -472,6 +472,12 @@ public def layoutCommunityPlugins(String home, boolean maySkipAndroidPlugin = fa
jar("junit-rt.jar") {
module("junit_rt")
}
+ jar("junit5-rt.jar") {
+ module("junit5_rt")
+ }
+ fileset(dir: "$home/plugins/junit5_rt/lib") {
+ include(name: "*.jar")
+ }
}
pluginDir("ByteCodeViewer") {
@@ -955,7 +961,6 @@ def layout_core(String home, String target) {
module("util")
module("core-api")
module("core-impl")
- module("boot")
module("extensions")
module("java-psi-api")
module("java-psi-impl")
diff --git a/build/scripts/libLicenses.gant b/build/scripts/libLicenses.gant
index 3f0eaf561e28..9b61c888ba32 100644
--- a/build/scripts/libLicenses.gant
+++ b/build/scripts/libLicenses.gant
@@ -244,6 +244,7 @@ libraryLicense(name: "jsr305", libraryName: "jsr305", version: "snapshot", licen
libraryLicense(name: "Jsr305", version: "1.3.9", license: "New BSD", url: "http://code.google.com/p/jsr-305/", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause")
libraryLicense(name: "JUnit", libraryName: "JUnit3", version: "3.8.1", license: "CPL 1.0", url: "http://junit.org/")
libraryLicense(name: "JUnit", libraryName: "JUnit4", version: "4.11", license: "CPL 1.0", url: "http://junit.org/")
+libraryLicense(name: "junit5_rt", libraryName: "junit5_rt", version: "5.0.0", license: "Eclipse Public License 1.0", url: "http://junit.org/")
libraryLicense(name: "jzlib", libraryName: "jzlib", version: "1.1.1", license: "BSD", url: "http://www.jcraft.com/jzlib/", licenseUrl: "http://www.jcraft.com/jzlib/LICENSE.txt")
libraryLicense(name: "Kryo", libraryName: "Kryo", version: "2.22", license: "New BSD License", url: "https://github.com/EsotericSoftware/kryo", licenseUrl: "https://github.com/EsotericSoftware/kryo/blob/master/license.txt")
libraryLicense(name: "kXML2", libraryName: "kxml2", version: "2.3.0", license: "BSD", url: "http://sourceforge.net/projects/kxml/")
@@ -266,6 +267,7 @@ libraryLicense(name: "NanoXML", version: "2.2.3", license: "zlib/libpng", url: "
libraryLicense(name: "nekohtml", libraryName: "nekohtml", version: "1.9.14", license: "Apache 2.0", url: "http://nekohtml.sourceforge.net/", licenseUrl: "http://apache.org/licenses/LICENSE-2.0.txt")
libraryLicense(name: "Netty", libraryName: "Netty", version: "4.1.0.Beta3", license: "Apache 2.0", url: "http://netty.io", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0")
libraryLicense(name: "Objenesis", libraryName: "objenesis-1.2.jar", version: "1.2", license: "Apache 2.0", url: "http://objenesis.org/", licenseUrl: "http://apache.org/licenses/LICENSE-2.0")
+libraryLicense(name: "opentest4j", libraryName: "opentest4j", version: "1.0.0", license: "Apache 2.0", url: "https://github.com/ota4j-team/opentest4j", licenseUrl: "http://apache.org/licenses/LICENSE-2.0")
libraryLicense(name: "pep8.py", attachedTo: "python-helpers", version: "1.6.2", license: "MIT", url: "http://pep8.readthedocs.org/")
libraryLicense(name: "PicoContainer", libraryName: "picocontainer", version: "1.2", license: "BSD", url: "http://www.picocontainer.org/", licenseUrl: "http://docs.codehaus.org/display/PICO/License")
libraryLicense(name: "plexus-archiver", libraryName: "plexus-archiver-2.4.4.jar", version: "2.4.4", license: "Apache 2.0", url: "https://github.com/codehaus-plexus/plexus-archiver", licenseUrl: "http://apache.org/licenses/LICENSE-2.0")
diff --git a/java/debugger/impl/debugger-impl.iml b/java/debugger/impl/debugger-impl.iml
index b35289246ebb..3a9669db998f 100644
--- a/java/debugger/impl/debugger-impl.iml
+++ b/java/debugger/impl/debugger-impl.iml
@@ -21,8 +21,6 @@
-
-
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/CodeFragmentFactoryContextWrapper.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/CodeFragmentFactoryContextWrapper.java
index f790a0bf68ce..6183d59f03c4 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/CodeFragmentFactoryContextWrapper.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/CodeFragmentFactoryContextWrapper.java
@@ -26,6 +26,7 @@ import com.intellij.psi.JavaRecursiveElementVisitor;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLocalVariable;
import com.intellij.util.StringBuilderSpinAllocator;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebuggerManager;
import com.intellij.xdebugger.impl.XDebugSessionImpl;
@@ -87,7 +88,7 @@ public class CodeFragmentFactoryContextWrapper extends CodeFragmentFactory {
XValueMarkers, ?> markers = ((XDebugSessionImpl)session).getValueMarkers();
Map, ValueMarkup> markupMap = markers != null ? markers.getAllMarkers() : null;
//final Map markupMap = ValueDescriptorImpl.getMarkupMap(process);
- if (markupMap != null && markupMap.size() > 0) {
+ if (!ContainerUtil.isEmpty(markupMap)) {
final Pair> markupVariables = createMarkupVariablesText(markupMap);
int offset = markupVariables.getFirst().length() - 1;
final TextWithImportsImpl textWithImports = new TextWithImportsImpl(CodeFragmentKind.CODE_BLOCK, markupVariables.getFirst(), "", myDelegate.getFileType());
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/CatchEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/CatchEvaluator.java
new file mode 100644
index 000000000000..0ad17237fec4
--- /dev/null
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/CatchEvaluator.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.debugger.engine.evaluation.expression;
+
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
+import com.sun.jdi.ObjectReference;
+
+/**
+ * @author egor
+ */
+public class CatchEvaluator implements Evaluator {
+ private final String myExceptionType;
+ private final String myParamName;
+ private final CodeFragmentEvaluator myEvaluator;
+
+ public CatchEvaluator(String exceptionType, String paramName, CodeFragmentEvaluator evaluator) {
+ myExceptionType = exceptionType;
+ myParamName = paramName;
+ myEvaluator = evaluator;
+ }
+
+ public Object evaluate(ObjectReference exception, EvaluationContextImpl context) throws EvaluateException {
+ myEvaluator.setValue(myParamName, exception);
+ return myEvaluator.evaluate(context);
+ }
+
+ @Override
+ public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
+ throw new IllegalStateException("Use evaluate(ObjectReference exception, EvaluationContextImpl context)");
+ }
+
+ public String getExceptionType() {
+ return myExceptionType;
+ }
+
+ @Override
+ public Modifier getModifier() {
+ return null;
+ }
+}
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/CodeFragmentEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/CodeFragmentEvaluator.java
index 3575d76fab4f..f3fae7db1796 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/CodeFragmentEvaluator.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/CodeFragmentEvaluator.java
@@ -18,6 +18,7 @@ package com.intellij.debugger.engine.evaluation.expression;
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
+import com.intellij.debugger.engine.evaluation.EvaluateRuntimeException;
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.containers.HashMap;
@@ -103,10 +104,11 @@ public class CodeFragmentEvaluator extends BlockStatementEvaluator{
}
}
- public void setInitialValue(String localName, Object value) throws EvaluateException {
+ public void setInitialValue(String localName, Object value) {
LOG.assertTrue(!(value instanceof Value), "use setValue for jdi values");
if(hasValue(localName)) {
- throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.variable.already.declared", localName));
+ throw new EvaluateRuntimeException(
+ EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.variable.already.declared", localName)));
}
mySyntheticLocals.put(localName, value);
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java
index 291407a2989d..b0a57d5e5b98 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java
@@ -190,9 +190,51 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
@Override
public void visitTryStatement(PsiTryStatement statement) {
- throw new EvaluateRuntimeException(new UnsupportedExpressionException(statement.getText()));
+ if (statement.getResourceList() != null) {
+ throw new EvaluateRuntimeException(new UnsupportedExpressionException("Try with resources is not yet supported"));
+ }
+ Evaluator bodyEvaluator = accept(statement.getTryBlock());
+ if (bodyEvaluator != null) {
+ PsiCatchSection[] catchSections = statement.getCatchSections();
+ List evaluators = new ArrayList<>();
+ for (PsiCatchSection catchSection : catchSections) {
+ PsiParameter parameter = catchSection.getParameter();
+ PsiCodeBlock catchBlock = catchSection.getCatchBlock();
+ if (parameter != null && catchBlock != null) {
+ CodeFragmentEvaluator oldFragmentEvaluator = setNewCodeFragmentEvaluator();
+ try {
+ myCurrentFragmentEvaluator.setInitialValue(parameter.getName(), null);
+ myCurrentFragmentEvaluator.setStatements(visitStatements(catchBlock.getStatements()));
+ PsiType type = parameter.getType();
+ List types =
+ type instanceof PsiDisjunctionType ? ((PsiDisjunctionType)type).getDisjunctions() : Collections.singletonList(type);
+ for (PsiType psiType : types) {
+ evaluators.add(new CatchEvaluator(psiType.getCanonicalText(), parameter.getName(), myCurrentFragmentEvaluator));
+ }
+ }
+ finally{
+ myCurrentFragmentEvaluator = oldFragmentEvaluator;
+ }
+ }
+ }
+ myResult = new TryEvaluator(bodyEvaluator, evaluators, accept(statement.getFinallyBlock()));
+ }
}
+ @Override
+ public void visitThrowStatement(PsiThrowStatement statement) {
+ Evaluator accept = accept(statement.getException());
+ if (accept != null) {
+ myResult = new ThrowEvaluator(accept);
+ }
+ }
+
+ @Override
+ public void visitReturnStatement(PsiReturnStatement statement) {
+ myResult = new ReturnEvaluator(accept(statement.getReturnValue()));
+ }
+
+
@Override
public void visitStatement(PsiStatement statement) {
throwEvaluateException(DebuggerBundle.message("evaluation.error.statement.not.supported", statement.getText()));
@@ -204,25 +246,33 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
return old;
}
+ private Evaluator[] visitStatements(PsiStatement[] statements) {
+ Evaluator[] evaluators = new Evaluator[statements.length];
+ for (int i = 0; i < statements.length; i++) {
+ PsiStatement psiStatement = statements[i];
+ psiStatement.accept(this);
+ evaluators[i] = new DisableGC(myResult);
+ myResult = null;
+ }
+ return evaluators;
+ }
+
@Override
- public void visitBlockStatement(PsiBlockStatement statement) {
+ public void visitCodeBlock(PsiCodeBlock block) {
CodeFragmentEvaluator oldFragmentEvaluator = setNewCodeFragmentEvaluator();
try {
- PsiStatement[] statements = statement.getCodeBlock().getStatements();
- Evaluator[] evaluators = new Evaluator[statements.length];
- for (int i = 0; i < statements.length; i++) {
- PsiStatement psiStatement = statements[i];
- psiStatement.accept(this);
- evaluators[i] = new DisableGC(myResult);
- myResult = null;
- }
- myResult = new BlockStatementEvaluator(evaluators);
+ myResult = new BlockStatementEvaluator(visitStatements(block.getStatements()));
}
finally {
myCurrentFragmentEvaluator = oldFragmentEvaluator;
}
}
+ @Override
+ public void visitBlockStatement(PsiBlockStatement statement) {
+ visitCodeBlock(statement.getCodeBlock());
+ }
+
@Override
public void visitLabeledStatement(PsiLabeledStatement labeledStatement) {
PsiStatement statement = labeledStatement.getStatement();
@@ -259,33 +309,40 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
@Override
public void visitForStatement(PsiForStatement statement) {
- Evaluator initializerEvaluator = accept(statement.getInitialization());
- Evaluator conditionEvaluator = accept(statement.getCondition());
- if (conditionEvaluator != null) {
- conditionEvaluator = new UnBoxingEvaluator(conditionEvaluator);
- }
- Evaluator updateEvaluator = accept(statement.getUpdate());
- Evaluator bodyEvaluator = accept(statement.getBody());
- if (bodyEvaluator != null) {
- myResult = new ForStatementEvaluator(initializerEvaluator, conditionEvaluator, updateEvaluator, bodyEvaluator, getLabel(statement));
+ CodeFragmentEvaluator oldFragmentEvaluator = setNewCodeFragmentEvaluator();
+ try {
+ Evaluator initializerEvaluator = accept(statement.getInitialization());
+ Evaluator conditionEvaluator = accept(statement.getCondition());
+ if (conditionEvaluator != null) {
+ conditionEvaluator = new UnBoxingEvaluator(conditionEvaluator);
+ }
+ Evaluator updateEvaluator = accept(statement.getUpdate());
+ Evaluator bodyEvaluator = accept(statement.getBody());
+ if (bodyEvaluator != null) {
+ myResult =
+ new ForStatementEvaluator(initializerEvaluator, conditionEvaluator, updateEvaluator, bodyEvaluator, getLabel(statement));
+ }
+ } finally {
+ myCurrentFragmentEvaluator = oldFragmentEvaluator;
}
}
@Override
public void visitForeachStatement(PsiForeachStatement statement) {
+ CodeFragmentEvaluator oldFragmentEvaluator = setNewCodeFragmentEvaluator();
try {
String iterationParameterName = statement.getIterationParameter().getName();
myCurrentFragmentEvaluator.setInitialValue(iterationParameterName, null);
- SyntheticVariableEvaluator iterationParameterEvaluator = new SyntheticVariableEvaluator(myCurrentFragmentEvaluator, iterationParameterName);
+ SyntheticVariableEvaluator iterationParameterEvaluator =
+ new SyntheticVariableEvaluator(myCurrentFragmentEvaluator, iterationParameterName);
Evaluator iteratedValueEvaluator = accept(statement.getIteratedValue());
Evaluator bodyEvaluator = accept(statement.getBody());
if (bodyEvaluator != null) {
myResult = new ForeachStatementEvaluator(iterationParameterEvaluator, iteratedValueEvaluator, bodyEvaluator, getLabel(statement));
}
- }
- catch (EvaluateException e) {
- throw new EvaluateRuntimeException(e);
+ } finally {
+ myCurrentFragmentEvaluator = oldFragmentEvaluator;
}
}
@@ -538,9 +595,6 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
catch (IncorrectOperationException e) {
LOG.error(e);
}
- catch (EvaluateException e) {
- throw new EvaluateRuntimeException(e);
- }
PsiExpression initializer = localVariable.getInitializer();
if (initializer != null) {
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/ExpressionEvaluatorImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/ExpressionEvaluatorImpl.java
index 9c8ab0671541..b0e19e6ac527 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/ExpressionEvaluatorImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/ExpressionEvaluatorImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2015 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -72,6 +72,9 @@ public class ExpressionEvaluatorImpl implements ExpressionEvaluator {
myValue = (Value)value;
return myValue;
}
+ catch (ReturnEvaluator.ReturnException r) {
+ return (Value)r.getReturnValue();
+ }
catch (Throwable/*IncompatibleThreadStateException*/ e) {
if (LOG.isDebugEnabled()) {
LOG.debug(e);
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/ReturnEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/ReturnEvaluator.java
new file mode 100644
index 000000000000..a1b4057d04df
--- /dev/null
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/ReturnEvaluator.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.debugger.engine.evaluation.expression;
+
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author egor
+ */
+public class ReturnEvaluator implements Evaluator {
+ @Nullable private final Evaluator myReturnValueEvaluator;
+
+ public ReturnEvaluator(@Nullable Evaluator returnValueEvaluator) {
+ myReturnValueEvaluator = returnValueEvaluator;
+ }
+
+ @Override
+ public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
+ Object returnValue = myReturnValueEvaluator == null ?
+ context.getDebugProcess().getVirtualMachineProxy().mirrorOfVoid() :
+ myReturnValueEvaluator.evaluate(context);
+ throw new ReturnException(returnValue);
+ }
+
+ @Override
+ public Modifier getModifier() {
+ return null;
+ }
+
+ public static class ReturnException extends EvaluateException {
+ private final Object myReturnValue;
+
+ public ReturnException(Object returnValue) {
+ super("Return");
+ myReturnValue = returnValue;
+ }
+
+ public Object getReturnValue() {
+ return myReturnValue;
+ }
+ }
+}
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/ThrowEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/ThrowEvaluator.java
new file mode 100644
index 000000000000..b14bb4b371d9
--- /dev/null
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/ThrowEvaluator.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.debugger.engine.evaluation.expression;
+
+import com.intellij.debugger.DebuggerBundle;
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
+import com.sun.jdi.ObjectReference;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author egor
+ */
+public class ThrowEvaluator implements Evaluator {
+ @NotNull private final Evaluator myExceptionEvaluator;
+
+ public ThrowEvaluator(@NotNull Evaluator exceptionEvaluator) {
+ myExceptionEvaluator = exceptionEvaluator;
+ }
+
+ @Override
+ public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
+ ObjectReference exception = (ObjectReference)myExceptionEvaluator.evaluate(context);
+ EvaluateException ex = new EvaluateException(
+ DebuggerBundle.message("evaluation.error.method.exception", exception.referenceType().name()));
+ ex.setTargetException(exception);
+ throw ex;
+ }
+
+ @Override
+ public Modifier getModifier() {
+ return null;
+ }
+}
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/TryEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/TryEvaluator.java
new file mode 100644
index 000000000000..d3267e6f2ab6
--- /dev/null
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/TryEvaluator.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.debugger.engine.evaluation.expression;
+
+import com.intellij.debugger.engine.DebuggerUtils;
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
+import com.sun.jdi.ObjectReference;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author egor
+ */
+public class TryEvaluator implements Evaluator {
+ @NotNull private final Evaluator myBodyEvaluator;
+ private final List myCatchBlockEvaluators;
+ @Nullable private final Evaluator myFinallyEvaluator;
+
+ public TryEvaluator(@NotNull Evaluator bodyEvaluator,
+ List catchBlockEvaluators,
+ @Nullable Evaluator finallyEvaluator) {
+ myBodyEvaluator = bodyEvaluator;
+ myCatchBlockEvaluators = catchBlockEvaluators;
+ myFinallyEvaluator = finallyEvaluator;
+ }
+
+ @Override
+ public Object evaluate(EvaluationContextImpl context) throws EvaluateException {
+ Object result = context.getSuspendContext().getDebugProcess().getVirtualMachineProxy().mirrorOfVoid();
+ try {
+ result = myBodyEvaluator.evaluate(context);
+ } catch (EvaluateException e) {
+ boolean catched = false;
+ ObjectReference vmException = e.getExceptionFromTargetVM();
+ if (vmException != null) {
+ for (CatchEvaluator evaluator : myCatchBlockEvaluators) {
+ if (evaluator != null && DebuggerUtils.instanceOf(vmException.type(), evaluator.getExceptionType())) {
+ result = evaluator.evaluate(vmException, context);
+ catched = true;
+ break;
+ }
+ }
+ }
+ if (!catched) {
+ throw e;
+ }
+ } finally {
+ if (myFinallyEvaluator != null) {
+ result = myFinallyEvaluator.evaluate(context);
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public Modifier getModifier() {
+ return null;
+ }
+}
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/DebuggerUtils.java b/java/debugger/openapi/src/com/intellij/debugger/engine/DebuggerUtils.java
index 7819a3dd076d..542fd55570da 100644
--- a/java/debugger/openapi/src/com/intellij/debugger/engine/DebuggerUtils.java
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/DebuggerUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2015 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -153,10 +153,17 @@ public abstract class DebuggerUtils {
public static Method findMethod(@NotNull ReferenceType refType, @NonNls String methodName, @Nullable @NonNls String methodSignature) {
if (refType instanceof ArrayType) {
// for array types methodByName() in JDI always returns empty list
- final Method method = findMethod(refType.virtualMachine().classesByName(CommonClassNames.JAVA_LANG_OBJECT).get(0), methodName, methodSignature);
+ Method method = findMethod(refType.virtualMachine().classesByName(CommonClassNames.JAVA_LANG_OBJECT).get(0), methodName, methodSignature);
if (method != null) {
return method;
}
+ // for arrays, clone signature may return array of objects, there is no such method in Object class
+ if ("clone".equals(methodName) && "()[Ljava/lang/Object;".equals(methodSignature)) {
+ method = findMethod(refType.virtualMachine().classesByName(CommonClassNames.JAVA_LANG_OBJECT).get(0), "clone", null);
+ if (method != null) {
+ return method;
+ }
+ }
}
Method method = null;
diff --git a/java/execution/impl/src/com/intellij/execution/junit/InheritorChooser.java b/java/execution/impl/src/com/intellij/execution/junit/InheritorChooser.java
index 2f538f46db98..d52bb86f8fcc 100644
--- a/java/execution/impl/src/com/intellij/execution/junit/InheritorChooser.java
+++ b/java/execution/impl/src/com/intellij/execution/junit/InheritorChooser.java
@@ -21,13 +21,14 @@ import com.intellij.execution.junit2.PsiMemberParameterizedLocation;
import com.intellij.execution.junit2.info.MethodLocation;
import com.intellij.ide.util.PsiClassListCellRenderer;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Condition;
-import com.intellij.openapi.util.Conditions;
import com.intellij.psi.*;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.util.PsiClassUtil;
@@ -88,10 +89,11 @@ public class InheritorChooser {
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
@Override
public void run() {
+ final boolean isJUnit5 = ApplicationManager.getApplication().runReadAction((Computable)() -> JUnitUtil.isJUnit5(containingClass));
ClassInheritorsSearch.search(containingClass).forEach(new Processor() {
@Override
public boolean process(PsiClass aClass) {
- if (PsiClassUtil.isRunnableClass(aClass, true, true)) {
+ if (PsiClassUtil.isRunnableClass(aClass, !isJUnit5, true)) {
classes.add(aClass);
}
return true;
diff --git a/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java b/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java
index 74bf67d2c428..db073a2738d5 100644
--- a/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java
+++ b/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java
@@ -37,10 +37,7 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Iterator;
+import java.util.*;
@SuppressWarnings({"UtilityClassWithoutPrivateConstructor"})
public class JUnitUtil {
@@ -48,17 +45,38 @@ public class JUnitUtil {
@NonNls private static final String TEST_INTERFACE = "junit.framework.Test";
@NonNls private static final String TESTSUITE_CLASS = "junit.framework.TestSuite";
@NonNls public static final String TEST_ANNOTATION = "org.junit.Test";
+ @NonNls public static final String TEST5_ANNOTATION = "org.junit.gen5.api.Test";
@NonNls public static final String IGNORE_ANNOTATION = "org.junit.Ignore";
@NonNls public static final String RUN_WITH = "org.junit.runner.RunWith";
@NonNls public static final String DATA_POINT = "org.junit.experimental.theories.DataPoint";
@NonNls public static final String SUITE_METHOD_NAME = "suite";
+
public static final String BEFORE_ANNOTATION_NAME = "org.junit.Before";
public static final String AFTER_ANNOTATION_NAME = "org.junit.After";
+
+ public static final String BEFORE_EACH_ANNOTATION_NAME = "org.junit.gen5.api.BeforeEach";
+ public static final String AFTER_EACH_ANNOTATION_NAME = "org.junit.gen5.api.AfterEach";
+
public static final String PARAMETRIZED_PARAMETERS_ANNOTATION_NAME = "org.junit.runners.Parameterized.Parameters";
+
public static final String AFTER_CLASS_ANNOTATION_NAME = "org.junit.AfterClass";
public static final String BEFORE_CLASS_ANNOTATION_NAME = "org.junit.BeforeClass";
+
+ public static final String BEFORE_ALL_ANNOTATION_NAME = "org.junit.gen5.api.BeforeAll";
+ public static final String AFTER_ALL_ANNOTATION_NAME = "org.junit.gen5.api.AfterAll";
+
+ private static final Collection TEST_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(TEST_ANNOTATION, TEST5_ANNOTATION));
+
+ private static final List INSTANCE_CONFIGS = Arrays.asList(BEFORE_ANNOTATION_NAME, AFTER_ANNOTATION_NAME);
+ private static final List INSTANCE_5_CONFIGS = Arrays.asList(BEFORE_EACH_ANNOTATION_NAME, AFTER_EACH_ANNOTATION_NAME);
+
+ private static final List STATIC_5_CONFIGS = Arrays.asList(BEFORE_ALL_ANNOTATION_NAME, AFTER_ALL_ANNOTATION_NAME);
+
+ private static final List STATIC_CONFIGS = Arrays.asList(BEFORE_CLASS_ANNOTATION_NAME, AFTER_CLASS_ANNOTATION_NAME,
+ PARAMETRIZED_PARAMETERS_ANNOTATION_NAME);
private static final Collection CONFIGURATIONS_ANNOTATION_NAME = Collections.unmodifiableList(
- Arrays.asList(DATA_POINT, AFTER_ANNOTATION_NAME, BEFORE_ANNOTATION_NAME, AFTER_CLASS_ANNOTATION_NAME, BEFORE_CLASS_ANNOTATION_NAME));
+ Arrays.asList(DATA_POINT, AFTER_ANNOTATION_NAME, BEFORE_ANNOTATION_NAME, AFTER_CLASS_ANNOTATION_NAME, BEFORE_CLASS_ANNOTATION_NAME,
+ BEFORE_ALL_ANNOTATION_NAME, AFTER_ALL_ANNOTATION_NAME));
@NonNls public static final String PARAMETERIZED_CLASS_NAME = "org.junit.runners.Parameterized";
@NonNls public static final String SUITE_CLASS_NAME = "org.junit.runners.Suite";
@@ -126,17 +144,27 @@ public class JUnitUtil {
}
}
}
- if (!PsiClassUtil.isRunnableClass(psiClass, true, checkAbstract)) return false;
- if (checkForTestCaseInheritance && isTestCaseInheritor(psiClass)) return true;
final PsiModifierList modifierList = psiClass.getModifierList();
if (modifierList == null) return false;
if (AnnotationUtil.isAnnotated(psiClass, RUN_WITH, true)) return true;
+ final boolean hasJUnit5 = isJUnit5(modifierList);
+ if (!PsiClassUtil.isRunnableClass(psiClass, !hasJUnit5, checkAbstract)) return false;
+ if (checkForTestCaseInheritance && (!hasJUnit5 || psiClass.hasModifierProperty(PsiModifier.PUBLIC)) && isTestCaseInheritor(psiClass)) return true;
+
for (final PsiMethod method : psiClass.getAllMethods()) {
ProgressManager.checkCanceled();
if (isSuiteMethod(method)) return true;
if (isTestAnnotated(method)) return true;
}
+
+ if (hasJUnit5) {
+ for (PsiClass innerClass : psiClass.getInnerClasses()) {
+ for (PsiMethod method : innerClass.getAllMethods()) {
+ if (isTestAnnotated(method)) return true;
+ }
+ }
+ }
return false;
}
@@ -150,11 +178,12 @@ public class JUnitUtil {
}
private static boolean isJUnit4TestClass(final PsiClass psiClass, boolean checkAbstract) {
- if (!PsiClassUtil.isRunnableClass(psiClass, true, checkAbstract)) return false;
-
final PsiModifierList modifierList = psiClass.getModifierList();
if (modifierList == null) return false;
if (AnnotationUtil.isAnnotated(psiClass, RUN_WITH, true)) return true;
+
+ if (!PsiClassUtil.isRunnableClass(psiClass, !isJUnit5(modifierList), checkAbstract)) return false;
+
for (final PsiMethod method : psiClass.getAllMethods()) {
ProgressManager.checkCanceled();
if (isTestAnnotated(method)) return true;
@@ -163,8 +192,16 @@ public class JUnitUtil {
return false;
}
+ public static boolean isJUnit5(@NotNull PsiElement element) {
+ return isJUnit5(element.getResolveScope(), element.getProject());
+ }
+
+ public static boolean isJUnit5(GlobalSearchScope scope, Project project) {
+ return JavaPsiFacade.getInstance(project).findClass(TEST5_ANNOTATION, scope) != null;
+ }
+
public static boolean isTestAnnotated(final PsiMethod method) {
- if (AnnotationUtil.isAnnotated(method, TEST_ANNOTATION, false) || JUnitRecognizer.willBeAnnotatedAfterCompilation(method)) {
+ if (AnnotationUtil.isAnnotated(method, TEST_ANNOTATIONS, false) || JUnitRecognizer.willBeAnnotatedAfterCompilation(method)) {
final PsiAnnotation annotation = AnnotationUtil.findAnnotationInHierarchy(method.getContainingClass(), Collections.singleton(RUN_WITH));
if (annotation != null) {
final PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
@@ -240,18 +277,28 @@ public class JUnitUtil {
}
}
final String name = psiMethod.getName();
- if (psiMethod.hasModifierProperty(PsiModifier.PUBLIC) && !psiMethod.hasModifierProperty(PsiModifier.ABSTRACT)) {
- if (SUITE_METHOD_NAME.equals(name) || "setUp".equals(name) || "tearDown".equals(name)) {
+ final boolean isPublic = psiMethod.hasModifierProperty(PsiModifier.PUBLIC);
+ if (!psiMethod.hasModifierProperty(PsiModifier.ABSTRACT)) {
+ if (isPublic && (SUITE_METHOD_NAME.equals(name) || "setUp".equals(name) || "tearDown".equals(name))) {
return true;
}
+
if (psiMethod.hasModifierProperty(PsiModifier.STATIC)) {
- if (AnnotationUtil.isAnnotated(psiMethod, Arrays.asList(BEFORE_CLASS_ANNOTATION_NAME, AFTER_CLASS_ANNOTATION_NAME,
- PARAMETRIZED_PARAMETERS_ANNOTATION_NAME))) {
+ if (AnnotationUtil.isAnnotated(psiMethod, STATIC_CONFIGS)) {
+ return isPublic;
+ }
+ if (AnnotationUtil.isAnnotated(psiMethod, STATIC_5_CONFIGS)) {
return true;
}
}
else {
- if (AnnotationUtil.isAnnotated(psiMethod, Arrays.asList(BEFORE_ANNOTATION_NAME, AFTER_ANNOTATION_NAME))) return true;
+ if (AnnotationUtil.isAnnotated(psiMethod, INSTANCE_CONFIGS)) {
+ return isPublic;
+ }
+
+ if (AnnotationUtil.isAnnotated(psiMethod, INSTANCE_5_CONFIGS)) {
+ return true;
+ }
}
}
return false;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/AnnotateMethodFix.java b/java/java-analysis-impl/src/com/intellij/codeInspection/AnnotateMethodFix.java
index 6d4ac0cebcfa..721215762768 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/AnnotateMethodFix.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/AnnotateMethodFix.java
@@ -101,7 +101,7 @@ public class AnnotateMethodFix implements LocalQuickFix {
@Override
@NotNull
public String getFamilyName() {
- return getName();
+ return InspectionsBundle.message("inspection.annotate.method.quickfix.family.name");
}
private void annotateMethod(@NotNull PsiMethod method) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspectionBase.java
index 0c8a33278d3c..b263fc278ffe 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspectionBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavaDocLocalInspectionBase.java
@@ -16,6 +16,7 @@
package com.intellij.codeInspection.javaDoc;
import com.intellij.ToolExtensionPoints;
+import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInspection.*;
import com.intellij.openapi.extensions.ExtensionPoint;
import com.intellij.openapi.extensions.Extensions;
@@ -168,16 +169,10 @@ public class JavaDocLocalInspectionBase extends BaseJavaBatchLocalInspectionTool
boolean required = aPackage != null && JavadocHighlightUtil.isJavaDocRequired(this, aPackage);
ProblemHolderImpl holder = new ProblemHolderImpl(manager, isOnTheFly);
- if (IGNORE_DEPRECATED) {
- if (aPackage != null) {
- PsiModifierList modifierList = aPackage.getModifierList();
- if (modifierList != null && modifierList.findAnnotation("java.lang.Deprecated") != null) {
- return null;
- }
- }
- if (docComment != null && docComment.findTagByName("deprecated") != null) {
- return null;
- }
+ if (IGNORE_DEPRECATED &&
+ (AnnotationUtil.findAnnotation(aPackage, CommonClassNames.JAVA_LANG_DEPRECATED) != null ||
+ docComment != null && docComment.findTagByName("deprecated") != null)) {
+ return null;
}
if (docComment == null) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavaDocReferenceInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavaDocReferenceInspectionBase.java
index d32a21279e9d..ecbe13ea09eb 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavaDocReferenceInspectionBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavaDocReferenceInspectionBase.java
@@ -248,7 +248,7 @@ public class JavaDocReferenceInspectionBase extends BaseJavaBatchLocalInspectio
@Override
@NotNull
public String getFamilyName() {
- return getName();
+ return "Remove tag";
}
@Override
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavadocHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavadocHighlightUtil.java
index 5a6697869b86..3a25e62e4fc4 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavadocHighlightUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/javaDoc/JavadocHighlightUtil.java
@@ -15,7 +15,8 @@
*/
package com.intellij.codeInspection.javaDoc;
-import com.intellij.codeInspection.*;
+import com.intellij.codeInspection.InspectionsBundle;
+import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.reference.RefJavaUtil;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.project.Project;
@@ -23,7 +24,9 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.javadoc.PsiDocParamRef;
+import com.intellij.psi.impl.source.tree.JavaDocElementType;
import com.intellij.psi.javadoc.*;
+import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
@@ -39,6 +42,8 @@ import java.util.stream.Stream;
public class JavadocHighlightUtil {
private static final String[] TAGS_TO_CHECK = {"author", "version", "since"};
private static final Set UNIQUE_TAGS = ContainerUtil.newHashSet("return", "deprecated", "serial", "serialData");
+ private static final TokenSet SEE_TAG_REFS = TokenSet.create(
+ JavaDocElementType.DOC_REFERENCE_HOLDER, JavaDocElementType.DOC_METHOD_OR_FIELD_REF);
public interface ProblemHolder {
Project project();
@@ -181,7 +186,18 @@ public class JavadocHighlightUtil {
}
}
- checkInlineTags(tag.getDataElements(), holder);
+ PsiElement[] dataElements = tag.getDataElements();
+
+ if ("see".equals(tagName)) {
+ if (dataElements.length == 0 || dataElements.length == 1 && empty(dataElements[0])) {
+ holder.problem(tag.getNameElement(), InspectionsBundle.message("inspection.javadoc.problem.see.tag.expecting.ref"), null);
+ }
+ else if (!SEE_TAG_REFS.contains(dataElements[0].getNode().getElementType())) {
+ holder.problem(dataElements[0], InspectionsBundle.message("inspection.javadoc.problem.see.tag.expecting.ref"), null);
+ }
+ }
+
+ checkInlineTags(dataElements, holder);
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/AnnotateOverriddenMethodParameterFix.java b/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/AnnotateOverriddenMethodParameterFix.java
index c1dbdbf78f0e..c00eb42484a9 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/AnnotateOverriddenMethodParameterFix.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/AnnotateOverriddenMethodParameterFix.java
@@ -98,6 +98,6 @@ public class AnnotateOverriddenMethodParameterFix implements LocalQuickFix {
@Override
@NotNull
public String getFamilyName() {
- return getName();
+ return InspectionsBundle.message("annotate.overridden.methods.parameters.family.name");
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspectionBase.java
index 27be172ae58a..accdc0b2b17b 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspectionBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspectionBase.java
@@ -42,6 +42,7 @@ import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspectionTool {
@@ -68,8 +69,8 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
return uncheckedCb;
}
- public static LocalQuickFix[] getChangeVariableTypeFixes(@NotNull PsiVariable parameter, PsiType itemType) {
- if (itemType instanceof PsiMethodReferenceType) return LocalQuickFix.EMPTY_ARRAY;
+ public static LocalQuickFix[] getChangeVariableTypeFixes(@NotNull PsiVariable parameter, PsiType itemType, LocalQuickFix[] generifyFixes) {
+ if (itemType instanceof PsiMethodReferenceType) return generifyFixes;
final List result = new ArrayList();
LOG.assertTrue(parameter.isValid());
if (itemType != null) {
@@ -81,6 +82,10 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
}
}
}
+
+ if (generifyFixes.length > 0) {
+ Collections.addAll(result, generifyFixes);
+ }
return result.toArray(new LocalQuickFix[result.size()]);
}
@@ -283,7 +288,7 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
if (initializer == null || initializer instanceof PsiArrayInitializerExpression) return;
final PsiType initializerType = initializer.getType();
checkRawToGenericsAssignment(initializer, initializer, variable.getType(), initializerType, true,
- myOnTheFly ? getChangeVariableTypeFixes(variable, initializerType) : LocalQuickFix.EMPTY_ARRAY);
+ myOnTheFly ? getChangeVariableTypeFixes(variable, initializerType, myGenerifyFixes) : LocalQuickFix.EMPTY_ARRAY);
}
@Override
@@ -295,7 +300,8 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
final PsiExpression iteratedValue = statement.getIteratedValue();
if (iteratedValue == null) return;
final PsiType itemType = JavaGenericsUtil.getCollectionItemType(iteratedValue);
- checkRawToGenericsAssignment(parameter, iteratedValue, parameterType, itemType, true, myOnTheFly ? getChangeVariableTypeFixes(parameter, itemType) : LocalQuickFix.EMPTY_ARRAY);
+ checkRawToGenericsAssignment(parameter, iteratedValue, parameterType, itemType, true, myOnTheFly ? getChangeVariableTypeFixes(parameter, itemType,
+ myGenerifyFixes) : LocalQuickFix.EMPTY_ARRAY);
}
@Override
@@ -316,7 +322,7 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe
leftVar = (PsiVariable)element;
}
}
- checkRawToGenericsAssignment(rExpr, rExpr, lType, rType, true, myOnTheFly && leftVar != null ? getChangeVariableTypeFixes(leftVar, rType) : LocalQuickFix.EMPTY_ARRAY);
+ checkRawToGenericsAssignment(rExpr, rExpr, lType, rType, true, myOnTheFly && leftVar != null ? getChangeVariableTypeFixes(leftVar, rType, myGenerifyFixes) : LocalQuickFix.EMPTY_ARRAY);
}
@Override
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java
index 919c6b447259..aca399d6b20e 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateLocalFromUsageFix.java
@@ -31,6 +31,8 @@ import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
+import com.intellij.refactoring.introduceParameter.AbstractJavaInplaceIntroducer;
+import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
import org.jetbrains.annotations.NotNull;
/**
@@ -73,7 +75,9 @@ public class CreateLocalFromUsageFix extends CreateVarFromUsageFix {
final PsiFile targetFile = targetClass.getContainingFile();
PsiType[] expectedTypes = CreateFromUsageUtils.guessType(myReferenceExpression, false);
- PsiType type = expectedTypes[0];
+ final SmartTypePointer defaultType = SmartTypePointerManager.getInstance(project).createSmartTypePointer(expectedTypes[0]);
+ final PsiType preferredType = TypeSelectorManagerImpl.getPreferredType(expectedTypes, expectedTypes[0]);
+ PsiType type = preferredType != null ? preferredType : expectedTypes[0];
String varName = myReferenceExpression.getReferenceName();
PsiExpression initializer = null;
@@ -116,7 +120,10 @@ public class CreateLocalFromUsageFix extends CreateVarFromUsageFix {
var = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(var);
if (var == null) return;
TemplateBuilderImpl builder = new TemplateBuilderImpl(var);
- builder.replaceElement(var.getTypeElement(), expression);
+ final PsiTypeElement typeElement = var.getTypeElement();
+ LOG.assertTrue(typeElement != null);
+ builder.replaceElement(typeElement,
+ AbstractJavaInplaceIntroducer.createExpression(expression, typeElement.getText()));
builder.setEndVariableAfter(var.getNameIdentifier());
Template template = builder.buildTemplate();
@@ -132,6 +139,8 @@ public class CreateLocalFromUsageFix extends CreateVarFromUsageFix {
final int offset = newEditor.getCaretModel().getOffset();
final PsiLocalVariable localVariable = PsiTreeUtil.findElementOfClassAtOffset(targetFile, offset, PsiLocalVariable.class, false);
if (localVariable != null) {
+ TypeSelectorManagerImpl.typeSelected(localVariable.getType(), defaultType.getType());
+
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MethodParameterFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MethodParameterFix.java
index 3ce3b66b3835..cf7fa5c74550 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MethodParameterFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MethodParameterFix.java
@@ -115,6 +115,11 @@ public class MethodParameterFix extends LocalQuickFixAndIntentionActionOnPsiElem
}
}
+ @Override
+ public boolean startInWriteAction() {
+ return false;
+ }
+
private ParameterInfoImpl[] getNewParametersInfo(PsiMethod method) throws IncorrectOperationException {
List result = new ArrayList();
PsiParameter[] parameters = method.getParameterList().getParameters();
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplacePrimitiveWithBoxedTypeAction.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplacePrimitiveWithBoxedTypeAction.java
index 95ed0c7cfb02..973a694657b9 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplacePrimitiveWithBoxedTypeAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ReplacePrimitiveWithBoxedTypeAction.java
@@ -46,7 +46,7 @@ public class ReplacePrimitiveWithBoxedTypeAction extends LocalQuickFixAndIntenti
@NotNull
@Override
public String getFamilyName() {
- return getText();
+ return "Convert primitive to boxed type";
}
@Override
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java
index 302e1faca415..85e0b4560bf4 100644
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java
@@ -595,10 +595,6 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta
css.addRule("p.problem-description-group {text-indent: " + JBUI.scale(12) + "px;font-weight:bold;}");
css.addRule("div.problem-description {margin-left: " + JBUI.scale(10) + "px;}");
css.addRule("ul {margin-left:" + JBUI.scale(10) + "px;text-indent: 0}");
- //TODO Dmitry Batkovich: it's hack to hide tags in JEditorPane (any standard methods (display...) are unsupported in java)
- final StringBuilder sb = new StringBuilder();
- UIUtil.appendColor(UIUtil.getLabelBackground(), sb);
- css.addRule(".package {color: #" + sb.toString() + ";}");
final StringBuffer buf = new StringBuffer();
getComposer().compose(buf, entity, false);
final String text = buf.toString();
diff --git a/java/java-impl/src/com/intellij/codeInspection/ex/HTMLJavaHTMLComposerImpl.java b/java/java-impl/src/com/intellij/codeInspection/ex/HTMLJavaHTMLComposerImpl.java
index ea448a93c7fc..a8382980e462 100644
--- a/java/java-impl/src/com/intellij/codeInspection/ex/HTMLJavaHTMLComposerImpl.java
+++ b/java/java-impl/src/com/intellij/codeInspection/ex/HTMLJavaHTMLComposerImpl.java
@@ -338,17 +338,20 @@ public class HTMLJavaHTMLComposerImpl extends HTMLJavaHTMLComposer {
buf.append(HTMLComposerImpl.CODE_CLOSING);
- if (refElement instanceof RefClass && ((RefClass)refElement).isAnonymous()) {
- buf.append(" ");
- buf.append(InspectionsBundle.message("inspection.export.results.anonymous.ref.in.owner"));
- buf.append(" ");
- myComposer.appendElementReference(buf, ((RefElement)refElement.getOwner()), isPackageIncluded);
- }
- else if (isPackageIncluded) {
- buf.append(" ").append("").append("(");
- myComposer.appendQualifiedName(buf, refElement.getOwner());
-// buf.append(RefUtil.getPackageName(refElement));
- buf.append(")").append(HTMLComposerImpl.CODE_CLOSING);
+ final RefEntity owner = refElement.getOwner();
+ if (owner != null) {
+ if ((refElement instanceof RefClass && ((RefClass)refElement).isAnonymous())) {
+ buf.append(" ");
+ buf.append(InspectionsBundle.message("inspection.export.results.anonymous.ref.in.owner"));
+ buf.append(" ");
+ myComposer.appendElementReference(buf, (RefElement) owner, isPackageIncluded);
+ }
+ else if (isPackageIncluded) {
+ buf.append(" ").append("").append("(");
+ myComposer.appendQualifiedName(buf, owner);
+ // buf.append(RefUtil.getPackageName(refElement));
+ buf.append(")").append(HTMLComposerImpl.CODE_CLOSING);
+ }
}
}
diff --git a/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java b/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java
index 5ac31e88f656..0a9415f38cc4 100644
--- a/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java
+++ b/java/java-impl/src/com/intellij/javadoc/JavadocConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2015 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -15,21 +15,17 @@
*/
package com.intellij.javadoc;
-import com.intellij.openapi.util.DefaultJDOMExternalizer;
-import com.intellij.openapi.util.InvalidDataException;
-import com.intellij.openapi.util.JDOMExternalizable;
-import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.PsiKeyword;
-import org.jdom.Element;
-import org.jetbrains.annotations.NotNull;
-
-import java.lang.reflect.Field;
+import com.intellij.util.xmlb.SerializationFilter;
/**
* @author Eugene Zhuravlev
- * Date: Apr 24, 2004
+ * @since Apr 24, 2004
*/
-public class JavadocConfiguration implements JDOMExternalizable {
+public class JavadocConfiguration {
+ public static final SerializationFilter FILTER = (accessor, bean) ->
+ !accessor.getName().equals("OPTION_LINK_TO_JDK_DOCS") || ((JavadocConfiguration)bean).OPTION_LINK_TO_JDK_DOCS;
+
public String OUTPUT_DIRECTORY;
public String OPTION_SCOPE = PsiKeyword.PROTECTED;
public boolean OPTION_HIERARCHY = true;
@@ -47,21 +43,4 @@ public class JavadocConfiguration implements JDOMExternalizable {
public boolean OPEN_IN_BROWSER = true;
public boolean OPTION_INCLUDE_LIBS = false;
public boolean OPTION_LINK_TO_JDK_DOCS = false;
-
- public JavadocConfiguration() {
- }
-
- public void readExternal(Element element) throws InvalidDataException {
- DefaultJDOMExternalizer.readExternal(this, element);
- }
-
- public void writeExternal(Element element) throws WriteExternalException {
- DefaultJDOMExternalizer.writeExternal(this, element, new DefaultJDOMExternalizer.JDOMFilter() {
- @Override
- public boolean isAccept(@NotNull Field field) {
- return !field.getName().equals("OPTION_LINK_TO_JDK_DOCS") || OPTION_LINK_TO_JDK_DOCS;
- }
- });
- }
-}
-
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java b/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java
index 7dbd51d06036..b94e25ce5399 100644
--- a/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java
+++ b/java/java-impl/src/com/intellij/javadoc/JavadocGenerationManager.java
@@ -24,17 +24,14 @@ import com.intellij.execution.util.ExecutionErrorDialog;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.components.State;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.InvalidDataException;
-import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.util.xmlb.XmlSerializer;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
@State(name = "JavadocGenerationManager")
public final class JavadocGenerationManager implements PersistentStateComponent {
- private static final Logger LOG = Logger.getInstance("#com.intellij.javadoc.JavadocGenerationManager");
- private final JavadocConfiguration myConfiguration;
+ private final JavadocConfiguration myConfiguration = new JavadocConfiguration();
private final Project myProject;
public static JavadocGenerationManager getInstance(@NotNull Project project) {
@@ -43,31 +40,19 @@ public final class JavadocGenerationManager implements PersistentStateComponent<
JavadocGenerationManager(Project project) {
myProject = project;
- myConfiguration = new JavadocConfiguration();
}
@Override
public Element getState() {
- final Element state = new Element("state");
- try {
- myConfiguration.writeExternal(state);
- }
- catch (WriteExternalException e) {
- LOG.error(e);
- }
- return state;
+ return XmlSerializer.serialize(myConfiguration, JavadocConfiguration.FILTER);
}
@Override
public void loadState(Element state) {
- try {
- myConfiguration.readExternal(state);
- }
- catch (InvalidDataException e) {
- LOG.error(e);
- }
+ XmlSerializer.deserializeInto(myConfiguration, state);
}
+ @NotNull
public JavadocConfiguration getConfiguration() {
return myConfiguration;
}
@@ -81,4 +66,4 @@ public final class JavadocGenerationManager implements PersistentStateComponent<
ExecutionErrorDialog.show(e, CommonBundle.getErrorTitle(), myProject);
}
}
-}
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/AbstractJavaInplaceIntroducer.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/AbstractJavaInplaceIntroducer.java
index c1a707718308..6e7cdac9a820 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/AbstractJavaInplaceIntroducer.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/AbstractJavaInplaceIntroducer.java
@@ -2,6 +2,7 @@ package com.intellij.refactoring.introduceParameter;
import com.intellij.codeInsight.intention.impl.TypeExpression;
import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
import com.intellij.codeInsight.template.Expression;
import com.intellij.codeInsight.template.ExpressionContext;
import com.intellij.codeInsight.template.Result;
@@ -200,7 +201,23 @@ public abstract class AbstractJavaInplaceIntroducer extends AbstractInplaceIntro
@Override
public LookupElement[] calculateLookupItems(ExpressionContext context) {
- return expression.calculateLookupItems(context);
+ final LookupElement[] elements = expression.calculateLookupItems(context);
+ if (elements != null) {
+ LookupElement toBeSelected = null;
+ for (LookupElement element : elements) {
+ if (element instanceof PsiTypeLookupItem && ((PsiTypeLookupItem)element).getType().getPresentableText().equals(defaultType)) {
+ toBeSelected = element;
+ break;
+ }
+ }
+ if (toBeSelected != null) {
+ final int idx = ArrayUtil.find(elements, toBeSelected);
+ if (idx > 0) {
+ return ArrayUtil.prepend(toBeSelected, ArrayUtil.remove(elements, idx));
+ }
+ }
+ }
+ return elements;
}
@Override
diff --git a/java/java-impl/src/com/intellij/refactoring/typeCook/Util.java b/java/java-impl/src/com/intellij/refactoring/typeCook/Util.java
index 54149613704b..09370d3afe5a 100644
--- a/java/java-impl/src/com/intellij/refactoring/typeCook/Util.java
+++ b/java/java-impl/src/com/intellij/refactoring/typeCook/Util.java
@@ -17,6 +17,7 @@ package com.intellij.refactoring.typeCook;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
+import com.intellij.psi.impl.PsiDiamondTypeUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.typeCook.deductive.PsiTypeVariableFactory;
@@ -405,6 +406,10 @@ public class Util {
list
.add(factory.createTypeElement(aType == null ? PsiType.getJavaLangObject(list.getManager(), list.getResolveScope()) : aType));
}
+
+ if (PsiDiamondTypeUtil.canCollapseToDiamond(newx, newx, newx.getType())) {
+ PsiDiamondTypeUtil.replaceExplicitWithDiamond(list);
+ }
}
}
else {
diff --git a/java/java-impl/src/com/intellij/refactoring/ui/TypeSelectorManagerImpl.java b/java/java-impl/src/com/intellij/refactoring/ui/TypeSelectorManagerImpl.java
index b308a4cdf929..308ee4b175fb 100644
--- a/java/java-impl/src/com/intellij/refactoring/ui/TypeSelectorManagerImpl.java
+++ b/java/java-impl/src/com/intellij/refactoring/ui/TypeSelectorManagerImpl.java
@@ -312,18 +312,25 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
private void setTypesAndPreselect(PsiType[] types) {
myTypeSelector.setTypes(types);
+ final PsiType preferredType = getPreferredType(types, getDefaultType());
+ if (preferredType != null) {
+ myTypeSelector.selectType(preferredType);
+ }
+ }
+
+ public static PsiType getPreferredType(PsiType[] types, PsiType defaultType) {
Map map = new THashMap();
for (final PsiType type : types) {
map.put(serialize(type), type);
}
- for (StatisticsInfo info : StatisticsManager.getInstance().getAllValues(getStatsKey())) {
+ for (StatisticsInfo info : StatisticsManager.getInstance().getAllValues(getStatsKey(defaultType))) {
final PsiType candidate = map.get(info.getValue());
if (candidate != null && StatisticsManager.getInstance().getUseCount(info) > 0) {
- myTypeSelector.selectType(candidate);
- return;
+ return candidate;
}
}
+ return null;
}
@Override
@@ -353,15 +360,10 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
StatisticsManager.getInstance().incUseCount(new StatisticsInfo(getStatsKey(defaultType), serialize(type)));
}
- private String getStatsKey() {
- final PsiType defaultType = getDefaultType();
+ private static String getStatsKey(final PsiType defaultType) {
if (defaultType == null) {
return "IntroduceVariable##";
}
- return getStatsKey(defaultType);
- }
-
- private static String getStatsKey(final PsiType defaultType) {
return "IntroduceVariable##" + serialize(defaultType);
}
diff --git a/java/java-indexing-api/src/com/intellij/psi/search/searches/DirectClassInheritorsSearch.java b/java/java-indexing-api/src/com/intellij/psi/search/searches/DirectClassInheritorsSearch.java
index 8db0cf827e9b..6cbf5bbe4bed 100644
--- a/java/java-indexing-api/src/com/intellij/psi/search/searches/DirectClassInheritorsSearch.java
+++ b/java/java-indexing-api/src/com/intellij/psi/search/searches/DirectClassInheritorsSearch.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,6 @@
package com.intellij.psi.search.searches;
import com.intellij.openapi.extensions.ExtensionPointName;
-import com.intellij.openapi.util.Condition;
import com.intellij.psi.PsiAnonymousClass;
import com.intellij.psi.PsiClass;
import com.intellij.psi.search.GlobalSearchScope;
@@ -25,6 +24,7 @@ import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.FilteredQuery;
import com.intellij.util.Query;
import com.intellij.util.QueryExecutor;
+import org.jetbrains.annotations.NotNull;
/**
* @author max
@@ -34,30 +34,32 @@ public class DirectClassInheritorsSearch extends ExtensibleQueryFactory raw = INSTANCE.createUniqueResultsQuery(new SearchParameters(aClass, scope, includeAnonymous, checkInheritance));
if (!includeAnonymous) {
- return new FilteredQuery(raw, new Condition() {
- @Override
- public boolean value(final PsiClass psiClass) {
- return !(psiClass instanceof PsiAnonymousClass);
- }
- });
+ return new FilteredQuery<>(raw, psiClass -> !(psiClass instanceof PsiAnonymousClass));
}
return raw;
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaDirectInheritorsSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaDirectInheritorsSearcher.java
index a0ea9b3fd68f..2c3505df7246 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaDirectInheritorsSearcher.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/JavaDirectInheritorsSearcher.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2015 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -37,6 +37,7 @@ import com.intellij.util.QueryExecutor;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
@@ -51,87 +52,46 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor consumer) {
final PsiClass aClass = p.getClassToProcess();
- final SearchScope useScope = ApplicationManager.getApplication().runReadAction(new Computable() {
- @Override
- public SearchScope compute() {
- return aClass.getUseScope();
- }
- });
+ final SearchScope useScope = ApplicationManager.getApplication().runReadAction((Computable)aClass::getUseScope);
- final String qualifiedName = ApplicationManager.getApplication().runReadAction(new Computable() {
- @Override
- public String compute() {
- return aClass.getQualifiedName();
- }
- });
+ final String qualifiedName = ApplicationManager.getApplication().runReadAction((Computable)aClass::getQualifiedName);
final Project project = PsiUtilCore.getProjectInReadAction(aClass);
if (CommonClassNames.JAVA_LANG_OBJECT.equals(qualifiedName)) {
- //[pasynkov]: WTF?
- //final SearchScope scope = useScope.intersectWith(GlobalSearchScope.notScope(GlobalSearchScope.getScopeRestrictedByFileTypes(
- // GlobalSearchScope.allScope(psiManager.getProject()), StdFileTypes.JSP, StdFileTypes.JSPX)));
-
- return AllClassesSearch.search(useScope, project).forEach(new Processor() {
- @Override
- public boolean process(final PsiClass psiClass) {
- ProgressManager.checkCanceled();
- if (psiClass.isInterface()) {
- return consumer.process(psiClass);
- }
- final PsiClass superClass = psiClass.getSuperClass();
- if (superClass != null && CommonClassNames.JAVA_LANG_OBJECT.equals(ApplicationManager.getApplication().runReadAction(new Computable() {
- public String compute() {
- return superClass.getQualifiedName();
- }
- }))) {
- return consumer.process(psiClass);
- }
- return true;
+ return AllClassesSearch.search(useScope, project).forEach(psiClass -> {
+ ProgressManager.checkCanceled();
+ if (psiClass.isInterface()) {
+ return consumer.process(psiClass);
}
+ final PsiClass superClass = psiClass.getSuperClass();
+ if (superClass != null &&
+ CommonClassNames.JAVA_LANG_OBJECT.equals(ApplicationManager.getApplication().runReadAction((Computable)superClass::getQualifiedName))) {
+ return consumer.process(psiClass);
+ }
+ return true;
});
}
final GlobalSearchScope scope = useScope instanceof GlobalSearchScope ? (GlobalSearchScope)useScope : new EverythingGlobalScope(project);
- final String searchKey = ApplicationManager.getApplication().runReadAction(new Computable() {
- @Override
- public String compute() {
- return aClass.getName();
- }
- });
+ final String searchKey = ApplicationManager.getApplication().runReadAction((Computable)aClass::getName);
if (StringUtil.isEmpty(searchKey)) {
return true;
}
- Collection candidates = MethodUsagesSearcher.resolveInReadAction(project,
- new Computable>() {
- @Override
- public Collection compute() {
- return JavaSuperClassNameOccurenceIndex
- .getInstance().get(searchKey, project, scope);
- }
- });
+ Collection candidates =
+ MethodUsagesSearcher.resolveInReadAction(project, () -> JavaSuperClassNameOccurenceIndex.getInstance().get(searchKey, project, scope));
- Map> classes = new HashMap>();
+ Map> classes = new HashMap<>();
for (final PsiReferenceList referenceList : candidates) {
ProgressManager.checkCanceled();
- final PsiClass candidate = (PsiClass)ApplicationManager.getApplication().runReadAction(new Computable() {
- @Override
- public PsiElement compute() {
- return referenceList.getParent();
- }
- });
+ final PsiClass candidate = (PsiClass)ApplicationManager.getApplication().runReadAction((Computable)referenceList::getParent);
if (!checkInheritance(p, aClass, candidate, project)) continue;
- String fqn = ApplicationManager.getApplication().runReadAction(new Computable() {
- @Override
- public String compute() {
- return candidate.getQualifiedName();
- }
- });
+ String fqn = ApplicationManager.getApplication().runReadAction((Computable)candidate::getQualifiedName);
List list = classes.get(fqn);
if (list == null) {
- list = new ArrayList();
+ list = new ArrayList<>();
classes.put(fqn, list);
}
list.add(candidate);
@@ -141,20 +101,13 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor sameNamedClasses : classes.values()) {
ProgressManager.checkCanceled();
- if (!processSameNamedClasses(consumer, sameNamedClasses, jarFile)) return false;
+ if (!processSameNamedClasses(sameNamedClasses, jarFile, consumer)) return false;
}
}
if (p.includeAnonymous()) {
- Collection anonymousCandidates = MethodUsagesSearcher.resolveInReadAction(project,
- new Computable>() {
- @Override
- public Collection compute() {
- return JavaAnonymousClassBaseRefOccurenceIndex
- .getInstance()
- .get(searchKey, project, scope);
- }
- });
+ Collection anonymousCandidates =
+ MethodUsagesSearcher.resolveInReadAction(project, () -> JavaAnonymousClassBaseRefOccurenceIndex.getInstance().get(searchKey, project, scope));
for (PsiAnonymousClass candidate : anonymousCandidates) {
ProgressManager.checkCanceled();
@@ -163,30 +116,15 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor() {
- @Override
- public Boolean compute() {
- return aClass.isEnum();
- }
- });
+ boolean isEnum = ApplicationManager.getApplication().runReadAction((Computable)aClass::isEnum);
if (isEnum) {
// abstract enum can be subclassed in the body
- PsiField[] fields = ApplicationManager.getApplication().runReadAction(new Computable() {
- @Override
- public PsiField[] compute() {
- return aClass.getFields();
- }
- });
+ PsiField[] fields = ApplicationManager.getApplication().runReadAction((Computable)aClass::getFields);
for (final PsiField field : fields) {
ProgressManager.checkCanceled();
if (field instanceof PsiEnumConstant) {
PsiEnumConstantInitializer initializingClass =
- ApplicationManager.getApplication().runReadAction(new Computable() {
- @Override
- public PsiEnumConstantInitializer compute() {
- return ((PsiEnumConstant)field).getInitializingClass();
- }
- });
+ ApplicationManager.getApplication().runReadAction((Computable)((PsiEnumConstant)field)::getInitializingClass);
if (initializingClass != null) {
if (!consumer.process(initializingClass)) return false;
}
@@ -198,16 +136,16 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor() {
- @Override
- public Boolean compute() {
- return !p.isCheckInheritance() || candidate.isInheritor(aClass, false);
- }
- });
+ private static boolean checkInheritance(@NotNull DirectClassInheritorsSearch.SearchParameters p,
+ @NotNull PsiClass aClass,
+ @NotNull PsiClass candidate,
+ @NotNull Project project) {
+ return MethodUsagesSearcher.resolveInReadAction(project, () -> !p.isCheckInheritance() || candidate.isInheritor(aClass, false));
}
- private static boolean processSameNamedClasses(Processor consumer, List sameNamedClasses, final VirtualFile jarFile) {
+ private static boolean processSameNamedClasses(@NotNull List sameNamedClasses,
+ @Nullable VirtualFile jarFile,
+ @NotNull Processor consumer) {
// if there is a class from the same jar, prefer it
boolean sameJarClassFound = false;
@@ -225,12 +163,7 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor() {
- @Override
- public VirtualFile compute() {
- return PsiUtil.getJarFile(aClass);
- }
- });
+ private static VirtualFile getJarFile(@NotNull PsiClass aClass) {
+ return ApplicationManager.getApplication().runReadAction((Computable)() -> PsiUtil.getJarFile(aClass));
}
}
diff --git a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java
index 4dad59cfb946..f63fcb976dd2 100644
--- a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java
+++ b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2015 JetBrains s.r.o.
+ * Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +16,6 @@
package com.intellij.codeInsight;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
@@ -87,9 +86,9 @@ public class AnnotationUtil {
}
@Nullable
- public static PsiAnnotation findAnnotation(@Nullable PsiModifierListOwner listOwner, final boolean skipExternal, @NotNull String... annotationNames) {
+ public static PsiAnnotation findAnnotation(@Nullable PsiModifierListOwner listOwner, boolean skipExternal, @NotNull String... annotationNames) {
if (annotationNames.length == 0) return null;
- Set set = annotationNames.length == 1 ? Collections.singleton(annotationNames[0]) : new HashSet(Arrays.asList(annotationNames));
+ Set set = annotationNames.length == 1 ? Collections.singleton(annotationNames[0]) : ContainerUtil.newHashSet(annotationNames);
return findAnnotation(listOwner, set, skipExternal);
}
@@ -104,8 +103,7 @@ public class AnnotationUtil {
}
@Nullable
- public static PsiAnnotation findAnnotation(@Nullable PsiModifierListOwner listOwner, @NotNull Collection annotationNames,
- final boolean skipExternal) {
+ public static PsiAnnotation findAnnotation(@Nullable PsiModifierListOwner listOwner, @NotNull Collection annotationNames, boolean skipExternal) {
if (listOwner == null) return null;
PsiAnnotation annotation = findOwnAnnotation(listOwner, annotationNames);
diff --git a/java/java-psi-api/src/com/intellij/psi/javadoc/JavadocTagInfo.java b/java/java-psi-api/src/com/intellij/psi/javadoc/JavadocTagInfo.java
index d79132857438..fdbee5a2d5c4 100644
--- a/java/java-psi-api/src/com/intellij/psi/javadoc/JavadocTagInfo.java
+++ b/java/java-psi-api/src/com/intellij/psi/javadoc/JavadocTagInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -18,7 +18,6 @@ package com.intellij.psi.javadoc;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
/**
@@ -27,13 +26,12 @@ import org.jetbrains.annotations.Nullable;
public interface JavadocTagInfo {
ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.javadocTagInfo");
- @NonNls String getName();
+ String getName();
+
boolean isInline();
boolean isValidInContext(PsiElement element);
- Object[] getPossibleValues(PsiElement context, PsiElement place, String prefix);
-
/**
* Checks the tag value for correctness.
*
@@ -45,4 +43,4 @@ public interface JavadocTagInfo {
@Nullable
PsiReference getReference(PsiDocTagValue value);
-}
+}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ExceptionTagInfo.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ExceptionTagInfo.java
index 06e68c41dabe..8901416ebf1f 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ExceptionTagInfo.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ExceptionTagInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -20,7 +20,6 @@ import com.intellij.psi.*;
import com.intellij.psi.javadoc.JavadocTagInfo;
import com.intellij.psi.javadoc.PsiDocTagValue;
import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NonNls;
/**
@@ -33,6 +32,22 @@ class ExceptionTagInfo implements JavadocTagInfo {
myName = name;
}
+ @Override
+ public String getName() {
+ return myName;
+ }
+
+ @Override
+ public boolean isInline() {
+ return false;
+ }
+
+ @Override
+ public boolean isValidInContext(PsiElement element) {
+ if (!(element instanceof PsiMethod)) return false;
+ return true;
+ }
+
@Override
public String checkTagValue(PsiDocTagValue value) {
if (value == null) return JavaErrorMessages.message("javadoc.exception.tag.exception.class.expected");
@@ -89,29 +104,8 @@ class ExceptionTagInfo implements JavadocTagInfo {
return JavaErrorMessages.message("javadoc.exception.tag.exception.is.not.thrown", exceptionClass.getName(), method.getName());
}
- @Override
- public String getName() {
- return myName;
- }
-
- @Override
- public Object[] getPossibleValues(PsiElement context, PsiElement place, String prefix) {
- return ArrayUtil.EMPTY_OBJECT_ARRAY;
- }
-
@Override
public PsiReference getReference(PsiDocTagValue value) {
return null;
}
-
- @Override
- public boolean isValidInContext(PsiElement element) {
- if (!(element instanceof PsiMethod)) return false;
- return true;
- }
-
- @Override
- public boolean isInline() {
- return false;
- }
-}
+}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/JavadocManagerImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/JavadocManagerImpl.java
index 1fd12fd8d55a..ea0d03a9b4e6 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/JavadocManagerImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/JavadocManagerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -68,16 +68,12 @@ public class JavadocManagerImpl implements JavadocManager {
myInfos.add(new ValueDocTagInfo());
Collections.addAll(myInfos, Extensions.getExtensions(JavadocTagInfo.EP_NAME, project));
+
for (CustomJavadocTagProvider extension : Extensions.getExtensions(CustomJavadocTagProvider.EP_NAME)) {
myInfos.addAll(extension.getSupportedTags());
}
}
- @Deprecated
- public void registerTagInfo(@NotNull JavadocTagInfo info) {
- myInfos.add(info);
- }
-
@Override
@NotNull
public JavadocTagInfo[] getTagInfos(PsiElement context) {
@@ -96,9 +92,11 @@ public class JavadocManagerImpl implements JavadocManager {
@Nullable
public JavadocTagInfo getTagInfo(String name) {
for (JavadocTagInfo info : myInfos) {
- if (info.getName().equals(name)) return info;
+ if (info.getName().equals(name)) {
+ return info;
+ }
}
return null;
}
-}
+}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ParamDocTagInfo.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ParamDocTagInfo.java
index ca4d827653bc..af91d31fb6f3 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ParamDocTagInfo.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ParamDocTagInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -21,12 +21,6 @@ import com.intellij.psi.*;
import com.intellij.psi.javadoc.JavadocTagInfo;
import com.intellij.psi.javadoc.PsiDocTagValue;
import com.intellij.psi.util.PsiUtil;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.containers.ContainerUtil;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
/**
* @author mike
@@ -38,25 +32,14 @@ class ParamDocTagInfo implements JavadocTagInfo {
}
@Override
- public boolean isValidInContext(PsiElement element) {
- return element instanceof PsiMethod ||
- (element instanceof PsiClass && PsiUtil.isLanguageLevel5OrHigher(element));
+ public boolean isInline() {
+ return false;
}
@Override
- public Object[] getPossibleValues(PsiElement context, PsiElement place, String prefix) {
- if (context instanceof PsiTypeParameterListOwner) {
- List result = new ArrayList(Arrays.asList(((PsiTypeParameterListOwner)context).getTypeParameters()));
-
- if (context instanceof PsiMethod) {
- PsiMethod method = (PsiMethod)context;
- ContainerUtil.addAll(result, method.getParameterList().getParameters());
- }
-
- return result.toArray(new PsiNamedElement[result.size()]);
- }
-
- return ArrayUtil.EMPTY_OBJECT_ARRAY;
+ public boolean isValidInContext(PsiElement element) {
+ return element instanceof PsiMethod ||
+ (element instanceof PsiClass && PsiUtil.isLanguageLevel5OrHigher(element));
}
@Override
@@ -81,10 +64,4 @@ class ParamDocTagInfo implements JavadocTagInfo {
if (value instanceof PsiDocParamRef) return value.getReference();
return null;
}
-
-
- @Override
- public boolean isInline() {
- return false;
- }
-}
+}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ReturnDocTagInfo.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ReturnDocTagInfo.java
index 6e9de7361c5c..7680cc2dad7c 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ReturnDocTagInfo.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ReturnDocTagInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -21,30 +21,19 @@ import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiType;
import com.intellij.psi.javadoc.JavadocTagInfo;
import com.intellij.psi.javadoc.PsiDocTagValue;
-import com.intellij.util.ArrayUtil;
/**
* @author mike
*/
class ReturnDocTagInfo implements JavadocTagInfo {
- @Override
- public String checkTagValue(PsiDocTagValue value) {
- return null;
- }
-
@Override
public String getName() {
return "return";
}
@Override
- public Object[] getPossibleValues(PsiElement context, PsiElement place, String prefix) {
- return ArrayUtil.EMPTY_OBJECT_ARRAY;
- }
-
- @Override
- public PsiReference getReference(PsiDocTagValue value) {
- return null;
+ public boolean isInline() {
+ return false;
}
@Override
@@ -57,7 +46,12 @@ class ReturnDocTagInfo implements JavadocTagInfo {
}
@Override
- public boolean isInline() {
- return false;
+ public String checkTagValue(PsiDocTagValue value) {
+ return null;
}
-}
+
+ @Override
+ public PsiReference getReference(PsiDocTagValue value) {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/SeeDocTagInfo.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/SeeDocTagInfo.java
index 5356938959e1..83bc31dc1959 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/SeeDocTagInfo.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/SeeDocTagInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,123 +16,53 @@
package com.intellij.psi.impl.source.javadoc;
import com.intellij.pom.java.LanguageLevel;
-import com.intellij.psi.*;
-import com.intellij.psi.impl.source.tree.JavaElementType;
-import com.intellij.psi.util.PsiUtil;
-import com.intellij.psi.impl.source.SourceTreeToPsiMap;
-import com.intellij.psi.impl.source.tree.ElementType;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiReference;
import com.intellij.psi.javadoc.JavadocTagInfo;
import com.intellij.psi.javadoc.PsiDocTagValue;
-import com.intellij.psi.javadoc.PsiDocToken;
-import com.intellij.psi.tree.IElementType;
-import com.intellij.util.ArrayUtil;
-import org.jetbrains.annotations.NonNls;
-
-import java.util.ArrayList;
-import java.util.List;
+import com.intellij.psi.util.PsiUtil;
/**
* @author mike
*/
class SeeDocTagInfo implements JavadocTagInfo {
+ private static final String LINKPLAIN_TAG = "linkplain";
+
private final String myName;
private final boolean myInline;
- @NonNls private static final String LINKPLAIN_TAG = "linkplain";
- public SeeDocTagInfo(@NonNls String name, boolean isInline) {
+ public SeeDocTagInfo(String name, boolean isInline) {
myName = name;
myInline = isInline;
}
- @Override
- public String checkTagValue(PsiDocTagValue value) {
- return null;
- }
-
@Override
public String getName() {
return myName;
}
@Override
- public Object[] getPossibleValues(PsiElement context, PsiElement place, String prefix) {
- if (place instanceof PsiDocToken) {
- PsiDocToken token = (PsiDocToken) place;
- if (token.getTokenType() == JavaDocTokenType.DOC_TAG_VALUE_SHARP_TOKEN) {
- return getPossibleMethodsAndFields(context, place, prefix);
- } else if (token.getTokenType() == JavaDocTokenType.DOC_TAG_VALUE_LPAREN) {
- if (token.getPrevSibling() == null) return ArrayUtil.EMPTY_OBJECT_ARRAY;
- final String methodName = token.getPrevSibling().getText();
-
- PsiElement targetContext = getTargetContext(context, place);
-
- List result = new ArrayList();
- final PsiMethod[] methods = PsiDocMethodOrFieldRef.getAllMethods(targetContext, place);
- for (final PsiMethod method : methods) {
- if (method.getName().equals(methodName)) {
- result.add(method);
- }
- }
- return ArrayUtil.toObjectArray(result);
- } else if (token.getTokenType() == JavaDocTokenType.DOC_TAG_VALUE_TOKEN && place.getParent() instanceof PsiDocMethodOrFieldRef) {
- return getPossibleMethodsAndFields(context, place, prefix);
- }
- }
-
- return ArrayUtil.EMPTY_OBJECT_ARRAY;
+ public boolean isInline() {
+ return myInline;
}
- private Object[] getPossibleMethodsAndFields(PsiElement context, PsiElement place, String prefix) {
- List result = new ArrayList();
-
- PsiElement targetContext = getTargetContext(context, place);
-
- final PsiMethod[] methods = PsiDocMethodOrFieldRef.getAllMethods(targetContext, place);
- for (PsiMethod method : methods) {
- result.add(method);
- }
-
- final PsiVariable[] variables = PsiDocMethodOrFieldRef.getAllVariables(targetContext, place);
- for (PsiVariable variable : variables) {
- result.add(variable);
- }
-
- return ArrayUtil.toObjectArray(result);
- }
-
- private PsiElement getTargetContext(PsiElement context, PsiElement place) {
- PsiElement targetContext = context;
-
- if (place.getParent() instanceof PsiDocMethodOrFieldRef) {
- PsiDocMethodOrFieldRef methodRef = (PsiDocMethodOrFieldRef) place.getParent();
-
- final IElementType firstChildType = methodRef.getFirstChildNode().getElementType();
- if (firstChildType == JavaElementType.JAVA_CODE_REFERENCE || firstChildType == JavaElementType.REFERENCE_EXPRESSION) {
- PsiJavaCodeReferenceElement referenceElement = (PsiJavaCodeReferenceElement) SourceTreeToPsiMap.treeElementToPsi(methodRef.getFirstChildNode());
- final PsiElement element = referenceElement.resolve();
- if (element instanceof PsiClass) {
- targetContext = element.getFirstChild();
- }
- }
- }
- return targetContext;
- }
@Override
public boolean isValidInContext(PsiElement element) {
- if (myInline && myName.equals(LINKPLAIN_TAG) && element != null)
+ if (myInline && myName.equals(LINKPLAIN_TAG) && element != null) {
return PsiUtil.getLanguageLevel(element).compareTo(LanguageLevel.JDK_1_4) >= 0;
+ }
return true;
}
+ @Override
+ public String checkTagValue(PsiDocTagValue value) {
+ return null;
+ }
+
@Override
public PsiReference getReference(PsiDocTagValue value) {
return null;
}
-
- @Override
- public boolean isInline() {
- return myInline;
- }
-}
+}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/SerialDocTagInfo.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/SerialDocTagInfo.java
index 7f5a68f0e8c8..5eb7838ec28c 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/SerialDocTagInfo.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/SerialDocTagInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -21,7 +21,6 @@ import com.intellij.psi.PsiField;
import com.intellij.psi.PsiReference;
import com.intellij.psi.javadoc.JavadocTagInfo;
import com.intellij.psi.javadoc.PsiDocTagValue;
-import com.intellij.util.ArrayUtil;
public class SerialDocTagInfo implements JavadocTagInfo {
@Override
@@ -39,11 +38,6 @@ public class SerialDocTagInfo implements JavadocTagInfo {
return element instanceof PsiClass || element instanceof PsiField;
}
- @Override
- public Object[] getPossibleValues(PsiElement context, PsiElement place, String prefix) {
- return ArrayUtil.EMPTY_OBJECT_ARRAY;
- }
-
@Override
public String checkTagValue(PsiDocTagValue value) {
return null;
@@ -53,4 +47,4 @@ public class SerialDocTagInfo implements JavadocTagInfo {
public PsiReference getReference(PsiDocTagValue value) {
return null;
}
-}
+}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/SimpleDocTagInfo.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/SimpleDocTagInfo.java
index ddb6187a6420..78eb239b42c8 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/SimpleDocTagInfo.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/SimpleDocTagInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -18,10 +18,9 @@ package com.intellij.psi.impl.source.javadoc;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
-import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.javadoc.JavadocTagInfo;
import com.intellij.psi.javadoc.PsiDocTagValue;
-import com.intellij.util.ArrayUtil;
+import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NonNls;
/**
@@ -55,6 +54,11 @@ class SimpleDocTagInfo implements JavadocTagInfo {
return myName;
}
+ @Override
+ public boolean isInline() {
+ return myInline;
+ }
+
@Override
public boolean isValidInContext(PsiElement element) {
if (element != null && PsiUtil.getLanguageLevel(element).compareTo(myLanguageLevel) < 0) {
@@ -64,11 +68,6 @@ class SimpleDocTagInfo implements JavadocTagInfo {
return myContext.isInstance(element) || (myAdditionalContext != null && myAdditionalContext.isInstance(element));
}
- @Override
- public Object[] getPossibleValues(PsiElement context, PsiElement place, String prefix) {
- return ArrayUtil.EMPTY_OBJECT_ARRAY;
- }
-
@Override
public String checkTagValue(PsiDocTagValue value) {
return null;
@@ -78,9 +77,4 @@ class SimpleDocTagInfo implements JavadocTagInfo {
public PsiReference getReference(PsiDocTagValue value) {
return null;
}
-
- @Override
- public boolean isInline() {
- return myInline;
- }
-}
+}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ValueDocTagInfo.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ValueDocTagInfo.java
index 81838d615fa5..dcfca2b52970 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ValueDocTagInfo.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/ValueDocTagInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -44,11 +44,6 @@ public class ValueDocTagInfo implements JavadocTagInfo {
return true;
}
- @Override
- public Object[] getPossibleValues(PsiElement context, PsiElement place, String prefix) {
- return null;
- }
-
@Override
public String checkTagValue(PsiDocTagValue value) {
boolean hasReference = (value != null && value.getFirstChild() != null);
@@ -85,4 +80,4 @@ public class ValueDocTagInfo implements JavadocTagInfo {
public PsiReference getReference(PsiDocTagValue value) {
return null;
}
-}
+}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
index cae20db0f0c5..555ebb946ef1 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java
@@ -41,8 +41,11 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
@Override
public boolean reduce(InferenceSession session, List constraints) {
if (!PsiPolyExpressionUtil.isPolyExpression(myExpression)) {
+
+ PsiType exprType = myExpression.getType();
+
if (session.isProperType(myT)) {
- final boolean assignmentCompatible = TypeConversionUtil.areTypesAssignmentCompatible(myT, myExpression);
+ final boolean assignmentCompatible = exprType == null || TypeConversionUtil.isAssignable(myT, exprType);
if (!assignmentCompatible) {
final PsiType type = myExpression.getType();
session.registerIncompatibleErrorMessage((type != null ? type.getPresentableText() : myExpression.getText()) + " is not compatible with " + session.getPresentableText(myT));
@@ -50,8 +53,6 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
return assignmentCompatible;
}
- PsiType exprType = myExpression.getType();
-
if (exprType instanceof PsiLambdaParameterType) {
return false;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java
index 125b06a7d076..adecfa3687e4 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java
@@ -214,7 +214,7 @@ public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements Psi
PsiParameter parameter = lambdaParameters[lambdaParamIdx];
final PsiTypeElement typeElement = parameter.getTypeElement();
if (typeElement != null) {
- final PsiType lambdaFormalType = toArray(typeElement.getType());
+ final PsiType lambdaFormalType = toArray(parameter.getType());
final PsiType methodParameterType = toArray(parameterTypes[lambdaParamIdx]);
if (!lambdaFormalType.equals(methodParameterType)) {
return false;
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/LooseInvocationContextForProperPrimitiveTypes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/LooseInvocationContextForProperPrimitiveTypes.java
new file mode 100644
index 000000000000..5c9d04006208
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/LooseInvocationContextForProperPrimitiveTypes.java
@@ -0,0 +1,8 @@
+class Test {
+
+ {
+ pair(2);
+ }
+
+ static void pair( byte b) {}
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/LinkToItself.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/LinkToItself.java
new file mode 100644
index 000000000000..29c7e846dd3d
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/LinkToItself.java
@@ -0,0 +1,6 @@
+class Foo {
+ /**
+ * {@link #foo()}
+ */
+ void foo(){}
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/See2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/See2.java
index 7b842427978c..8531d3734c1b 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/See2.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/See2.java
@@ -1,6 +1,6 @@
class Test {
/**
- * @see A#
+ * @see A#
*/
public void i() {}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/See6.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/See6.java
deleted file mode 100644
index 91b8c48404ab..000000000000
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/See6.java
+++ /dev/null
@@ -1,6 +0,0 @@
-class Foo {
- /**
- * {@link #foo()}
- */
- void foo(){}
-}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/SeeNonRefs.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/SeeNonRefs.java
new file mode 100644
index 000000000000..2a128c97508d
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/javaDoc/SeeNonRefs.java
@@ -0,0 +1,10 @@
+/**
+ * @see
+ * @see {@link C} clarification
+ *
+ * @see C a correct one
+ * @see C#f
+ */
+class C {
+ int f;
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/CLikeArrayDeclarationInLambdaWithExplicitTypes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/CLikeArrayDeclarationInLambdaWithExplicitTypes.java
new file mode 100644
index 000000000000..cfdefea43c04
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/CLikeArrayDeclarationInLambdaWithExplicitTypes.java
@@ -0,0 +1,10 @@
+
+interface X {
+ void foo(int[] x);
+}
+
+class C {
+ static void main(String[] args){
+ X a = (int x[]) -> { };
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA152659.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA152659.java
new file mode 100644
index 000000000000..757d8dfec160
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA152659.java
@@ -0,0 +1,28 @@
+import java.util.*;
+
+class X, B extends Comparable> {
+
+ class Pair implements Comparable {
+ A a;
+ B b;
+
+
+ public A getA() {
+ return a;
+ }
+
+
+ public B getB() {
+ return b;
+ }
+
+
+ @Override
+ public int compareTo(Pair other) {
+ Comparator comparator = Comparator.comparing(Pair::getA).thenComparing(Pair::getB);
+
+ return comparator.compare(this, other);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/generifyFile/before2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/generifyFile/before2.java
new file mode 100644
index 000000000000..e821781e448e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/generifyFile/before2.java
@@ -0,0 +1,7 @@
+// "Try to generify 'before2.java'" "true"
+import java.util.ArrayList;
+class Use {
+ void f() {
+ ArrayList s = new ArrayList();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/typeCook/convertToDiamond/after/Test.1.items b/java/java-tests/testData/refactoring/typeCook/convertToDiamond/after/Test.1.items
new file mode 100644
index 000000000000..3b9e27f05d2c
--- /dev/null
+++ b/java/java-tests/testData/refactoring/typeCook/convertToDiamond/after/Test.1.items
@@ -0,0 +1 @@
+java.util.ArrayList\nnew
diff --git a/java/java-tests/testData/refactoring/typeCook/convertToDiamond/after/Test.items b/java/java-tests/testData/refactoring/typeCook/convertToDiamond/after/Test.items
new file mode 100644
index 000000000000..f994691fb0c5
--- /dev/null
+++ b/java/java-tests/testData/refactoring/typeCook/convertToDiamond/after/Test.items
@@ -0,0 +1 @@
+java.util.ArrayList\nnew
diff --git a/java/java-tests/testData/refactoring/typeCook/convertToDiamond/after/test.java b/java/java-tests/testData/refactoring/typeCook/convertToDiamond/after/test.java
new file mode 100644
index 000000000000..e61c977ebe95
--- /dev/null
+++ b/java/java-tests/testData/refactoring/typeCook/convertToDiamond/after/test.java
@@ -0,0 +1,6 @@
+import java.util.ArrayList;
+
+class Test
+{
+ ArrayList l = new ArrayList();
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/typeCook/convertToDiamond/before/test.java b/java/java-tests/testData/refactoring/typeCook/convertToDiamond/before/test.java
new file mode 100644
index 000000000000..e61c977ebe95
--- /dev/null
+++ b/java/java-tests/testData/refactoring/typeCook/convertToDiamond/before/test.java
@@ -0,0 +1,6 @@
+import java.util.ArrayList;
+
+class Test
+{
+ ArrayList l = new ArrayList();
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java
index 83b328b41e92..b9790fc35c6e 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/JavadocHighlightingTest.java
@@ -65,8 +65,9 @@ public class JavadocHighlightingTest extends LightDaemonAnalyzerTestCase {
public void testSee3() { doTest(); }
public void testSee4() { doTest(); }
public void testSee5() { doTest(); }
- public void testSee6() { doTest(); }
+ public void testLinkToItself() { doTest(); }
public void testSeeConstants() { doTest(); }
+ public void testSeeNonRefs() { doTest(); }
public void testReturn0() { doTest(); }
public void testException0() { doTest(); }
public void testException1() { doTest(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java
index 40904c0b5c97..504f48ee0470 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java
@@ -978,4 +978,8 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
public void testIDEA152179() throws Exception {
doTest();
}
+
+ public void testLooseInvocationContextForProperPrimitiveTypes() throws Exception {
+ doTest();
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java
index 7e3595fdbd83..dff25973cdc5 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewLambdaHighlightingTest.java
@@ -276,6 +276,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
+ public void testCLikeArrayDeclarationInLambdaWithExplicitTypes() throws Exception {
+ doTest();
+ }
+
private void doTest() {
doTest(false);
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java
index 91d9cf2104ea..2451d8280718 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java
@@ -498,6 +498,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
+ public void testIDEA152659() throws Exception {
+ doTest();
+ }
+
private void doTest() {
doTest(false);
}
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/TypeCookTest.java b/java/java-tests/testSrc/com/intellij/refactoring/TypeCookTest.java
index 861c5ef62b1d..78ac7052b2a4 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/TypeCookTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/TypeCookTest.java
@@ -17,9 +17,11 @@ package com.intellij.refactoring;
import com.intellij.JavaTestUtil;
import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiClass;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.refactoring.typeCook.Settings;
@@ -667,6 +669,18 @@ public class TypeCookTest extends MultiFileTestCase {
start();
}
+ public void testConvertToDiamond() throws Exception {
+ final LanguageLevelProjectExtension levelProjectExtension = LanguageLevelProjectExtension.getInstance(getProject());
+ final LanguageLevel oldLevel = levelProjectExtension.getLanguageLevel();
+ try {
+ levelProjectExtension.setLanguageLevel(LanguageLevel.JDK_1_8);
+ start();
+ }
+ finally {
+ levelProjectExtension.setLanguageLevel(oldLevel);
+ }
+ }
+
public void start() throws Exception {
start(false);
}
diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/intentions/ConvertAtomicToLongAdderIntention.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/intentions/ConvertAtomicToLongAdderIntention.java
index 5b30001450ad..c51e0be4c483 100644
--- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/intentions/ConvertAtomicToLongAdderIntention.java
+++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/intentions/ConvertAtomicToLongAdderIntention.java
@@ -77,7 +77,7 @@ public class ConvertAtomicToLongAdderIntention extends PsiElementBaseIntentionAc
@Override
public boolean startInWriteAction() {
- return true;
+ return false;
}
@NotNull
diff --git a/platform/analysis-api/src/com/intellij/codeInsight/intention/IntentionAction.java b/platform/analysis-api/src/com/intellij/codeInsight/intention/IntentionAction.java
index 8c2a8c5c51e2..ba47b7f5e045 100644
--- a/platform/analysis-api/src/com/intellij/codeInsight/intention/IntentionAction.java
+++ b/platform/analysis-api/src/com/intellij/codeInsight/intention/IntentionAction.java
@@ -16,6 +16,7 @@
package com.intellij.codeInsight.intention;
import com.intellij.openapi.application.Application;
+import com.intellij.openapi.application.WriteActionAware;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Iconable;
@@ -39,7 +40,7 @@ import org.jetbrains.annotations.NotNull;
*
* @see IntentionManager#registerIntentionAndMetaData(IntentionAction, String...)
*/
-public interface IntentionAction {
+public interface IntentionAction extends WriteActionAware {
IntentionAction[] EMPTY_ARRAY = new IntentionAction[0];
/**
* Returns text to be shown in the list of available actions, if this action
diff --git a/platform/analysis-api/src/com/intellij/codeInspection/QuickFix.java b/platform/analysis-api/src/com/intellij/codeInspection/QuickFix.java
index ae6b97a0421e..e585d3bc49b1 100644
--- a/platform/analysis-api/src/com/intellij/codeInspection/QuickFix.java
+++ b/platform/analysis-api/src/com/intellij/codeInspection/QuickFix.java
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInspection;
+import com.intellij.openapi.application.WriteActionAware;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -26,7 +27,7 @@ import org.jetbrains.annotations.NotNull;
* @since 6.0
* @see CommonProblemDescriptor#getFixes()
*/
-public interface QuickFix {
+public interface QuickFix extends WriteActionAware {
QuickFix[] EMPTY_ARRAY = new QuickFix[0];
/**
diff --git a/platform/analysis-api/src/com/intellij/openapi/application/WriteActionAware.java b/platform/analysis-api/src/com/intellij/openapi/application/WriteActionAware.java
new file mode 100644
index 000000000000..ed7cb85d8533
--- /dev/null
+++ b/platform/analysis-api/src/com/intellij/openapi/application/WriteActionAware.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.application;
+
+public interface WriteActionAware {
+ /**
+ * Indicate whether this action should be invoked inside write action.
+ * Should return false if e.g. modal dialog is shown inside the action.
+ * If false is returned the action itself is responsible for starting write action
+ * when needed, by calling {@link Application#runWriteAction(Runnable)}.
+ *
+ * @return true if the action requires a write action, false otherwise.
+ */
+ default boolean startInWriteAction() {
+ return true;
+ }
+}
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/QuickFixWrapper.java b/platform/analysis-impl/src/com/intellij/codeInspection/ex/QuickFixWrapper.java
index 251226105993..774ee7101b93 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/QuickFixWrapper.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/QuickFixWrapper.java
@@ -92,8 +92,7 @@ public class QuickFixWrapper implements IntentionAction {
@Override
public boolean startInWriteAction() {
- final LocalQuickFix fix = getFix();
- return !(fix instanceof IntentionAction) || ((IntentionAction)fix).startInWriteAction();
+ return getFix().startInWriteAction();
}
public LocalQuickFix getFix() {
diff --git a/platform/boot/boot.iml b/platform/boot/boot.iml
index b96e3da1edc5..9a0e7ff45829 100644
--- a/platform/boot/boot.iml
+++ b/platform/boot/boot.iml
@@ -1,12 +1,12 @@
-
+
-
+
diff --git a/platform/boot/src/com/intellij/concurrency/IdeaForkJoinWorkerThreadFactory.java b/platform/boot/src/com/intellij/concurrency/IdeaForkJoinWorkerThreadFactory.java
new file mode 100644
index 000000000000..1d741f87abe1
--- /dev/null
+++ b/platform/boot/src/com/intellij/concurrency/IdeaForkJoinWorkerThreadFactory.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.concurrency;
+
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.ForkJoinWorkerThread;
+import java.util.concurrent.atomic.AtomicLong;
+
+// must be accessible via "ClassLoader.getSystemClassLoader().loadClass(fp).newInstance()" from java.util.concurrent.ForkJoinPool.makeCommonPool()
+public class IdeaForkJoinWorkerThreadFactory implements ForkJoinPool.ForkJoinWorkerThreadFactory {
+ private static final int PARALLELISM = Runtime.getRuntime().availableProcessors();
+
+ // must be called in the earliest possible moment on startup
+ public static void setupForkJoinCommonPool() {
+ System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", String.valueOf(PARALLELISM));
+ System.setProperty("java.util.concurrent.ForkJoinPool.common.threadFactory", IdeaForkJoinWorkerThreadFactory.class.getName());
+
+ if (!ForkJoinPool.commonPool().getFactory().getClass().getName().equals(IdeaForkJoinWorkerThreadFactory.class.getName())) {
+ throw new IllegalStateException("Could not set ForkJoinPool thread factory: got "+ForkJoinPool.commonPool().getFactory());
+ }
+ }
+
+ private static final AtomicLong bits = new AtomicLong();
+ @Override
+ public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
+ final int n = setNextBit();
+ ForkJoinWorkerThread thread = new ForkJoinWorkerThread(pool) {
+ @Override
+ protected void onTermination(Throwable exception) {
+ clearBit(n);
+ super.onTermination(exception);
+ }
+ };
+ thread.setName("JobScheduler FJ pool " + n + "/" + PARALLELISM);
+ return thread;
+ }
+
+ private static int setNextBit() {
+ long oldValue = bits.getAndUpdate(value -> value + 1 | value);
+ return Long.numberOfTrailingZeros(oldValue + 1);
+ }
+
+ private static void clearBit(int n) {
+ bits.updateAndGet(value -> value & ~(1L << n));
+ }
+}
diff --git a/platform/core-api/src/com/intellij/lexer/StringLiteralLexer.java b/platform/core-api/src/com/intellij/lexer/StringLiteralLexer.java
index 3b943b9e6018..3703409fcf23 100644
--- a/platform/core-api/src/com/intellij/lexer/StringLiteralLexer.java
+++ b/platform/core-api/src/com/intellij/lexer/StringLiteralLexer.java
@@ -32,13 +32,13 @@ public class StringLiteralLexer extends LexerBase {
public static final char NO_QUOTE_CHAR = (char)-1;
- private CharSequence myBuffer;
- private int myStart;
- private int myEnd;
+ protected CharSequence myBuffer;
+ protected int myStart;
+ protected int myEnd;
private int myState;
private int myLastState;
- private int myBufferEnd;
- private final char myQuoteChar;
+ protected int myBufferEnd;
+ protected final char myQuoteChar;
private final IElementType myOriginalLiteralToken;
private final boolean myCanEscapeEolOrFramingSpaces;
private final String myAdditionalValidEscapes;
@@ -114,10 +114,7 @@ public class StringLiteralLexer extends LexerBase {
return StringEscapesTokenTypes.VALID_STRING_ESCAPE_TOKEN;
}
if (nextChar == 'u') {
- for(int i = myStart + 2; i < myStart + 6; i++) {
- if (i >= myEnd || !StringUtil.isHexDigit(myBuffer.charAt(i))) return StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN;
- }
- return StringEscapesTokenTypes.VALID_STRING_ESCAPE_TOKEN;
+ return getUnicodeEscapeSequenceType();
}
if (nextChar == 'x' && myAllowHex) {
@@ -155,6 +152,14 @@ public class StringLiteralLexer extends LexerBase {
return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN;
}
+ @NotNull
+ protected IElementType getUnicodeEscapeSequenceType() {
+ for (int i = myStart + 2; i < myStart + 6; i++) {
+ if (i >= myEnd || !StringUtil.isHexDigit(myBuffer.charAt(i))) return StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN;
+ }
+ return StringEscapesTokenTypes.VALID_STRING_ESCAPE_TOKEN;
+ }
+
// all subsequent chars are escaped spaces
private boolean isTrailingSpace(final int start) {
for (int i=start;i T submitTransactionAndWait(@NotNull TransactionKind kind, @NotNull final Computable transaction) throws ProcessCanceledException {
+ final Ref result = Ref.create();
+ submitTransactionAndWait(kind, new Runnable() {
+ @Override
+ public void run() {
+ result.set(transaction.compute());
+ }
+ });
+ return result.get();
+ }
+
/**
* A synchronous version of {@link #submitMergeableTransaction(TransactionKind, Runnable)}.
* @return a token object for this transaction. Call {@link AccessToken#finish()} (inside finally) when the transaction is complete.
diff --git a/platform/core-api/src/com/intellij/psi/util/PsiCacheKey.java b/platform/core-api/src/com/intellij/psi/util/PsiCacheKey.java
index d91e4823c5c0..bd57a08c6ba6 100644
--- a/platform/core-api/src/com/intellij/psi/util/PsiCacheKey.java
+++ b/platform/core-api/src/com/intellij/psi/util/PsiCacheKey.java
@@ -76,7 +76,7 @@ public class PsiCacheKey extends Key template2argument = findMatchingTemplates(file, editor, shortcutChar, templateSettings);
+ Map template2argument = findMatchingTemplates(file, editor, shortcutChar, TemplateSettings.getInstance());
- for (final CustomLiveTemplate customLiveTemplate : CustomLiveTemplate.EP_NAME.getExtensions()) {
- if (shortcutChar == customLiveTemplate.getShortcut()) {
- if (editor.getCaretModel().getCaretCount() > 1 && !supportsMultiCaretMode(customLiveTemplate)) {
- continue;
- }
- final Document document = editor.getDocument();
- PsiDocumentManager.getInstance(myProject).commitDocument(document);
- if (isApplicable(customLiveTemplate, editor, file)) {
- final CustomTemplateCallback callback = new CustomTemplateCallback(editor, file);
- final String key = customLiveTemplate.computeTemplateKey(callback);
+ List customCandidates = ContainerUtil.findAll(CustomLiveTemplate.EP_NAME.getExtensions(), customLiveTemplate ->
+ shortcutChar == customLiveTemplate.getShortcut() &&
+ (editor.getCaretModel().getCaretCount() <= 1 || supportsMultiCaretMode(customLiveTemplate)));
+ if (!customCandidates.isEmpty()) {
+ int caretOffset = editor.getCaretModel().getOffset();
+ PsiFile fileCopy = insertDummyIdentifierIfNeeded(file, caretOffset, caretOffset, "");
+ Document document = editor.getDocument();
+
+ for (final CustomLiveTemplate customLiveTemplate : customCandidates) {
+ if (isApplicable(customLiveTemplate, editor, fileCopy)) {
+ final String key = customLiveTemplate.computeTemplateKey(new CustomTemplateCallback(editor, fileCopy));
if (key != null) {
- int caretOffset = editor.getCaretModel().getOffset();
int offsetBeforeKey = caretOffset - key.length();
CharSequence text = document.getImmutableCharSequence();
if (template2argument == null || !containsTemplateStartingBefore(template2argument, offsetBeforeKey, caretOffset, text)) {
- return new Runnable() {
- @Override
- public void run() {
- customLiveTemplate.expand(key, callback);
- }
- };
+ return () -> customLiveTemplate.expand(key, new CustomTemplateCallback(editor, file));
}
}
}
}
}
+
return startNonCustomTemplates(template2argument, editor, processor);
}
@@ -357,13 +356,6 @@ public class TemplateManagerImpl extends TemplateManager implements Disposable {
return null;
}
- CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
- @Override
- public void run() {
- PsiDocumentManager.getInstance(myProject).commitDocument(document);
- }
- }, "", null);
-
candidatesWithoutArgument = filterApplicableCandidates(file, caretOffset, candidatesWithoutArgument);
candidatesWithArgument = filterApplicableCandidates(file, argumentOffset, candidatesWithArgument);
Map candidate2Argument = new HashMap();
@@ -474,7 +466,7 @@ public class TemplateManagerImpl extends TemplateManager implements Disposable {
return candidates;
}
- PsiFile copy = insertDummyIdentifier(file, caretOffset, caretOffset);
+ PsiFile copy = insertDummyIdentifierIfNeeded(file, caretOffset, caretOffset, CompletionUtil.DUMMY_IDENTIFIER_TRIMMED);
List result = new ArrayList();
for (TemplateImpl candidate : candidates) {
@@ -610,15 +602,34 @@ public class TemplateManagerImpl extends TemplateManager implements Disposable {
boolean selection = editor.getSelectionModel().hasSelection();
final int startOffset = selection ? editor.getSelectionModel().getSelectionStart() : editor.getCaretModel().getOffset();
final int endOffset = selection ? editor.getSelectionModel().getSelectionEnd() : startOffset;
- return insertDummyIdentifier(file, startOffset, endOffset);
+ return insertDummyIdentifierIfNeeded(file, startOffset, endOffset, CompletionUtil.DUMMY_IDENTIFIER_TRIMMED);
}
- public static PsiFile insertDummyIdentifier(PsiFile file, final int startOffset, final int endOffset) {
- file = (PsiFile)file.copy();
- final Document document = file.getViewProvider().getDocument();
- assert document != null;
- document.replaceString(startOffset, endOffset, CompletionUtil.DUMMY_IDENTIFIER_TRIMMED);
- PsiDocumentManager.getInstance(file.getProject()).commitDocument(document);
- return file;
+ private static PsiFile insertDummyIdentifierIfNeeded(PsiFile file, final int startOffset, final int endOffset, String replacement) {
+ Document originalDocument = file.getViewProvider().getDocument();
+ assert originalDocument != null;
+
+ if (replacement.isEmpty() && PsiDocumentManager.getInstance(file.getProject()).isCommitted(originalDocument)) {
+ return file;
+ }
+
+ ConcurrentFactoryMap, PsiFile> map =
+ CachedValuesManager.getCachedValue(file, () -> CachedValueProvider.Result.create(new ConcurrentFactoryMap, PsiFile>() {
+ @Nullable
+ @Override
+ protected PsiFile create(Trinity key) {
+ PsiFile copy = (PsiFile)file.copy();
+
+ final Document document = copy.getViewProvider().getDocument();
+ assert document != null;
+
+ document.setText(originalDocument.getImmutableCharSequence()); // original file might be uncommitted
+ document.replaceString(key.first, key.second, key.third);
+ PsiDocumentManager.getInstance(copy.getProject()).commitDocument(document);
+ return copy;
+ }
+ }, file, originalDocument));
+
+ return map.get(Trinity.create(startOffset, endOffset, replacement));
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/ExpandLiveTemplateCustomAction.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/ExpandLiveTemplateCustomAction.java
index 44f138f2229a..c35a85497d57 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/ExpandLiveTemplateCustomAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/ExpandLiveTemplateCustomAction.java
@@ -36,7 +36,7 @@ public class ExpandLiveTemplateCustomAction extends EditorAction {
setInjectedContext(true);
}
- static EditorWriteActionHandler createExpandTemplateHandler(final char shortcutChar) {
+ public static EditorWriteActionHandler createExpandTemplateHandler(final char shortcutChar) {
return new EditorWriteActionHandler(true) {
@Override
public void executeWriteAction(Editor editor, @Nullable Caret caret, DataContext dataContext) {
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/actions/ViewOfflineResultsAction.java b/platform/lang-impl/src/com/intellij/codeInspection/actions/ViewOfflineResultsAction.java
index 1cbba4208da2..2feab8fec30e 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/actions/ViewOfflineResultsAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/actions/ViewOfflineResultsAction.java
@@ -225,9 +225,7 @@ public class ViewOfflineResultsAction extends AnAction {
final InspectionResultsView view = new InspectionResultsView(context,
new OfflineInspectionRVContentProvider(resMap, project));
((RefManagerImpl)context.getRefManager()).startOfflineView();
- ApplicationManager.getApplication().executeOnPooledThread(() -> {
- ApplicationManager.getApplication().runReadAction((Runnable)view::buildTree);
- });
+ view.update();
TreeUtil.selectFirstNode(view.getTree());
context.addView(view, title);
return view;
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java
index 74dd8f344560..99bdc8a754ad 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java
@@ -91,7 +91,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.GlobalInspectionContextImpl");
private static final NotificationGroup NOTIFICATION_GROUP = NotificationGroup.toolWindowGroup("Inspection Results", ToolWindowId.INSPECTION);
private final NotNullLazyValue myContentManager;
- private InspectionResultsView myView;
+ private volatile InspectionResultsView myView;
private Content myContent;
private volatile boolean myViewClosed = true;
@@ -125,7 +125,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
});
myView = view;
- myView.getTree().setPaintBusy(true);
+ myView.setUpdating(true);
myContent = ContentFactory.SERVICE.getInstance().createContent(view, title, false);
myContent.setDisposer(myView);
@@ -344,7 +344,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
} else {
view = null;
}
- if (!(myView == null ? view : myView).update() && !getUIOptions().SHOW_ONLY_DIFF) {
+ if (!(myView == null ? view : myView).hasProblems() && !getUIOptions().SHOW_ONLY_DIFF) {
NOTIFICATION_GROUP.createNotification(InspectionsBundle.message("inspection.no.problems.message", scope.getFileCount(), scope.getDisplayName()), MessageType.INFO).notify(getProject());
close(true);
if (view != null) {
@@ -355,7 +355,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
addView(view);
}
if (myView != null) {
- myView.getTree().setPaintBusy(false);
+ myView.setUpdating(false);
}
}
});
@@ -779,7 +779,15 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
@Override
public void close(boolean noSuspisiousCodeFound) {
- if (!noSuspisiousCodeFound && (myView == null || myView.isRerun())) return;
+ if (!noSuspisiousCodeFound) {
+ if (myView.isRerun()) {
+ myViewClosed = true;
+ myView = null;
+ }
+ if (myView == null) {
+ return;
+ }
+ }
AnalysisUIOptions.getInstance(getProject()).save(myUIOptions);
if (myContent != null) {
final ContentManager contentManager = getContentManager();
@@ -800,7 +808,7 @@ public class GlobalInspectionContextImpl extends GlobalInspectionContextBase imp
}
}
if (myView != null) {
- myView.getTree().setPaintBusy(false);
+ myView.setUpdating(false);
}
super.cleanup();
}
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/PerformFixesModalTask.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/PerformFixesModalTask.java
index 96281b57098f..fc5b3964730e 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ex/PerformFixesModalTask.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/PerformFixesModalTask.java
@@ -77,13 +77,11 @@ public abstract class PerformFixesModalTask implements SequentialTask {
final QuickFix[] fixes = descriptor.getFixes();
if (fixes != null) {
for (QuickFix fix : fixes) {
- if (fix instanceof IntentionAction) {
- if (!((IntentionAction)fix).startInWriteAction()) {
- runInReadAction[0] = true;
- } else {
- runInReadAction[0] = false;
- break;
- }
+ if (!fix.startInWriteAction()) {
+ runInReadAction[0] = true;
+ } else {
+ runInReadAction[0] = false;
+ break;
}
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java
index d3cf6cbfb2fd..089651efa15d 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java
@@ -77,7 +77,7 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro
private Map myOldProblemElements = null;
protected static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.DescriptorProviderInspection");
- private boolean isDisposed;
+ private volatile boolean isDisposed;
public DefaultInspectionToolPresentation(@NotNull InspectionToolWrapper toolWrapper, @NotNull GlobalInspectionContextImpl context) {
myToolWrapper = toolWrapper;
@@ -230,46 +230,43 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro
return;
}
if (myToolWrapper instanceof LocalInspectionToolWrapper) {
- UIUtil.invokeLaterIfNeeded(new Runnable() {
- @Override
- public void run() {
- InspectionResultsView view = context.getView();
- if (view == null) {
- view = new InspectionResultsView(context,
- new InspectionRVContentProviderImpl(context.getProject()));
- context.addView(view);
+ InspectionResultsView view = context.getView();
+ if (view == null) {
+ view = UIUtil.invokeAndWaitIfNeeded(() -> {
+ InspectionResultsView newView = context.getView();
+ if (newView != null) {
+ return newView;
}
- if (!isDisposed()) {
- final InspectionResultsView finalView = view;
- ApplicationManager.getApplication().executeOnPooledThread(() -> {
- ApplicationManager.getApplication().runReadAction(() -> {
- synchronized (finalView.getTreeWriteLock()) {
- final InspectionNode toolNode;
- toolNode = myToolNode == null ?
- finalView.addTool(myToolWrapper, HighlightDisplayLevel.find(getSeverity((RefElement)refElement)),
- context.getUIOptions().GROUP_BY_SEVERITY) : myToolNode;
+ newView = new InspectionResultsView(context, new InspectionRVContentProviderImpl(context.getProject()));
+ context.addView(newView);
+ return newView;
+ });
+ }
+ if (!isDisposed()) {
+ ApplicationManager.getApplication().assertReadAccessAllowed();
+ synchronized (view.getTreeWriteLock()) {
+ final InspectionNode toolNode;
+ toolNode = myToolNode == null ?
+ view.addTool(myToolWrapper, HighlightDisplayLevel.find(getSeverity((RefElement)refElement)),
+ context.getUIOptions().GROUP_BY_SEVERITY) : myToolNode;
- final Map problems = new HashMap();
- problems.put(refElement, descriptors);
- final Map> contents = new HashMap>();
- final String groupName = refElement.getRefManager().getGroupName((RefElement)refElement);
- Set content = contents.get(groupName);
- if (content == null) {
- content = new HashSet();
- contents.put(groupName, content);
- }
- content.add(refElement);
-
- finalView.getProvider().appendToolNodeContent(context, toolNode,
- (InspectionTreeNode)toolNode.getParent(), context.getUIOptions().SHOW_STRUCTURE,
- contents, problems, (DefaultTreeModel)finalView.getTree().getModel());
-
- }
- });
- });
+ final Map problems = new HashMap();
+ problems.put(refElement, descriptors);
+ final Map> contents = new HashMap>();
+ final String groupName = refElement.getRefManager().getGroupName((RefElement)refElement);
+ Set content = contents.get(groupName);
+ if (content == null) {
+ content = new HashSet();
+ contents.put(groupName, content);
}
+ content.add(refElement);
+
+ view.getProvider().appendToolNodeContent(context, toolNode,
+ (InspectionTreeNode)toolNode.getParent(), context.getUIOptions().SHOW_STRUCTURE,
+ contents, problems, (DefaultTreeModel)view.getTree().getModel());
+
}
- });
+ }
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java
index f4a00097dee2..f29ea68ee74c 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java
@@ -34,6 +34,7 @@ import com.intellij.ide.actions.ContextHelpAction;
import com.intellij.injected.editor.VirtualFileWindow;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
@@ -43,6 +44,7 @@ import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.ui.popup.JBPopup;
+import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
@@ -50,10 +52,7 @@ import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.pom.Navigatable;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
-import com.intellij.psi.PsiDirectory;
-import com.intellij.psi.PsiDocumentManager;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
+import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.ui.*;
import com.intellij.ui.components.JBLabel;
@@ -62,6 +61,7 @@ import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.EditSourceOnDoubleClickHandler;
import com.intellij.util.OpenSourceUtil;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -94,7 +94,8 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
private final Project myProject;
private final InspectionTree myTree;
- private final ConcurrentMap> myGroups = ContainerUtil.newConcurrentMap();
+ private final ConcurrentMap> myGroups =
+ ContainerUtil.newConcurrentMap();
private final OccurenceNavigator myOccurenceNavigator;
private volatile InspectionProfile myInspectionProfile;
@NotNull
@@ -108,12 +109,14 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
private final GlobalInspectionContextImpl myGlobalInspectionContext;
private boolean myRerun;
private volatile boolean myDisposed;
+ private boolean myUpdating;
@NotNull
private final InspectionRVContentProvider myProvider;
private AnAction myIncludeAction;
private AnAction myExcludeAction;
private Editor myPreviewEditor;
+ private InspectionTreeLoadingProgressAware myLoadingProgressPreview;
private final Object myTreeWriteLock = new Object();
@@ -126,7 +129,7 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
myGlobalInspectionContext = globalInspectionContext;
myProvider = provider;
- myTree = new InspectionTree(myProject, globalInspectionContext);
+ myTree = new InspectionTree(myProject, globalInspectionContext, this);
initTreeListeners();
myOccurenceNavigator = initOccurenceNavigator();
@@ -144,8 +147,24 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
createActionsToolbar();
TreeUtil.selectFirstNode(myTree);
- }
+ PsiManager.getInstance(myProject).addPsiTreeChangeListener(new PsiTreeChangeAdapter() {
+ @Override
+ public void childRemoved(@NotNull PsiTreeChangeEvent event) {
+ myTree.queueUpdate();
+ }
+
+ @Override
+ public void childReplaced(@NotNull PsiTreeChangeEvent event) {
+ myTree.queueUpdate();
+ }
+
+ @Override
+ public void childMoved(@NotNull PsiTreeChangeEvent event) {
+ myTree.queueUpdate();
+ }
+ }, this);
+ }
private void initTreeListeners() {
@@ -181,7 +200,7 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
SmartExpander.installOn(myTree);
}
- private OccurenceNavigatorSupport initOccurenceNavigator(){
+ private OccurenceNavigatorSupport initOccurenceNavigator() {
return new OccurenceNavigatorSupport(myTree) {
@Override
@Nullable
@@ -238,7 +257,7 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
@SuppressWarnings({"NonStaticInitializer"})
private JComponent createRightActionsToolbar() {
- myIncludeAction = new AnAction(InspectionsBundle.message("inspections.result.view.include.action.text")){
+ myIncludeAction = new AnAction(InspectionsBundle.message("inspections.result.view.include.action.text")) {
{
registerCustomShortcutSet(CommonShortcuts.INSERT, myTree);
}
@@ -251,13 +270,13 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
((InspectionTreeNode)path.getLastPathComponent()).amnesty();
}
}
- updateView(false);
+ myTree.queueUpdate();
}
@Override
public void update(final AnActionEvent e) {
final TreePath[] paths = myTree.getSelectionPaths();
- e.getPresentation().setEnabled(paths != null && paths.length > 0 &&
+ e.getPresentation().setEnabled(paths != null && paths.length > 0 &&
!myGlobalInspectionContext.getUIOptions().FILTER_RESOLVED_ITEMS);
}
};
@@ -383,6 +402,10 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
private void syncRightPanel() {
final Editor oldEditor = myPreviewEditor;
+ if (myLoadingProgressPreview != null) {
+ Disposer.dispose(myLoadingProgressPreview);
+ myLoadingProgressPreview = null;
+ }
if (myTree.getSelectionModel().getSelectionCount() != 1) {
if (myTree.getSelectedToolWrapper() == null) {
mySplitter.setSecondComponent(getNothingToShowTextLabel());
@@ -408,12 +431,15 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
final String shortName = ((InspectionNode)node).getToolWrapper().getShortName();
if (shortName.isEmpty()) {
mySplitter.setSecondComponent(getNothingToShowTextLabel());
- } else {
+ }
+ else {
showInRightPanel(null);
}
}
else if (node instanceof InspectionRootNode || node instanceof InspectionGroupNode || node instanceof InspectionSeverityGroupNode) {
- mySplitter.setSecondComponent(new InspectionViewNavigationPanel(node, myTree));
+ final InspectionViewNavigationPanel panel = new InspectionViewNavigationPanel(node, myTree);
+ myLoadingProgressPreview = panel;
+ mySplitter.setSecondComponent(panel);
}
else {
LOG.error("Unexpected node: " + node.getClass());
@@ -456,11 +482,9 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
}
editorPanel.add(previewPanel, BorderLayout.CENTER);
if (problemCount > 0) {
- editorPanel.add(new QuickFixToolbar(myTree,
- myProject,
- myPreviewEditor,
- myProvider.getQuickFixes(tool, myTree)),
- BorderLayout.NORTH);
+ final QuickFixToolbar fixToolbar = new QuickFixToolbar(myPreviewEditor, this);
+ myLoadingProgressPreview = fixToolbar;
+ editorPanel.add(fixToolbar, BorderLayout.NORTH);
}
mySplitter.setSecondComponent(editorPanel);
}
@@ -526,7 +550,9 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
}
@NotNull
- public InspectionNode addTool(@NotNull final InspectionToolWrapper toolWrapper, HighlightDisplayLevel errorLevel, boolean groupedBySeverity) {
+ public InspectionNode addTool(@NotNull final InspectionToolWrapper toolWrapper,
+ HighlightDisplayLevel errorLevel,
+ boolean groupedBySeverity) {
String groupName =
toolWrapper.getGroupDisplayName().isEmpty() ? InspectionProfileEntry.GENERAL_GROUP_NAME : toolWrapper.getGroupDisplayName();
InspectionTreeNode parentNode = getToolParentNode(groupName, errorLevel, groupedBySeverity);
@@ -551,11 +577,6 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
}
}
- private void clearTree() {
- myTree.removeAllNodes();
- mySeverityGroupNodes.clear();
- }
-
@Nullable
public String getCurrentProfileName() {
return myInspectionProfile == null ? null : myInspectionProfile.getDisplayName();
@@ -565,45 +586,73 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
return myInspectionProfile;
}
- public boolean update(){
- return updateView(true);
+ public void update() {
+ updateView(true);
}
- public boolean updateView(boolean strict) {
- if (!strict && !myGlobalInspectionContext.getUIOptions().FILTER_RESOLVED_ITEMS){
+ public void updateView(boolean strict) {
+ ApplicationManager.getApplication().assertIsDispatchThread();
+ if (!strict && !myGlobalInspectionContext.getUIOptions().FILTER_RESOLVED_ITEMS) {
myTree.repaint();
- return false;
}
- clearTree();
- boolean resultsFound = buildTree();
- myTree.restoreExpansionAndSelection();
- return resultsFound;
+ myTree.removeAllNodes();
+ mySeverityGroupNodes.clear();
+ buildTree();
+ }
+
+ public void setUpdating(boolean isUpdating) {
+ final Runnable update = () -> {
+ myUpdating = isUpdating;
+ myTree.setPaintBusy(isUpdating);
+ if (!isUpdating && myLoadingProgressPreview != null) {
+ myLoadingProgressPreview.treeLoaded();
+ }
+ };
+ final Application app = ApplicationManager.getApplication();
+ if (app.isDispatchThread()) {
+ update.run();
+ }
+ else {
+ app.invokeLater(update, ModalityState.any());
+ }
}
public Object getTreeWriteLock() {
return myTreeWriteLock;
}
- public boolean buildTree() {
- synchronized (myTreeWriteLock) {
- InspectionProfile profile = myInspectionProfile;
- boolean isGroupedBySeverity = myGlobalInspectionContext.getUIOptions().GROUP_BY_SEVERITY;
- myGroups.clear();
- final Map tools = myGlobalInspectionContext.getTools();
- boolean resultsFound = false;
- for (Tools currentTools : tools.values()) {
- InspectionToolWrapper defaultToolWrapper = currentTools.getDefaultState().getTool();
- final HighlightDisplayKey key = HighlightDisplayKey.find(defaultToolWrapper.getShortName());
- for (ScopeToolState state : myProvider.getTools(currentTools)) {
- InspectionToolWrapper toolWrapper = state.getTool();
- if (myProvider.checkReportedProblems(myGlobalInspectionContext, toolWrapper)) {
- addTool(toolWrapper, ((InspectionProfileImpl)profile).getErrorLevel(key, state.getScope(myProject), myProject),
+ public void buildTree() {
+ final Application app = ApplicationManager.getApplication();
+ final Runnable buildAction = () -> {
+ try {
+ setUpdating(true);
+ InspectionProfile profile = myInspectionProfile;
+ boolean isGroupedBySeverity = myGlobalInspectionContext.getUIOptions().GROUP_BY_SEVERITY;
+ myGroups.clear();
+ final Map tools = myGlobalInspectionContext.getTools();
+ for (Tools currentTools : tools.values()) {
+ InspectionToolWrapper defaultToolWrapper = currentTools.getDefaultState().getTool();
+ final HighlightDisplayKey key = HighlightDisplayKey.find(defaultToolWrapper.getShortName());
+ for (ScopeToolState state : myProvider.getTools(currentTools)) {
+ InspectionToolWrapper toolWrapper = state.getTool();
+ if (myProvider.checkReportedProblems(myGlobalInspectionContext, toolWrapper)) {
+ addTool(toolWrapper, ((InspectionProfileImpl)profile).getErrorLevel(key, state.getScope(myProject), myProject),
isGroupedBySeverity);
- resultsFound = true;
+ }
}
}
}
- return resultsFound;
+ finally {
+ setUpdating(false);
+ UIUtil.invokeLaterIfNeeded(myTree::restoreExpansionAndSelection);
+ }
+ };
+ if (app.isUnitTestMode()) {
+ buildAction.run();
+ } else {
+ app.executeOnPooledThread(() -> {
+ app.runReadAction(buildAction);
+ });
}
}
@@ -627,7 +676,7 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
}
}
if (group == null) {
- group = ConcurrencyUtil.cacheOrGet(map, groupName, new InspectionGroupNode(groupName));
+ group = ConcurrencyUtil.cacheOrGet(map, groupName, new InspectionGroupNode(groupName));
if (!myDisposed) {
insertByIndex(group, getRelativeRootNode(groupedBySeverity, errorLevel));
}
@@ -756,7 +805,7 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
@Nullable
private Navigatable getSelectedNavigatable(final CommonProblemDescriptor descriptor, final PsiElement psiElement) {
if (descriptor instanceof ProblemDescriptorBase) {
- Navigatable navigatable = ((ProblemDescriptorBase) descriptor).getNavigatable();
+ Navigatable navigatable = ((ProblemDescriptorBase)descriptor).getNavigatable();
if (navigatable != null) {
return navigatable;
}
@@ -837,7 +886,7 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
}
@NotNull
- public InspectionTree getTree(){
+ public InspectionTree getTree() {
return myTree;
}
@@ -887,7 +936,8 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
final InputEvent event = e.getInputEvent();
if (event instanceof MouseEvent) {
popup.showUnderneathOf(event.getComponent());
- } else {
+ }
+ else {
popup.showInBestPositionFor(e.getDataContext());
}
}
@@ -900,6 +950,29 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
syncRightPanel();
}
+ public boolean isUpdating() {
+ return myUpdating;
+ }
+
+ public void updateRightPanelLoading() {
+ if (!myDisposed && isUpdating() && myLoadingProgressPreview != null) {
+ myLoadingProgressPreview.updateLoadingProgress();
+ }
+ }
+
+ public boolean hasProblems() {
+ final Map tools = myGlobalInspectionContext.getTools();
+ for (Tools currentTools : tools.values()) {
+ for (ScopeToolState state : myProvider.getTools(currentTools)) {
+ InspectionToolWrapper toolWrapper = state.getTool();
+ if (myProvider.checkReportedProblems(myGlobalInspectionContext, toolWrapper)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
private class CloseAction extends AnAction implements DumbAware {
private CloseAction() {
super(CommonBundle.message("action.close"), null, AllIcons.Actions.Cancel);
@@ -929,9 +1002,10 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
if (toolWrapper != null) {
final HighlightDisplayKey key = HighlightDisplayKey.find(toolWrapper.getShortName()); //do not search for dead code entry point tool
- if (key != null){
- if (new EditInspectionToolsSettingsAction(key).editToolSettings(myProject, (InspectionProfileImpl)inspectionProfile, profileIsDefined)
- && profileIsDefined){
+ if (key != null) {
+ if (new EditInspectionToolsSettingsAction(key)
+ .editToolSettings(myProject, (InspectionProfileImpl)inspectionProfile, profileIsDefined)
+ && profileIsDefined) {
updateCurrentProfile();
}
return;
@@ -941,7 +1015,7 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
updateCurrentProfile();
}
}
- }
+ }
public void updateCurrentProfile() {
final String name = myInspectionProfile.getName();
@@ -964,6 +1038,7 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren
public void actionPerformed(AnActionEvent e) {
rerun();
}
+
private void rerun() {
myRerun = true;
if (myScope.isValid()) {
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTree.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTree.java
index 3443152fe515..a9807900b53c 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTree.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTree.java
@@ -24,7 +24,6 @@ package com.intellij.codeInspection.ui;
import com.intellij.codeInspection.CommonProblemDescriptor;
import com.intellij.codeInspection.InspectionsBundle;
-import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ex.*;
import com.intellij.codeInspection.reference.RefElement;
import com.intellij.codeInspection.reference.RefEntity;
@@ -40,7 +39,6 @@ import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.ui.UIUtil;
-import com.intellij.util.ui.tree.TreeModelAdapter;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -59,8 +57,9 @@ public class InspectionTree extends Tree {
private SelectionPath mySelectionPath;
private boolean myQueueUpdate;
- public InspectionTree(@NotNull Project project, @NotNull GlobalInspectionContextImpl context) {
- setModel(new DefaultTreeModel(new InspectionRootNode(project, new InspectionTreeUpdater(this))));
+ public InspectionTree(@NotNull Project project,
+ @NotNull GlobalInspectionContextImpl context, InspectionResultsView view) {
+ setModel(new DefaultTreeModel(new InspectionRootNode(project, new InspectionTreeUpdater(view))));
myContext = context;
setCellRenderer(new CellRenderer());
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTreeLoadingProgressAware.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTreeLoadingProgressAware.java
new file mode 100644
index 000000000000..4ad87cb489bc
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTreeLoadingProgressAware.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.codeInspection.ui;
+
+import com.intellij.openapi.Disposable;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public interface InspectionTreeLoadingProgressAware extends Disposable {
+
+ void updateLoadingProgress();
+
+ void treeLoaded();
+
+ @Override
+ default void dispose() {
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTreeNode.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTreeNode.java
index 574902b3c16e..0927185fb70f 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTreeNode.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTreeNode.java
@@ -22,7 +22,9 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
+import javax.swing.tree.TreeNode;
import java.util.Enumeration;
/**
@@ -87,7 +89,7 @@ public abstract class InspectionTreeNode extends DefaultMutableTreeNode {
super.add(newChild);
if (myUpdater != null) {
((InspectionTreeNode)newChild).propagateUpdater(myUpdater);
- myUpdater.update();
+ myUpdater.updateWithPreviewPanel();
}
}
@@ -96,7 +98,7 @@ public abstract class InspectionTreeNode extends DefaultMutableTreeNode {
super.insert(newChild, childIndex);
if (myUpdater != null) {
((InspectionTreeNode)newChild).propagateUpdater(myUpdater);
- myUpdater.update();
+ myUpdater.updateWithPreviewPanel();
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTreeUpdater.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTreeUpdater.java
index 338055f2c7d5..e10a744feb35 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTreeUpdater.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionTreeUpdater.java
@@ -20,21 +20,24 @@ import com.intellij.util.ui.update.MergingUpdateQueue;
import com.intellij.util.ui.update.Update;
import javax.swing.tree.DefaultTreeModel;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author Dmitry Batkovich
*/
public class InspectionTreeUpdater {
- private final InspectionTree myTree;
private final MergingUpdateQueue myUpdateQueue;
+ private final InspectionResultsView myView;
+ private final AtomicBoolean myDoUpdatePreviewPanel = new AtomicBoolean(false);
- public InspectionTreeUpdater(InspectionTree tree) {
- myTree = tree;
- myUpdateQueue = new MergingUpdateQueue("InspectionView", 100, true, tree);
+ public InspectionTreeUpdater(InspectionResultsView view) {
+ myView = view;
+ myUpdateQueue = new MergingUpdateQueue("InspectionView", 100, true, view);
}
- public void update() {
+ public void updateWithPreviewPanel() {
update(false);
+ myDoUpdatePreviewPanel.compareAndSet(false, true);
}
public void update(boolean force) {
@@ -44,14 +47,18 @@ public class InspectionTreeUpdater {
myUpdateQueue.queue(new Update("TreeRepaint") {
@Override
public void run() {
+ final InspectionTree tree = myView.getTree();
try {
- myTree.setQueueUpdate(true);
- ((DefaultTreeModel)myTree.getModel()).reload();
- myTree.revalidate();
- myTree.repaint();
- myTree.restoreExpansionAndSelection();
+ tree.setQueueUpdate(true);
+ ((DefaultTreeModel)tree.getModel()).reload();
+ tree.revalidate();
+ tree.repaint();
+ tree.restoreExpansionAndSelection();
+ if (myDoUpdatePreviewPanel.compareAndSet(true, false)) {
+ myView.updateRightPanelLoading();
+ }
} finally {
- myTree.setQueueUpdate(false);
+ tree.setQueueUpdate(false);
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionViewNavigationPanel.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionViewNavigationPanel.java
index 0b316bb3b9c9..7db226688f08 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionViewNavigationPanel.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionViewNavigationPanel.java
@@ -30,26 +30,43 @@ import java.awt.*;
/**
* @author Dmitry Batkovich
*/
-public class InspectionViewNavigationPanel extends JPanel {
+public class InspectionViewNavigationPanel extends JPanel implements InspectionTreeLoadingProgressAware {
+ private final InspectionTreeNode myNode;
+ private final InspectionTree myTree;
+ private final JPanel myLinks;
+ private int myShownChildrenCount;
+
public InspectionViewNavigationPanel(InspectionTreeNode node, InspectionTree tree) {
+ myNode = node;
+ myTree = tree;
setLayout(new BorderLayout());
setBorder(IdeBorderFactory.createEmptyBorder(5, 7, 0, 0));
- final String titleLabelText = getTitleText(node instanceof InspectionRootNode, true);
+ final String titleLabelText = getTitleText(myNode instanceof InspectionRootNode, true);
add(new JBLabel(titleLabelText), BorderLayout.NORTH);
- final JPanel links = new JPanel();
- links.setLayout(new BoxLayout(links, BoxLayout.Y_AXIS));
- links.add(Box.createVerticalStrut(JBUI.scale(10)));
- add(BorderLayout.CENTER, links);
- for (int i = 0; i < node.getChildCount(); i++) {
- final TreeNode child = node.getChildAt(i);
- final LinkLabel link = new LinkLabel(child.toString(), null) {
- @Override
- public void doClick() {
- TreeUtil.selectInTree((DefaultMutableTreeNode)child, true, tree);
- }
- };
- link.setBorder(IdeBorderFactory.createEmptyBorder(1, 17, 3, 1));
- links.add(link);
+ myLinks = new JPanel();
+ myLinks.setLayout(new BoxLayout(myLinks, BoxLayout.Y_AXIS));
+
+ add(BorderLayout.CENTER, myLinks);
+ resetChildrenNavigation();
+ }
+
+ private void resetChildrenNavigation() {
+ final int currentChildrenCount = myNode.getChildCount();
+ if (myShownChildrenCount != currentChildrenCount) {
+ myLinks.removeAll();
+ myLinks.add(Box.createVerticalStrut(JBUI.scale(10)));
+ for (int i = 0; i < currentChildrenCount; i++) {
+ final TreeNode child = myNode.getChildAt(i);
+ final LinkLabel link = new LinkLabel(child.toString(), null) {
+ @Override
+ public void doClick() {
+ TreeUtil.selectInTree((DefaultMutableTreeNode)child, true, myTree);
+ }
+ };
+ link.setBorder(IdeBorderFactory.createEmptyBorder(1, 17, 3, 1));
+ myLinks.add(link);
+ }
+ myShownChildrenCount = currentChildrenCount;
}
}
@@ -57,4 +74,14 @@ public class InspectionViewNavigationPanel extends JPanel {
public static String getTitleText(boolean addGroupWord, boolean addColon) {
return "Select inspection" + (addGroupWord ? " group " : " ") + "to see problems" + (addColon ? ":" : ".");
}
+
+ @Override
+ public void updateLoadingProgress() {
+ resetChildrenNavigation();
+ }
+
+ @Override
+ public void treeLoaded() {
+ resetChildrenNavigation();
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/QuickFixToolbar.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/QuickFixToolbar.java
index 0208d56427f5..2a587334a10f 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ui/QuickFixToolbar.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/QuickFixToolbar.java
@@ -25,15 +25,15 @@ import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.ComboBoxAction;
import com.intellij.openapi.actionSystem.ex.CustomComponentAction;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Disposer;
import com.intellij.ui.ClickListener;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.SimpleColoredComponent;
-import com.intellij.ui.SimpleTextAttributes;
-import com.intellij.util.ui.JBInsets;
+import com.intellij.util.ui.AsyncProcessIcon;
import com.intellij.util.ui.JBUI;
-import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -41,48 +41,121 @@ import javax.swing.*;
import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.MouseEvent;
-import java.awt.image.BufferedImage;
import java.util.function.Supplier;
/**
* @author Dmitry Batkovich
*/
-public class QuickFixToolbar extends JPanel {
+public class QuickFixToolbar extends JPanel implements InspectionTreeLoadingProgressAware {
+ private static final Logger LOG = Logger.getInstance(QuickFixToolbar.class);
private static final int MAX_FIX_COUNT = 3;
+ @Nullable private final Editor myEditor;
+ @Nullable private final String myTargetName;
+ @NotNull private final InspectionResultsView myView;
+ private final InspectionToolWrapper myWrapper;
- public QuickFixToolbar(@NotNull InspectionTree tree,
- @NotNull Project project,
- @Nullable Editor editor,
- @Nullable QuickFixAction[] fixes) {
- final boolean hasFixes = fixes != null && fixes.length != 0;
- CommonProblemDescriptor[] descriptors = tree.getSelectedDescriptors();
+ private SimpleColoredComponent myWaitingLabel;
+
+ public QuickFixToolbar(@Nullable Editor editor,
+ @NotNull InspectionResultsView view) {
+ myEditor = editor;
+ myView = view;
+ myWrapper = view.getTree().getSelectedToolWrapper();
+ LOG.assertTrue(myWrapper != null);
+ CommonProblemDescriptor[] descriptors = myView.getTree().getSelectedDescriptors();
int problemCount = descriptors.length;
- final boolean multipleDescriptors = problemCount > 1;
setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
- setBorder(IdeBorderFactory.createEmptyBorder(7 + (hasFixes ? 0 : 5), hasFixes ? 12 : 9, hasFixes ? 0 : 6, 0));
+ setBorder(IdeBorderFactory.createEmptyBorder(7, 11, 0, 0));
+ myTargetName = getTargetName();
- fill(multipleDescriptors, () -> getLabel(fixes, tree.getSelectionCount() == 1 ? (InspectionTreeNode)tree.getSelectionPath().getLastPathComponent() : null, problemCount), this);
+ if (view.isUpdating() && !areDescriptorNodesSelected()) {
+ AsyncProcessIcon waitingIcon = new AsyncProcessIcon("Inspection preview panel updating...");
+ Disposer.register(this, waitingIcon);
+ myWaitingLabel = getLabel(null, problemCount);
+ add(myWaitingLabel);
+ add(waitingIcon);
+ }
+ else {
+ QuickFixAction[] fixes = view.getProvider().getQuickFixes(myWrapper, view.getTree());
+ fillPanel(editor, fixes, descriptors);
+ }
+ }
+
+ @Override
+ public void treeLoaded() {
+ if (myWaitingLabel != null) {
+ removeAll();
+ final InspectionTree tree = myView.getTree();
+ QuickFixAction[] fixes = myView.getProvider().getQuickFixes(myWrapper, tree);
+ CommonProblemDescriptor[] descriptors = tree.getSelectedDescriptors();
+ fillPanel(myEditor, fixes, descriptors);
+ }
+ }
+
+ @Override
+ public void updateLoadingProgress() {
+ if (myWaitingLabel != null) {
+ myWaitingLabel.clear();
+ final InspectionTree tree = myView.getTree();
+ appendTextToLabel(myWaitingLabel, tree.getSelectedProblemCount(), null);
+ }
+ }
+
+ private void fillPanel(@Nullable Editor editor,
+ @Nullable QuickFixAction[] fixes,
+ CommonProblemDescriptor[] descriptors) {
+ InspectionTree tree = myView.getTree();
+ Project project = myView.getProject();
+ boolean hasFixes = fixes != null && fixes.length != 0;
+ int problemCount = descriptors.length;
+ boolean multipleDescriptors = problemCount > 1;
+ fill(multipleDescriptors, () -> getLabel(fixes, problemCount), this);
fill(hasFixes, () -> createFixPanel(fixes, multipleDescriptors), this);
- fill(true, () -> createSuppressionCombo(tree.getSelectedToolWrapper(), tree.getSelectionPaths(), project, multipleDescriptors), this);
- fill(multipleDescriptors && editor != null, () -> ActionManager.getInstance().createActionToolbar("", GoToSubsequentOccurrenceAction.createNextPreviousActions(
- editor, descriptors), true).getComponent(), this);
+ fill(true, () -> createSuppressionCombo(myWrapper, tree.getSelectionPaths(), project, multipleDescriptors), this);
+ fill(multipleDescriptors && editor != null,
+ () -> ActionManager.getInstance().createActionToolbar("", GoToSubsequentOccurrenceAction.createNextPreviousActions(
+ editor, descriptors), true).getComponent(), this);
+ }
+
+ @Nullable
+ private String getTargetName() {
+ if (myView.getTree().getSelectionCount() == 1) {
+ final Object node = myView.getTree().getSelectionPath().getLastPathComponent();
+ return node instanceof RefElementNode ? ((RefElementNode)node).getElement().getName() : null;
+ }
+ return null;
+ }
+
+ private boolean areDescriptorNodesSelected() {
+ final TreePath[] paths = myView.getTree().getSelectionPaths();
+ for (TreePath path : paths) {
+ if (!(path.getLastPathComponent() instanceof ProblemDescriptionNode)) {
+ return false;
+ }
+ }
+ return true;
}
@NotNull
- private static JComponent getLabel(QuickFixAction[] fixes, InspectionTreeNode targetNode, int problemsCount) {
- final String targetName = targetNode instanceof RefElementNode ? ((RefElementNode)targetNode).getElement().getName() : null;
+ private SimpleColoredComponent getLabel(QuickFixAction[] fixes, int problemsCount) {
SimpleColoredComponent label = new SimpleColoredComponent();
+ appendTextToLabel(label, problemsCount, fixes);
+ label.setBorder(IdeBorderFactory.createEmptyBorder(0, 0, 0, 2));
+ return label;
+ }
+
+ private void appendTextToLabel(SimpleColoredComponent label,
+ int problemsCount,
+ QuickFixAction[] fixes) {
boolean hasFixesNonIntersectedFixes = fixes != null && fixes.length == 0;
label.append(problemsCount + " problems" +
- (targetName == null ? "" : (" in " + targetName)) +
- (problemsCount > 1 && (fixes != null && fixes.length == MAX_FIX_COUNT) ? " Fix all:" : "") +
- (hasFixesNonIntersectedFixes ? ":" : "" ));
+ (myTargetName == null ? "" : (" in " + myTargetName)) +
+ (problemsCount > 1 && (fixes != null && fixes.length >= MAX_FIX_COUNT) ? " Fix all:" : "") +
+ (hasFixesNonIntersectedFixes ? ":" : ""));
if (hasFixesNonIntersectedFixes) {
label.append(" select a single problem to see its quick fixes");
}
- label.setBorder(IdeBorderFactory.createEmptyBorder(0, 0, 0, 2));
- return label;
}
private static JComponent createSuppressionCombo(@NotNull final InspectionToolWrapper toolWrapper,
@@ -108,6 +181,14 @@ public class QuickFixToolbar extends JPanel {
return action.createCustomComponent(action.getTemplatePresentation());
}
+ private static void fill(boolean add,
+ @NotNull Supplier componentSupplier,
+ @NotNull JPanel parent) {
+ if (add) {
+ parent.add(componentSupplier.get());
+ }
+ }
+
@NotNull
private static JPanel createFixPanel(QuickFixAction[] fixes, boolean multipleDescriptors) {
JPanel fixPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, JBUI.scale(3), JBUI.scale(5)));
@@ -140,14 +221,6 @@ public class QuickFixToolbar extends JPanel {
return fixPanel;
}
- private static void fill(boolean add,
- @NotNull Supplier componentSupplier,
- @NotNull JPanel parent) {
- if (add) {
- parent.add(componentSupplier.get());
- }
- }
-
private static JComponent createQuickFixButton(@NotNull QuickFixAction fix, boolean multipleFixes) {
final MyCustomComponentLocalQuickFixWrapper action = new MyCustomComponentLocalQuickFixWrapper(fix);
if (multipleFixes) {
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java
index 52448f725767..004a3b5036b6 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java
@@ -73,6 +73,7 @@ import com.intellij.usageView.UsageInfo;
import com.intellij.usages.*;
import com.intellij.usages.impl.UsagePreviewPanel;
import com.intellij.util.*;
+import com.intellij.util.containers.Convertor;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -644,6 +645,12 @@ public class FindDialog extends DialogWrapper {
}
};
myResultsPreviewTable = table;
+ new TableSpeedSearch(table, new Convertor
diff --git a/plugins/junit/src/com/intellij/execution/ConfigurationUtil.java b/plugins/junit/src/com/intellij/execution/ConfigurationUtil.java
index 0d0354fabafa..040f4cb52bb3 100644
--- a/plugins/junit/src/com/intellij/execution/ConfigurationUtil.java
+++ b/plugins/junit/src/com/intellij/execution/ConfigurationUtil.java
@@ -35,8 +35,8 @@ import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.search.searches.ClassesWithAnnotatedMembersSearch;
import com.intellij.psi.stubsHierarchy.impl.ClassAnchorUtil;
-import com.intellij.psi.stubsHierarchy.impl.SingleClassHierarchy;
import com.intellij.psi.stubsHierarchy.impl.HierarchyService;
+import com.intellij.psi.stubsHierarchy.impl.SingleClassHierarchy;
import com.intellij.psi.stubsHierarchy.impl.SmartClassAnchor;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.Processor;
@@ -103,8 +103,9 @@ public class ConfigurationUtil {
}
Set processed = ContainerUtil.newHashSet();
- boolean hasJunit4 = addAnnotatedMethodsAnSubclasses(manager, scope, testClassFilter, found, processed, "org.junit.Test", true, symbols);
- hasJunit4 |= addAnnotatedMethodsAnSubclasses(manager, scope, testClassFilter, found, processed, "org.junit.runner.RunWith", false, symbols);
+ boolean hasJunit4 = addAnnotatedMethodsAnSubclasses(manager, scope, testClassFilter, found, processed, JUnitUtil.TEST_ANNOTATION, true, symbols);
+ hasJunit4 |= addAnnotatedMethodsAnSubclasses(manager, scope, testClassFilter, found, processed, JUnitUtil.TEST5_ANNOTATION, true, symbols);
+ hasJunit4 |= addAnnotatedMethodsAnSubclasses(manager, scope, testClassFilter, found, processed, JUnitUtil.RUN_WITH, false, symbols);
return hasJunit4;
}
diff --git a/plugins/junit/src/com/intellij/execution/junit/TestMethod.java b/plugins/junit/src/com/intellij/execution/junit/TestMethod.java
index 3b68c8fb60f8..2808eab23761 100644
--- a/plugins/junit/src/com/intellij/execution/junit/TestMethod.java
+++ b/plugins/junit/src/com/intellij/execution/junit/TestMethod.java
@@ -51,7 +51,7 @@ class TestMethod extends TestObject {
protected void addJUnit3Parameter(JavaParameters javaParameters, final JUnitConfiguration.Data data, Project project) throws ExecutionException {
final PsiClass psiClass = JavaExecutionUtil.findMainClass(project, data.getMainClassName(), GlobalSearchScope.allScope(project));
- if (psiClass == null || JUnitUtil.isJUnit4TestClass(psiClass)) {
+ if (psiClass == null || JUnitUtil.isJUnit4TestClass(psiClass) || JUnitUtil.isJUnit5(psiClass)) {
return;
}
final String methodName = data.getMethodName();
diff --git a/plugins/junit/src/com/intellij/execution/junit/TestObject.java b/plugins/junit/src/com/intellij/execution/junit/TestObject.java
index a48926d97494..2a25b1a0145f 100644
--- a/plugins/junit/src/com/intellij/execution/junit/TestObject.java
+++ b/plugins/junit/src/com/intellij/execution/junit/TestObject.java
@@ -40,10 +40,12 @@ import com.intellij.execution.testframework.*;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.execution.util.JavaParametersUtil;
import com.intellij.execution.util.ProgramParametersUtil;
+import com.intellij.junit5.JUnit5IdeaTestRunner;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Getter;
import com.intellij.openapi.util.Key;
@@ -51,6 +53,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.refactoring.listeners.RefactoringElementListener;
import com.intellij.rt.execution.junit.IDEAJUnitListener;
import com.intellij.rt.execution.junit.JUnitStarter;
@@ -155,6 +158,13 @@ public abstract class TestObject extends JavaTestFrameworkRunnableState findProcessor = new CommonProcessors.FindProcessor() {
diff --git a/plugins/junit5_rt/junit5_rt.iml b/plugins/junit5_rt/junit5_rt.iml
new file mode 100644
index 000000000000..ec639f339e82
--- /dev/null
+++ b/plugins/junit5_rt/junit5_rt.iml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/junit5_rt/lib/junit-commons-5.0.0-ALPHA.jar b/plugins/junit5_rt/lib/junit-commons-5.0.0-ALPHA.jar
new file mode 100644
index 000000000000..0e941851fd0e
Binary files /dev/null and b/plugins/junit5_rt/lib/junit-commons-5.0.0-ALPHA.jar differ
diff --git a/plugins/junit5_rt/lib/junit-engine-api-5.0.0-ALPHA.jar b/plugins/junit5_rt/lib/junit-engine-api-5.0.0-ALPHA.jar
new file mode 100644
index 000000000000..3346ebab9a16
Binary files /dev/null and b/plugins/junit5_rt/lib/junit-engine-api-5.0.0-ALPHA.jar differ
diff --git a/plugins/junit5_rt/lib/junit-launcher-5.0.0-ALPHA.jar b/plugins/junit5_rt/lib/junit-launcher-5.0.0-ALPHA.jar
new file mode 100644
index 000000000000..f881f91ec5bf
Binary files /dev/null and b/plugins/junit5_rt/lib/junit-launcher-5.0.0-ALPHA.jar differ
diff --git a/plugins/junit5_rt/lib/opentest4j-1.0.0.jar b/plugins/junit5_rt/lib/opentest4j-1.0.0.jar
new file mode 100644
index 000000000000..7208395ee319
Binary files /dev/null and b/plugins/junit5_rt/lib/opentest4j-1.0.0.jar differ
diff --git a/plugins/junit5_rt/src/com/intellij/junit5/JUnit5IdeaTestRunner.java b/plugins/junit5_rt/src/com/intellij/junit5/JUnit5IdeaTestRunner.java
new file mode 100644
index 000000000000..6084caddab43
--- /dev/null
+++ b/plugins/junit5_rt/src/com/intellij/junit5/JUnit5IdeaTestRunner.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.junit5;
+
+import com.intellij.rt.execution.junit.IdeaTestRunner;
+import com.intellij.rt.execution.junit.segments.OutputObjectRegistry;
+import org.junit.gen5.launcher.Launcher;
+import org.junit.gen5.launcher.TestDiscoveryRequest;
+import org.junit.gen5.launcher.TestIdentifier;
+import org.junit.gen5.launcher.TestPlan;
+import org.junit.gen5.launcher.main.LauncherFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+public class JUnit5IdeaTestRunner implements IdeaTestRunner {
+ private JUnit5TestExecutionListener myListener;
+ private TestPlan myTestPlan;
+
+ @Override
+ public int startRunnerWithArgs(String[] args, ArrayList listeners, String name, int count, boolean sendTree) {
+ Launcher launcher = LauncherFactory.create();
+ launcher.registerTestExecutionListeners(myListener);
+ final String[] packageNameRef = new String[1];
+ final TestDiscoveryRequest discoveryRequest = JUnit5TestRunnerUtil.buildRequest(args, packageNameRef);
+ myTestPlan = launcher.discover(discoveryRequest);
+ myListener.sendTree(myTestPlan, packageNameRef[0]);
+ launcher.execute(discoveryRequest);
+
+ return 0;
+ }
+
+ @Override
+ public void setStreams(Object segmentedOut, Object segmentedErr, int lastIdx) {
+ myListener = new JUnit5TestExecutionListener(System.out);
+ }
+
+ @Override
+ public OutputObjectRegistry getRegistry() {
+ return null;
+ }
+
+ @Override
+ public Object getTestToStart(String[] args, String name) {
+ final TestDiscoveryRequest request = JUnit5TestRunnerUtil.buildRequest(args, new String[1]);
+ Launcher launcher = LauncherFactory.create();
+ myTestPlan = launcher.discover(request);
+ final Set roots = myTestPlan.getRoots();
+
+ return roots.isEmpty() ? null : roots.iterator().next();
+ }
+
+ @Override
+ public List getChildTests(Object description) {
+ return new ArrayList<>(myTestPlan.getChildren((TestIdentifier)description));
+ }
+
+ @Override
+ public String getStartDescription(Object child) {
+ final TestIdentifier testIdentifier = (TestIdentifier)child;
+ final String className = JUnit5TestExecutionListener.getClassName(testIdentifier);
+ final String methodName = JUnit5TestExecutionListener.getMethodName(testIdentifier);
+ if (methodName != null) {
+ return className + "#" + methodName;
+ }
+ return className != null ? className : (testIdentifier).getDisplayName();
+ }
+
+ @Override
+ public String getTestClassName(Object child) {
+ return child.toString();
+ }
+}
diff --git a/plugins/junit5_rt/src/com/intellij/junit5/JUnit5TestExecutionListener.java b/plugins/junit5_rt/src/com/intellij/junit5/JUnit5TestExecutionListener.java
new file mode 100644
index 000000000000..fcc78338351a
--- /dev/null
+++ b/plugins/junit5_rt/src/com/intellij/junit5/JUnit5TestExecutionListener.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.junit5;
+
+import com.intellij.junit4.ExpectedPatterns;
+import com.intellij.rt.execution.junit.ComparisonFailureData;
+import com.intellij.rt.execution.junit.MapSerializerUtil;
+import org.junit.gen5.engine.TestExecutionResult;
+import org.junit.gen5.engine.support.descriptor.JavaSource;
+import org.junit.gen5.launcher.TestExecutionListener;
+import org.junit.gen5.launcher.TestIdentifier;
+import org.junit.gen5.launcher.TestPlan;
+import org.opentest4j.AssertionFailedError;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+
+public class JUnit5TestExecutionListener implements TestExecutionListener {
+ private final PrintStream myPrintStream;
+ private TestPlan myTestPlan;
+ private long myCurrentTestStart;
+ private int myFinishCount = 0;
+ private String myRootName;
+
+ public JUnit5TestExecutionListener() {
+ this(System.out);
+ }
+
+ public JUnit5TestExecutionListener(PrintStream printStream) {
+ myPrintStream = printStream;
+ myPrintStream.println("##teamcity[enteredTheMatrix]");
+ }
+
+ @Override
+ public void testPlanExecutionStarted(TestPlan testPlan) {
+ if (myRootName != null) {
+ int lastPointIdx = myRootName.lastIndexOf('.');
+ String name = myRootName;
+ String comment = null;
+ if (lastPointIdx >= 0) {
+ name = myRootName.substring(lastPointIdx + 1);
+ comment = myRootName.substring(0, lastPointIdx);
+ }
+
+ myPrintStream.println("##teamcity[rootName name = \'" + escapeName(name) +
+ (comment != null ? ("\' comment = \'" + escapeName(comment)) : "") + "\'" +
+ " location = \'java:suite://" + escapeName(myRootName) +
+ "\']");
+ }
+ }
+
+ @Override
+ public void testPlanExecutionFinished(TestPlan testPlan) {
+ myTestPlan = null;
+ }
+
+ @Override
+ public void executionSkipped(TestIdentifier testIdentifier, String reason) {
+ testIgnored(testIdentifier, reason);
+ }
+
+ private void testIgnored(TestIdentifier testIdentifier, String reason) {
+ if (testIdentifier.isTest()) {
+ executionStarted(testIdentifier);
+ Map attrs = new HashMap<>();
+ if (reason != null) {
+ attrs.put("message", reason);
+ }
+ attrs.put("name", testIdentifier.getDisplayName());
+ attrs.put("id", testIdentifier.getUniqueId().toString());
+ myPrintStream.println(MapSerializerUtil.asString(MapSerializerUtil.TEST_IGNORED, attrs));
+
+ testFinished(testIdentifier, System.currentTimeMillis() - myCurrentTestStart);
+ }
+ else {
+ myTestPlan.getDescendants(testIdentifier).forEach(identifier -> testIgnored(identifier, reason));
+ }
+ }
+
+ @Override
+ public void executionStarted(TestIdentifier testIdentifier) {
+ if (testIdentifier.isTest()) {
+ testStarted(testIdentifier);
+ myCurrentTestStart = System.currentTimeMillis();
+ }
+ else {
+ myFinishCount = 0;
+ myPrintStream.println("##teamcity[testSuiteStarted" + idAndName(testIdentifier) + "\']");
+ }
+ }
+
+ private static String idAndName(TestIdentifier testIdentifier) {
+ return idAndName(testIdentifier, testIdentifier.getDisplayName());
+ }
+
+ private static String idAndName(TestIdentifier testIdentifier, String displayName) {
+ return " id=\'" + testIdentifier.getUniqueId().toString() + "\' name=\'" + escapeName(displayName);
+ }
+
+ @Override
+ public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) {
+ final String displayName = testIdentifier.getDisplayName();
+ final TestExecutionResult.Status status = testExecutionResult.getStatus();
+ final Throwable throwableOptional = testExecutionResult.getThrowable().orElse(null);
+ if (testIdentifier.isTest()) {
+ final long duration = System.currentTimeMillis() - myCurrentTestStart;
+ if (status == TestExecutionResult.Status.FAILED) {
+ testFailure(throwableOptional, MapSerializerUtil.TEST_FAILED, testIdentifier, duration);
+ }
+ else if (status == TestExecutionResult.Status.ABORTED) {
+ testFailure(throwableOptional, MapSerializerUtil.TEST_IGNORED, testIdentifier, duration);
+ }
+ testFinished(testIdentifier, duration);
+ myFinishCount++;
+ }
+ else {
+ String messageName = null;
+ if (status == TestExecutionResult.Status.FAILED) {
+ messageName = MapSerializerUtil.TEST_FAILED;
+ }
+ else if (status == TestExecutionResult.Status.ABORTED) {
+ messageName = MapSerializerUtil.TEST_IGNORED;
+ }
+ if (messageName != null && myFinishCount == 0) {
+ for (TestIdentifier childIdentifier : myTestPlan.getChildren(testIdentifier)) {
+ testStarted(childIdentifier);
+ testFailure(throwableOptional, messageName, childIdentifier, 0);
+ testFinished(childIdentifier, 0);
+ }
+ }
+ myPrintStream.println("##teamcity[testSuiteFinished " + idAndName(testIdentifier, displayName) + "\']");
+ }
+ }
+
+ private void testStarted(TestIdentifier testIdentifier) {
+ myPrintStream.println("\n##teamcity[testStarted" + idAndName(testIdentifier) + "\']");
+ }
+
+ private void testFinished(TestIdentifier testIdentifier, long duration) {
+ myPrintStream.println("\n##teamcity[testFinished" + idAndName(testIdentifier) + (duration > 0 ? "\' duration=\'" + Long.toString(duration) : "") + "\']");
+ }
+
+ private void testFailure(Throwable ex, String messageName, TestIdentifier testIdentifier, long duration) {
+ final Map attrs = new HashMap<>();
+ attrs.put("name", testIdentifier.getDisplayName());
+ attrs.put("id", testIdentifier.getUniqueId().toString());
+ if (duration > 0) {
+ attrs.put("duration", Long.toString(duration));
+ }
+ try {
+ if (ex != null) {
+ final StringWriter stringWriter = new StringWriter();
+ final PrintWriter writer = new PrintWriter(stringWriter);
+ ex.printStackTrace(writer);
+ final ComparisonFailureData failureData;
+ if (ex instanceof AssertionFailedError && ((AssertionFailedError)ex).isActualDefined() && ((AssertionFailedError)ex).isExpectedDefined()) {
+ final Object actual = ((AssertionFailedError)ex).getActual();
+ final Object expected = ((AssertionFailedError)ex).getExpected();
+ failureData = new ComparisonFailureData(expected.toString(), actual.toString());
+ }
+ else {
+ failureData = ExpectedPatterns.createExceptionNotification(ex);
+ }
+ ComparisonFailureData.registerSMAttributes(failureData, stringWriter.toString(), ex.getMessage(), attrs, ex);
+ }
+ }
+ finally {
+ myPrintStream.println("\n" + MapSerializerUtil.asString(messageName, attrs));
+ }
+ }
+
+
+ public void sendTree(TestPlan testPlan, String rootName) {
+ myTestPlan = testPlan;
+ myRootName = rootName;
+ for (TestIdentifier root : testPlan.getRoots()) {
+ sendTreeUnderRoot(testPlan, root);
+ }
+ myPrintStream.println("##teamcity[treeEnded]");
+ }
+
+ private void sendTreeUnderRoot(TestPlan testPlan, TestIdentifier root) {
+ final String idAndName = idAndName(root);
+ if (root.isContainer()) {
+ myPrintStream.println("##teamcity[suiteTreeStarted" + idAndName + "\' locationHint=\'java:suite://" + escapeName(getClassName(root)) + "\']");
+ for (TestIdentifier childIdentifier : testPlan.getChildren(root)) {
+ sendTreeUnderRoot(testPlan, childIdentifier);
+ }
+ myPrintStream.println("##teamcity[suiteTreeEnded" + idAndName + "\']");
+ }
+ else if (root.isTest()) {
+ myPrintStream.println("##teamcity[suiteTreeNode " + idAndName + "\' locationHint=\'java:test://" + escapeName(getClassName(root) + "." + getMethodName(root)) + "\']");
+ }
+ }
+
+
+ private static String escapeName(String str) {
+ return MapSerializerUtil.escapeStr(str, MapSerializerUtil.STD_ESCAPER);
+ }
+
+ static String getClassName(TestIdentifier description) {
+ Optional javaSource = getJavaSource(description);
+ return javaSource.map(source -> {
+ final Optional> javaClass = source.getJavaClass();
+ return javaClass.isPresent() ? javaClass.get().getName() : null;
+ }).orElse(null);
+ }
+
+ static String getMethodName(TestIdentifier testIdentifier) {
+ return getJavaSource(testIdentifier).map((source) -> source.getJavaMethodName().orElse(null)).orElse(null);
+ }
+
+ private static Optional getJavaSource(TestIdentifier testIdentifier) {
+ return testIdentifier.getSource().filter(JavaSource.class::isInstance).map(JavaSource.class::cast);
+ }
+
+}
diff --git a/plugins/junit5_rt/src/com/intellij/junit5/JUnit5TestRunnerUtil.java b/plugins/junit5_rt/src/com/intellij/junit5/JUnit5TestRunnerUtil.java
new file mode 100644
index 000000000000..a8d271f648db
--- /dev/null
+++ b/plugins/junit5_rt/src/com/intellij/junit5/JUnit5TestRunnerUtil.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2000-2016 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.junit5;
+
+import org.junit.gen5.engine.discovery.NameBasedSelector;
+import org.junit.gen5.launcher.TestDiscoveryRequest;
+import org.junit.gen5.launcher.main.TestDiscoveryRequestBuilder;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class JUnit5TestRunnerUtil {
+
+ public static TestDiscoveryRequest buildRequest(String[] suiteClassNames, String[] packageNameRef) {
+ if (suiteClassNames.length == 0) {
+ return null;
+ }
+
+ final TestDiscoveryRequestBuilder builder = TestDiscoveryRequestBuilder.request();
+ final List lines = new ArrayList<>();
+
+
+ if (suiteClassNames.length == 1 && suiteClassNames[0].charAt(0) == '@') {
+ // all tests in the package specified
+ try {
+ BufferedReader reader = new BufferedReader(new FileReader(suiteClassNames[0].substring(1)));
+ try {
+ final String packageName = reader.readLine();
+ if (packageName == null) return null;
+
+ //todo category?
+ final String categoryName = reader.readLine();
+ String line;
+
+ while ((line = reader.readLine()) != null) {
+ lines.add(line);
+ }
+ packageNameRef[0] = packageName.length() == 0 ? "" : packageName;
+ }
+ finally {
+ reader.close();
+ }
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+ else {
+ Collections.addAll(lines, suiteClassNames);
+ }
+
+ final List mappedLines = lines.stream().map(line -> line.replaceFirst(",", "#")).collect(Collectors.toList());
+ return builder.select(NameBasedSelector.forNames(mappedLines)).build();
+ }
+
+}
diff --git a/plugins/junit_rt/src/com/intellij/junit4/ExpectedPatterns.java b/plugins/junit_rt/src/com/intellij/junit4/ExpectedPatterns.java
index 364577a2a028..ef879e7fa64f 100644
--- a/plugins/junit_rt/src/com/intellij/junit4/ExpectedPatterns.java
+++ b/plugins/junit_rt/src/com/intellij/junit4/ExpectedPatterns.java
@@ -15,8 +15,9 @@
*/
package com.intellij.junit4;
-import com.intellij.rt.execution.testFrameworks.AbstractExpectedPatterns;
import com.intellij.rt.execution.junit.ComparisonFailureData;
+import com.intellij.rt.execution.testFrameworks.AbstractExpectedPatterns;
+import junit.framework.ComparisonFailure;
import java.util.ArrayList;
import java.util.List;
@@ -35,6 +36,10 @@ public class ExpectedPatterns extends AbstractExpectedPatterns {
".*?\\s*expected: (.*)\\s*but was: (.*)"
};
+ private static final String MESSAGE_LENGTH_FOR_PATTERN_MATCHING = "idea.junit.message.length.threshold";
+ private static final String JUNIT_FRAMEWORK_COMPARISON_NAME = ComparisonFailure.class.getName();
+ private static final String ORG_JUNIT_COMPARISON_NAME = "org.junit.ComparisonFailure";
+
static {
registerPatterns(PATTERN_STRINGS, PATTERNS);
}
@@ -42,4 +47,55 @@ public class ExpectedPatterns extends AbstractExpectedPatterns {
public static ComparisonFailureData createExceptionNotification(String message) {
return createExceptionNotification(message, PATTERNS);
}
+
+ public static ComparisonFailureData createExceptionNotification(Throwable assertion) {
+ if (isComparisonFailure(assertion)) {
+ return ComparisonFailureData.create(assertion);
+ }
+ try {
+ final Throwable cause = assertion.getCause();
+ if (isComparisonFailure(cause)) {
+ return ComparisonFailureData.create(cause);
+ }
+ }
+ catch (Throwable ignore) {
+ }
+
+ final String message = assertion.getMessage();
+ if (message != null && acceptedByThreshold(message.length())) {
+ try {
+ return createExceptionNotification(message);
+ }
+ catch (Throwable ignored) {}
+ }
+ return null;
+ }
+
+ private static boolean isComparisonFailure(Throwable throwable) {
+ if (throwable == null) return false;
+ return isComparisonFailure(throwable.getClass());
+ }
+
+ private static boolean isComparisonFailure(Class aClass) {
+ if (aClass == null) return false;
+ final String throwableClassName = aClass.getName();
+ if (throwableClassName.equals(JUNIT_FRAMEWORK_COMPARISON_NAME) || throwableClassName.equals(ORG_JUNIT_COMPARISON_NAME)) return true;
+ return isComparisonFailure(aClass.getSuperclass());
+ }
+
+
+ private static boolean acceptedByThreshold(int messageLength) {
+ int threshold = 10000;
+ try {
+ final String property = System.getProperty(MESSAGE_LENGTH_FOR_PATTERN_MATCHING);
+ if (property != null) {
+ try {
+ threshold = Integer.parseInt(property);
+ }
+ catch (NumberFormatException ignore) {}
+ }
+ }
+ catch (SecurityException ignored) {}
+ return messageLength < threshold;
+ }
}
diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestListener.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestListener.java
index bcb71b321c60..a8b978d18dde 100644
--- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestListener.java
+++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestListener.java
@@ -22,7 +22,6 @@ package com.intellij.junit4;
import com.intellij.rt.execution.junit.ComparisonFailureData;
import com.intellij.rt.execution.junit.MapSerializerUtil;
-import junit.framework.ComparisonFailure;
import org.junit.Ignore;
import org.junit.runner.Description;
import org.junit.runner.Result;
@@ -36,9 +35,6 @@ import java.lang.annotation.Annotation;
import java.util.*;
public class JUnit4TestListener extends RunListener {
- private static final String MESSAGE_LENGTH_FOR_PATTERN_MATCHING = "idea.junit.message.length.threshold";
- private static final String JUNIT_FRAMEWORK_COMPARISON_NAME = ComparisonFailure.class.getName();
- private static final String ORG_JUNIT_COMPARISON_NAME = "org.junit.ComparisonFailure";
public static final String EMPTY_SUITE_NAME = "junit.framework.TestSuite$1";
public static final String EMPTY_SUITE_WARNING = "warning";
@@ -202,7 +198,7 @@ public class JUnit4TestListener extends RunListener {
if (failure != null) {
final String trace = getTrace(failure);
final Throwable ex = failure.getException();
- final ComparisonFailureData notification = createExceptionNotification(ex);
+ final ComparisonFailureData notification = ExpectedPatterns.createExceptionNotification(ex);
ComparisonFailureData.registerSMAttributes(notification, trace, failure.getMessage(), attrs, ex);
}
}
@@ -283,55 +279,6 @@ public class JUnit4TestListener extends RunListener {
testFinished(description);
}
- private static boolean isComparisonFailure(Throwable throwable) {
- if (throwable == null) return false;
- return isComparisonFailure(throwable.getClass());
- }
-
- private static boolean isComparisonFailure(Class aClass) {
- if (aClass == null) return false;
- final String throwableClassName = aClass.getName();
- if (throwableClassName.equals(JUNIT_FRAMEWORK_COMPARISON_NAME) || throwableClassName.equals(ORG_JUNIT_COMPARISON_NAME)) return true;
- return isComparisonFailure(aClass.getSuperclass());
- }
-
- static ComparisonFailureData createExceptionNotification(Throwable assertion) {
- if (isComparisonFailure(assertion)) {
- return ComparisonFailureData.create(assertion);
- }
- try {
- final Throwable cause = assertion.getCause();
- if (isComparisonFailure(cause)) {
- return ComparisonFailureData.create(cause);
- }
- }
- catch (Throwable ignore) {
- }
- final String message = assertion.getMessage();
- if (message != null && acceptedByThreshold(message.length())) {
- try {
- return ExpectedPatterns.createExceptionNotification(message);
- }
- catch (Throwable ignored) {}
- }
- return null;
- }
-
- private static boolean acceptedByThreshold(int messageLength) {
- int threshold = 10000;
- try {
- final String property = System.getProperty(MESSAGE_LENGTH_FOR_PATTERN_MATCHING);
- if (property != null) {
- try {
- threshold = Integer.parseInt(property);
- }
- catch (NumberFormatException ignore) {}
- }
- }
- catch (SecurityException ignored) {}
- return messageLength < threshold;
- }
-
private void sendTree(Description description, Description parent, List currentParents) {
List pParents = new ArrayList(3);
pParents.addAll(currentParents);
diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java
index b15959fa499a..9f73562b18a4 100644
--- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java
+++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestResultsSender.java
@@ -98,7 +98,7 @@ public class JUnit4TestResultsSender extends RunListener {
private static PacketFactory createExceptionNotification(Throwable assertion) {
if (assertion instanceof KnownException) return ((KnownException)assertion).getPacketFactory();
- final ComparisonFailureData notification = JUnit4TestListener.createExceptionNotification(assertion);
+ final ComparisonFailureData notification = ExpectedPatterns.createExceptionNotification(assertion);
if (notification != null) {
return ComparisonDetailsExtractor.create(assertion, notification.getExpected(), notification.getActual());
}
diff --git a/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitForkedSplitter.java b/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitForkedSplitter.java
index f9fa01fd147e..3cd7532c4924 100644
--- a/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitForkedSplitter.java
+++ b/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitForkedSplitter.java
@@ -43,7 +43,7 @@ public class JUnitForkedSplitter extends ForkedSplitter {
protected Object createRootDescription(String[] args, String configName)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
- myTestRunner = (IdeaTestRunner)JUnitStarter.getAgentClass(Boolean.valueOf((String)myNewArgs.get(0)).booleanValue()).newInstance();
+ myTestRunner = (IdeaTestRunner)JUnitStarter.getAgentClass((String)myNewArgs.get(0)).newInstance();
myTestRunner.setStreams(myOut, myErr, 0);
return myTestRunner.getTestToStart(args, configName);
}
diff --git a/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitForkedStarter.java b/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitForkedStarter.java
index c7b2c7ebecd9..6aec02979bc1 100644
--- a/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitForkedStarter.java
+++ b/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitForkedStarter.java
@@ -31,12 +31,12 @@ public class JUnitForkedStarter extends ChildVMStarter {
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
final int lastIdx = Integer.parseInt(args[1]);
final String[] childTestDescription = {args[2]};
- final boolean isJUnit4 = args[3].equalsIgnoreCase("true");
+ final String argentName = args[3];
final ArrayList listeners = new ArrayList();
for (int i = 4, argsLength = args.length; i < argsLength; i++) {
listeners.add(args[i]);
}
- IdeaTestRunner testRunner = (IdeaTestRunner)JUnitStarter.getAgentClass(isJUnit4).newInstance();
+ IdeaTestRunner testRunner = (IdeaTestRunner)JUnitStarter.getAgentClass(argentName).newInstance();
//noinspection IOResourceOpenedButNotSafelyClosed
testRunner.setStreams(new SegmentedOutputStream(out, true), new SegmentedOutputStream(err, true), lastIdx);
System.exit(testRunner.startRunnerWithArgs(childTestDescription, listeners, null, 1, false));
diff --git a/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitStarter.java b/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitStarter.java
index b852a9b281b7..7e6dbbad721e 100644
--- a/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitStarter.java
+++ b/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitStarter.java
@@ -32,8 +32,15 @@ import java.util.Vector;
public class JUnitStarter {
public static final int VERSION = 5;
public static final String IDE_VERSION = "-ideVersion";
+
public static final String JUNIT3_PARAMETER = "-junit3";
+ public static final String JUNIT4_PARAMETER = "-junit4";
+ public static final String JUNIT5_PARAMETER = "-junit5";
+
private static final String SOCKET = "-socket";
+ public static final String JUNIT3_RUNNER_NAME = "com.intellij.junit3.JUnit3IdeaTestRunner";
+ public static final String JUNIT4_RUNNER_NAME = "com.intellij.junit4.JUnit4IdeaTestRunner";
+ public static final String JUNIT5_RUNNER_NAME = "com.intellij.junit5.JUnit5IdeaTestRunner";
private static String ourForkMode;
private static String ourCommandFileName;
private static String ourWorkingDirs;
@@ -60,9 +67,9 @@ public class JUnitStarter {
final ArrayList listeners = new ArrayList();
final String[] name = new String[1];
- boolean isJUnit4 = processParameters(argList, listeners, name);
+ String agentName = processParameters(argList, listeners, name);
- if (!canWorkWithJUnitVersion(System.err, isJUnit4)) {
+ if (!canWorkWithJUnitVersion(System.err, agentName)) {
System.exit(-3);
}
if (!checkVersion(args, System.err)) {
@@ -71,12 +78,12 @@ public class JUnitStarter {
String[] array = new String[argList.size()];
argList.copyInto(array);
- int exitCode = prepareStreamsAndStart(array, isJUnit4, listeners, name[0]);
+ int exitCode = prepareStreamsAndStart(array, agentName, listeners, name[0]);
System.exit(exitCode);
}
- private static boolean processParameters(Vector args, final List listeners, String[] params) {
- boolean isJunit4 = true;
+ private static String processParameters(Vector args, final List listeners, String[] params) {
+ String agentName = JUNIT4_RUNNER_NAME;
Vector result = new Vector(args.size());
for (int i = 0; i < args.size(); i++) {
String arg = (String)args.get(i);
@@ -84,7 +91,13 @@ public class JUnitStarter {
//ignore
}
else if (arg.equals(JUNIT3_PARAMETER)){
- isJunit4 = false;
+ agentName = JUNIT3_RUNNER_NAME;
+ }
+ else if (arg.equals(JUNIT4_PARAMETER)) {
+ agentName = JUNIT4_RUNNER_NAME;
+ }
+ else if (arg.equals(JUNIT5_PARAMETER)) {
+ agentName = JUNIT5_RUNNER_NAME;
}
else {
if (arg.startsWith("@name")) {
@@ -145,26 +158,22 @@ public class JUnitStarter {
String arg = (String)result.get(i);
args.addElement(arg);
}
- if (!isJunit4) {
+ if (JUNIT3_RUNNER_NAME.equals(agentName)) {
try {
Class.forName("org.junit.runner.Computer");
+ agentName = JUNIT4_RUNNER_NAME;
}
catch (ClassNotFoundException e) {
- return false;
+ return JUNIT3_RUNNER_NAME;
}
}
+
try {
final String forceJUnit3 = System.getProperty("idea.force.junit3");
- if (forceJUnit3 != null && Boolean.valueOf(forceJUnit3).booleanValue()) return false;
+ if (forceJUnit3 != null && Boolean.valueOf(forceJUnit3).booleanValue()) return JUNIT3_RUNNER_NAME;
}
catch (SecurityException ignored) {}
- try {
- Class.forName("org.junit.Test");
- return true;
- }
- catch (ClassNotFoundException e) {
- return false;
- }
+ return agentName;
}
public static boolean checkVersion(String[] args, PrintStream printStream) {
@@ -183,9 +192,9 @@ public class JUnitStarter {
return false;
}
- private static boolean canWorkWithJUnitVersion(PrintStream printStream, boolean isJUnit4) {
+ private static boolean canWorkWithJUnitVersion(PrintStream printStream, String agentName) {
try {
- junitVersionChecks(isJUnit4);
+ junitVersionChecks(agentName);
} catch (Throwable e) {
printStream.println("!!! JUnit version 3.8 or later expected:");
printStream.println();
@@ -198,21 +207,21 @@ public class JUnitStarter {
return true;
}
- private static void junitVersionChecks(boolean isJUnit4) throws ClassNotFoundException {
+ private static void junitVersionChecks(String agentName) throws ClassNotFoundException {
Class.forName("junit.framework.ComparisonFailure");
- getAgentClass(isJUnit4);
+ getAgentClass(agentName);
//noinspection UnnecessaryFullyQualifiedName
new junit.textui.TestRunner().setPrinter(new com.intellij.junit3.JUnit3IdeaTestRunner.MockResultPrinter());
}
private static int prepareStreamsAndStart(String[] args,
- final boolean isJUnit4,
+ final String agentName,
ArrayList listeners,
String name) {
PrintStream oldOut = System.out;
PrintStream oldErr = System.err;
try {
- IdeaTestRunner testRunner = (IdeaTestRunner)getAgentClass(isJUnit4).newInstance();
+ IdeaTestRunner testRunner = (IdeaTestRunner)getAgentClass(agentName).newInstance();
Object out = SM_RUNNER ? System.out : (Object)new SegmentedOutputStream(System.out);
Object err = SM_RUNNER ? System.err : (Object)new SegmentedOutputStream(System.err);
if (!SM_RUNNER) {
@@ -222,7 +231,7 @@ public class JUnitStarter {
if (ourCommandFileName != null) {
if (!"none".equals(ourForkMode) || ourWorkingDirs != null && new File(ourWorkingDirs).length() > 0) {
final List newArgs = new ArrayList();
- newArgs.add(String.valueOf(isJUnit4));
+ newArgs.add(agentName);
newArgs.addAll(listeners);
PrintStream printOutputStream = SM_RUNNER ? ((PrintStream)out) : ((SegmentedOutputStream)out).getPrintStream();
PrintStream printErrStream = SM_RUNNER ? ((PrintStream)err) : ((SegmentedOutputStream)err).getPrintStream();
@@ -243,11 +252,8 @@ public class JUnitStarter {
}
}
- static Class getAgentClass(boolean isJUnit4) throws ClassNotFoundException {
- return isJUnit4
- ? Class.forName("com.intellij.junit4.JUnit4IdeaTestRunner")
- : Class.forName("com.intellij.junit3.JUnit3IdeaTestRunner");
-
+ static Class getAgentClass(String agentName) throws ClassNotFoundException {
+ return Class.forName(agentName);
}
public static void printClassesList(List classNames, String packageName, String category, File tempFile) throws IOException {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/javadoc/MojoClassAnnotationTagProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/javadoc/MojoClassAnnotationTagProvider.java
index 545fb6e99788..f846d7af7ed3 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/javadoc/MojoClassAnnotationTagProvider.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/javadoc/MojoClassAnnotationTagProvider.java
@@ -1,20 +1,5 @@
/*
- * Copyright 2000-2015 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jetbrains.idea.maven.javadoc;/*
- * Copyright 2000-2015 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -28,6 +13,7 @@ package org.jetbrains.idea.maven.javadoc;/*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package org.jetbrains.idea.maven.javadoc;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
@@ -44,7 +30,6 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
public class MojoClassAnnotationTagProvider implements CustomJavadocTagProvider {
-
private static final String[] ANNOTATION_NAMES = {
"goal",
"requiresDependencyResolution",
@@ -66,12 +51,11 @@ public class MojoClassAnnotationTagProvider implements CustomJavadocTagProvider
}
});
}
-
}
class MojoAnnotationInfo implements JavadocTagInfo {
-
private static final String BASE_CLASS = "org.apache.maven.plugin.Mojo";
+
private final String myName;
public MojoAnnotationInfo(@NotNull String name) {
@@ -97,11 +81,6 @@ class MojoAnnotationInfo implements JavadocTagInfo {
return false;
}
- @Override
- public Object[] getPossibleValues(PsiElement context, PsiElement place, String prefix) {
- return null;
- }
-
@Nullable
@Override
public String checkTagValue(PsiDocTagValue value) {
@@ -113,7 +92,4 @@ class MojoAnnotationInfo implements JavadocTagInfo {
public PsiReference getReference(PsiDocTagValue value) {
return null;
}
-}
-
-
-
+}
\ No newline at end of file
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
index 75e4d6c4f1fc..2c1eb879f09a 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
@@ -40,8 +40,10 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.wm.impl.status.StatusBarUtil;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.NotNullFunction;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
+import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -308,7 +310,7 @@ public class SvnUtil {
}
@NotNull
- public static Map, Set> splitChangesIntoWc(@NotNull SvnVcs vcs, @NotNull List changes) {
+ public static MultiMap, Change> splitChangesIntoWc(@NotNull SvnVcs vcs, @NotNull List changes) {
return splitIntoRepositoriesMap(vcs, changes, new Convertor() {
@Override
public FilePath convert(@NotNull Change change) {
@@ -318,12 +320,13 @@ public class SvnUtil {
}
@NotNull
- public static Map, Set> splitIntoRepositoriesMap(@NotNull final SvnVcs vcs,
+ public static MultiMap, T> splitIntoRepositoriesMap(@NotNull final SvnVcs vcs,
@NotNull List items,
@NotNull final Convertor converter) {
- return ContainerUtil.classify(items.iterator(), new Convertor>() {
+ return ContainerUtil.groupBy(items, new NotNullFunction>() {
+ @NotNull
@Override
- public Pair convert(@NotNull T item) {
+ public Pair fun(@NotNull T item) {
RootUrlInfo path = vcs.getSvnFileUrlMapping().getWcRootForFilePath(converter.convert(item).getIOFile());
return path == null ? UNKNOWN_REPOSITORY_AND_FORMAT : Pair.create(path.getRepositoryUrlUrl(), path.getFormat());
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java
index 588e218c0167..63bb448b4a44 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnCheckinEnvironment.java
@@ -40,6 +40,7 @@ import com.intellij.util.NullableFunction;
import com.intellij.util.PairConsumer;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
+import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.*;
@@ -84,8 +85,9 @@ public class SvnCheckinEnvironment implements CheckinEnvironment {
private void doCommit(@NotNull List committables, String comment, List exception, final Set feedback) {
//noinspection unchecked
- Map, Set> map = SvnUtil.splitIntoRepositoriesMap(mySvnVcs, committables, Convertor.SELF);
- for (Map.Entry, Set> entry : map.entrySet()) {
+ MultiMap, FilePath> map = SvnUtil.splitIntoRepositoriesMap(mySvnVcs, committables, Convertor.SELF);
+
+ for (Map.Entry, Collection> entry : map.entrySet()) {
try {
doCommitOneRepo(entry.getValue(), comment, exception, feedback, entry.getKey().getSecond());
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java
index ce9ce271ffa6..272e90bc1ae6 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java
@@ -17,6 +17,7 @@ package org.jetbrains.idea.svn.rollback;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Couple;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
@@ -29,12 +30,14 @@ import org.jetbrains.idea.svn.*;
import org.jetbrains.idea.svn.api.Depth;
import org.jetbrains.idea.svn.info.Info;
import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.wc.SVNRevision;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
/**
* @author yole
@@ -56,9 +59,9 @@ public class SvnRollbackEnvironment extends DefaultRollbackEnvironment {
@NotNull RollbackProgressListener listener) {
listener.indeterminate();
- for (Collection collection : SvnUtil.splitChangesIntoWc(mySvnVcs, changes).values()) {
+ for (Map.Entry, Collection> entry : SvnUtil.splitChangesIntoWc(mySvnVcs, changes).entrySet()) {
// to be more sure about nested changes, being or being not reverted
- List sortedChanges = ContainerUtil.sorted(collection, ChangesAfterPathComparator.getInstance());
+ List sortedChanges = ContainerUtil.sorted(entry.getValue(), ChangesAfterPathComparator.getInstance());
rollbackGroupForWc(sortedChanges, exceptions, listener);
}
diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java
index 45f033e937fd..1dc14d36bb51 100644
--- a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java
+++ b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java
@@ -102,7 +102,7 @@ public class StudyProjectComponent implements ProjectComponent {
studyToolWindow.show(null);
}
if (progressToolWindow != null) {
- StudyUtils.updateToolWindows(myProject);
+ StudyUtils.initToolWindows(myProject);
progressToolWindow.show(null);
}
}
diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyUtils.java b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyUtils.java
index a1ed979c5309..0f68f81654ef 100644
--- a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyUtils.java
+++ b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyUtils.java
@@ -18,6 +18,7 @@ import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.impl.DocumentImpl;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
@@ -26,26 +27,30 @@ import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.ui.JBColor;
import com.intellij.ui.awt.RelativePoint;
+import com.intellij.ui.content.Content;
import com.intellij.util.ui.UIUtil;
import com.jetbrains.edu.EduAnswerPlaceholderDeleteHandler;
import com.jetbrains.edu.EduAnswerPlaceholderPainter;
import com.jetbrains.edu.EduNames;
import com.jetbrains.edu.EduUtils;
import com.jetbrains.edu.courseFormat.*;
-import com.jetbrains.edu.learning.editor.StudyEditor;
import com.jetbrains.edu.learning.checker.StudyExecutor;
import com.jetbrains.edu.learning.checker.StudyTestRunner;
+import com.jetbrains.edu.learning.editor.StudyEditor;
import com.jetbrains.edu.learning.ui.StudyProgressToolWindowFactory;
+import com.jetbrains.edu.learning.ui.StudyToolWindow;
import com.jetbrains.edu.learning.ui.StudyToolWindowFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.util.Collection;
@@ -56,6 +61,7 @@ public class StudyUtils {
}
private static final Logger LOG = Logger.getInstance(StudyUtils.class.getName());
+ private static final String EMPTY_TASK_TEXT = "Please, open any task to see task description";
public static void closeSilently(@Nullable final Closeable stream) {
if (stream != null) {
@@ -122,15 +128,42 @@ public class StudyUtils {
}
public static void updateToolWindows(@NotNull final Project project) {
+ final ToolWindowManager windowManager = ToolWindowManager.getInstance(project);
+ StudyToolWindowFactory factory = new StudyToolWindowFactory();
+ factory.update(project);
+
+ createProgressToolWindowContent(project, windowManager);
+ }
+
+ public static void initToolWindows(@NotNull final Project project) {
final ToolWindowManager windowManager = ToolWindowManager.getInstance(project);
windowManager.getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW).getContentManager().removeAllContents(false);
StudyToolWindowFactory factory = new StudyToolWindowFactory();
factory.createToolWindowContent(project, windowManager.getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW));
+ createProgressToolWindowContent(project, windowManager);
+ }
+
+ private static void createProgressToolWindowContent(@NotNull Project project, ToolWindowManager windowManager) {
windowManager.getToolWindow(StudyProgressToolWindowFactory.ID).getContentManager().removeAllContents(false);
StudyProgressToolWindowFactory windowFactory = new StudyProgressToolWindowFactory();
windowFactory.createToolWindowContent(project, windowManager.getToolWindow(StudyProgressToolWindowFactory.ID));
}
+
+ @Nullable
+ public static StudyToolWindow getStudyToolWindow(@NotNull final Project project) {
+ ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW);
+ if (toolWindow != null) {
+ Content[] contents = toolWindow.getContentManager().getContents();
+ for (Content content: contents) {
+ JComponent component = content.getComponent();
+ if (component != null && component instanceof StudyToolWindow) {
+ return (StudyToolWindow)component;
+ }
+ }
+ }
+ return null;
+ }
public static void deleteFile(@NotNull final VirtualFile file) {
try {
@@ -427,4 +460,23 @@ public class StudyUtils {
}
return null;
}
+
+ public static String getTaskText(@NotNull final Project project) {
+ VirtualFile[] files = FileEditorManager.getInstance(project).getSelectedFiles();
+ TaskFile taskFile = null;
+ for (VirtualFile file : files) {
+ taskFile = getTaskFile(project, file);
+ if (taskFile != null) {
+ break;
+ }
+ }
+ if (taskFile == null) {
+ return EMPTY_TASK_TEXT;
+ }
+ final Task task = taskFile.getTask();
+ if (task != null) {
+ return getTaskTextFromTask(task, task.getTaskDir(project));
+ }
+ return null;
+ }
}
diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindow.java b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindow.java
index c03a621624e7..e77592c7e355 100644
--- a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindow.java
+++ b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindow.java
@@ -21,17 +21,13 @@ import com.intellij.openapi.actionSystem.ActionToolbar;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.SimpleToolWindowPanel;
-import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.JBCardLayout;
import com.intellij.ui.OnePixelSplitter;
import com.intellij.util.ui.JBUI;
import com.jetbrains.edu.courseFormat.Course;
-import com.jetbrains.edu.courseFormat.Task;
-import com.jetbrains.edu.courseFormat.TaskFile;
import com.jetbrains.edu.learning.StudyTaskManager;
import com.jetbrains.edu.learning.StudyToolWindowConfigurator;
import com.jetbrains.edu.learning.StudyUtils;
@@ -43,7 +39,6 @@ import java.util.Map;
public abstract class StudyToolWindow extends SimpleToolWindowPanel implements DataProvider, Disposable {
private static final Logger LOG = Logger.getInstance(StudyToolWindow.class);
- private static final String EMPTY_TASK_TEXT = "Please, open any task to see task description";
private static final String TASK_INFO_ID = "taskInfo";
private final JBCardLayout myCardLayout;
private final JPanel myContentPanel;
@@ -57,7 +52,7 @@ public abstract class StudyToolWindow extends SimpleToolWindowPanel implements D
}
public void init(Project project) {
- String taskText = getTaskText(project);
+ String taskText = StudyUtils.getTaskText(project);
if (taskText == null) return;
JPanel toolbarPanel = createToolbarPanel(project);
@@ -117,27 +112,8 @@ public abstract class StudyToolWindow extends SimpleToolWindowPanel implements D
public JPanel getContentPanel() {
return myContentPanel;
}
-
-
- private static String getTaskText(@NotNull final Project project) {
- VirtualFile[] files = FileEditorManager.getInstance(project).getSelectedFiles();
- TaskFile taskFile = null;
- for (VirtualFile file : files) {
- taskFile = StudyUtils.getTaskFile(project, file);
- if (taskFile != null) {
- break;
- }
- }
- if (taskFile == null) {
- return EMPTY_TASK_TEXT;
- }
- final Task task = taskFile.getTask();
- if (task != null) {
- return StudyUtils.getTaskTextFromTask(task, task.getTaskDir(project));
- }
- return null;
- }
-
+
+
public abstract JComponent createTaskInfoPanel(String taskText, Project project);
private static JPanel createToolbarPanel(@NotNull final Project project) {
diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindowFactory.java b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindowFactory.java
index c0ededad3dc6..2394f32158cb 100644
--- a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindowFactory.java
+++ b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindowFactory.java
@@ -10,6 +10,7 @@ import com.intellij.ui.content.ContentManager;
import com.jetbrains.edu.courseFormat.Course;
import com.jetbrains.edu.learning.StudyProjectComponent;
import com.jetbrains.edu.learning.StudyTaskManager;
+import com.jetbrains.edu.learning.StudyUtils;
import icons.InteractiveLearningIcons;
import org.jetbrains.annotations.NotNull;
@@ -39,4 +40,11 @@ public class StudyToolWindowFactory implements ToolWindowFactory, DumbAware {
}
}
+ public void update(Project project) {
+ final StudyToolWindow studyToolWindow = StudyUtils.getStudyToolWindow(project);
+ if (studyToolWindow != null) {
+ String taskText = StudyUtils.getTaskText(project);
+ studyToolWindow.setTaskText(taskText);
+ }
+ }
}
diff --git a/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py b/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py
index 68f83cf73582..69d68d84ce85 100644
--- a/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py
+++ b/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py
@@ -1,7 +1,7 @@
from _pydev_bundle.pydev_imports import xmlrpclib, _queue, Exec
import sys
from _pydevd_bundle.pydevd_constants import IS_JYTHON
-from _pydev_imps import _pydev_thread as thread
+from _pydev_imps._pydev_saved_modules import thread
from _pydevd_bundle import pydevd_xml
from _pydevd_bundle import pydevd_vars
from _pydevd_bundle.pydevd_utils import * # @UnusedWildImport
@@ -489,7 +489,7 @@ class BaseInterpreterInterface:
try:
# Try to import the packages needed to attach the debugger
import pydevd
- from _pydev_imps import _pydev_threading as threading
+ from _pydev_imps._pydev_saved_modules import threading
except:
# This happens on Jython embedded in host eclipse
diff --git a/python/helpers/pydev/_pydev_bundle/pydev_imports.py b/python/helpers/pydev/_pydev_bundle/pydev_imports.py
index b6c582dc847c..4adc6b2d3183 100644
--- a/python/helpers/pydev/_pydev_bundle/pydev_imports.py
+++ b/python/helpers/pydev/_pydev_bundle/pydev_imports.py
@@ -4,7 +4,7 @@ from _pydevd_bundle.pydevd_constants import USE_LIB_COPY, izip
try:
try:
if USE_LIB_COPY:
- from _pydev_imps import _pydev_xmlrpclib as xmlrpclib
+ from _pydev_imps._pydev_saved_modules import xmlrpclib
else:
import xmlrpclib
except ImportError:
@@ -16,7 +16,8 @@ except ImportError:
try:
try:
if USE_LIB_COPY:
- from _pydev_imps._pydev_SimpleXMLRPCServer import SimpleXMLRPCServer
+ from _pydev_imps._pydev_saved_modules import _pydev_SimpleXMLRPCServer
+ from _pydev_SimpleXMLRPCServer import SimpleXMLRPCServer
else:
from SimpleXMLRPCServer import SimpleXMLRPCServer
except ImportError:
@@ -40,7 +41,7 @@ except NameError:
try:
if USE_LIB_COPY:
- from _pydev_imps import _pydev_Queue as _queue
+ from _pydev_imps._pydev_saved_modules import _queue
else:
import Queue as _queue
except:
diff --git a/python/helpers/pydev/_pydev_bundle/pydev_is_thread_alive.py b/python/helpers/pydev/_pydev_bundle/pydev_is_thread_alive.py
index 67be6facb4bc..d1a63d7541e2 100644
--- a/python/helpers/pydev/_pydev_bundle/pydev_is_thread_alive.py
+++ b/python/helpers/pydev/_pydev_bundle/pydev_is_thread_alive.py
@@ -1,4 +1,4 @@
-from _pydev_imps import _pydev_threading as threading
+from _pydev_imps._pydev_saved_modules import threading
# Hack for https://sw-brainwy.rhcloud.com/tracker/PyDev/363 (i.e.: calling isAlive() can throw AssertionError under some circumstances)
# It is required to debug threads started by start_new_thread in Python 3.4
diff --git a/python/helpers/pydev/_pydev_bundle/pydev_localhost.py b/python/helpers/pydev/_pydev_bundle/pydev_localhost.py
index 9d52635a8b35..3772db295471 100644
--- a/python/helpers/pydev/_pydev_bundle/pydev_localhost.py
+++ b/python/helpers/pydev/_pydev_bundle/pydev_localhost.py
@@ -1,5 +1,5 @@
from _pydevd_bundle import pydevd_constants
-from _pydev_imps import _pydev_socket as socket
+from _pydev_imps._pydev_saved_modules import socket
_cache = None
def get_localhost():
diff --git a/python/helpers/pydev/_pydev_bundle/pydev_log.py b/python/helpers/pydev/_pydev_bundle/pydev_log.py
index 680907e75a66..ae8f50455294 100644
--- a/python/helpers/pydev/_pydev_bundle/pydev_log.py
+++ b/python/helpers/pydev/_pydev_bundle/pydev_log.py
@@ -1,7 +1,7 @@
import sys
from _pydevd_bundle.pydevd_constants import DebugInfoHolder, dict_contains
-from _pydev_imps import _pydev_threading
-currentThread = _pydev_threading.currentThread
+from _pydev_imps._pydev_saved_modules import threading
+currentThread = threading.currentThread
import traceback
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_BaseHTTPServer.py b/python/helpers/pydev/_pydev_imps/_pydev_BaseHTTPServer.py
index 5f9dbfd63f4f..f8dd911127f6 100644
--- a/python/helpers/pydev/_pydev_imps/_pydev_BaseHTTPServer.py
+++ b/python/helpers/pydev/_pydev_imps/_pydev_BaseHTTPServer.py
@@ -71,8 +71,8 @@ __version__ = "0.3"
__all__ = ["HTTPServer", "BaseHTTPRequestHandler"]
import sys
-from _pydev_imps import _pydev_time as time
-from _pydev_imps import _pydev_socket as socket
+from _pydev_imps._pydev_saved_modules import time
+from _pydev_imps._pydev_saved_modules import socket
from warnings import filterwarnings, catch_warnings
with catch_warnings():
if sys.py3kwarning:
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_Queue.py b/python/helpers/pydev/_pydev_imps/_pydev_Queue.py
deleted file mode 100644
index 89ae775928be..000000000000
--- a/python/helpers/pydev/_pydev_imps/_pydev_Queue.py
+++ /dev/null
@@ -1,245 +0,0 @@
-"""A multi-producer, multi-consumer queue."""
-
-from _pydev_imps._pydev_time import time as _time
-from _pydev_imps import _pydev_thread
-try:
- from _pydev_imps import _pydev_threading as _threading
-except ImportError:
- import dummy_threading as _threading
-from collections import deque
-import heapq
-
-__all__ = ['Empty', 'Full', 'Queue', 'PriorityQueue', 'LifoQueue']
-
-class Empty(Exception):
- "Exception raised by Queue.get(block=0)/get_nowait()."
- pass
-
-class Full(Exception):
- "Exception raised by Queue.put(block=0)/put_nowait()."
- pass
-
-class Queue:
- """Create a queue object with a given maximum size.
-
- If maxsize is <= 0, the queue size is infinite.
- """
- def __init__(self, maxsize=0):
- self.maxsize = maxsize
- self._init(maxsize)
- # mutex must be held whenever the queue is mutating. All methods
- # that acquire mutex must release it before returning. mutex
- # is shared between the three conditions, so acquiring and
- # releasing the conditions also acquires and releases mutex.
- self.mutex = _pydev_thread.allocate_lock()
- # Notify not_empty whenever an item is added to the queue; a
- # thread waiting to get is notified then.
- self.not_empty = _threading.Condition(self.mutex) # @UndefinedVariable
- # Notify not_full whenever an item is removed from the queue;
- # a thread waiting to put is notified then.
- self.not_full = _threading.Condition(self.mutex) # @UndefinedVariable
- # Notify all_tasks_done whenever the number of unfinished tasks
- # drops to zero; thread waiting to join() is notified to resume
- self.all_tasks_done = _threading.Condition(self.mutex) # @UndefinedVariable
- self.unfinished_tasks = 0
-
- def task_done(self):
- """Indicate that a formerly enqueued task is complete.
-
- Used by Queue consumer threads. For each get() used to fetch a task,
- a subsequent call to task_done() tells the queue that the processing
- on the task is complete.
-
- If a join() is currently blocking, it will resume when all items
- have been processed (meaning that a task_done() call was received
- for every item that had been put() into the queue).
-
- Raises a ValueError if called more times than there were items
- placed in the queue.
- """
- self.all_tasks_done.acquire()
- try:
- unfinished = self.unfinished_tasks - 1
- if unfinished <= 0:
- if unfinished < 0:
- raise ValueError('task_done() called too many times')
- self.all_tasks_done.notify_all()
- self.unfinished_tasks = unfinished
- finally:
- self.all_tasks_done.release()
-
- def join(self):
- """Blocks until all items in the Queue have been gotten and processed.
-
- The count of unfinished tasks goes up whenever an item is added to the
- queue. The count goes down whenever a consumer thread calls task_done()
- to indicate the item was retrieved and all work on it is complete.
-
- When the count of unfinished tasks drops to zero, join() unblocks.
- """
- self.all_tasks_done.acquire()
- try:
- while self.unfinished_tasks:
- self.all_tasks_done.wait()
- finally:
- self.all_tasks_done.release()
-
- def qsize(self):
- """Return the approximate size of the queue (not reliable!)."""
- self.mutex.acquire()
- n = self._qsize()
- self.mutex.release()
- return n
-
- def empty(self):
- """Return True if the queue is empty, False otherwise (not reliable!)."""
- self.mutex.acquire()
- n = not self._qsize()
- self.mutex.release()
- return n
-
- def full(self):
- """Return True if the queue is full, False otherwise (not reliable!)."""
- self.mutex.acquire()
- n = 0 < self.maxsize == self._qsize()
- self.mutex.release()
- return n
-
- def put(self, item, block=True, timeout=None):
- """Put an item into the queue.
-
- If optional args 'block' is true and 'timeout' is None (the default),
- block if necessary until a free slot is available. If 'timeout' is
- a positive number, it blocks at most 'timeout' seconds and raises
- the Full exception if no free slot was available within that time.
- Otherwise ('block' is false), put an item on the queue if a free slot
- is immediately available, else raise the Full exception ('timeout'
- is ignored in that case).
- """
- self.not_full.acquire()
- try:
- if self.maxsize > 0:
- if not block:
- if self._qsize() == self.maxsize:
- raise Full
- elif timeout is None:
- while self._qsize() == self.maxsize:
- self.not_full.wait()
- elif timeout < 0:
- raise ValueError("'timeout' must be a positive number")
- else:
- endtime = _time() + timeout
- while self._qsize() == self.maxsize:
- remaining = endtime - _time()
- if remaining <= 0.0:
- raise Full
- self.not_full.wait(remaining)
- self._put(item)
- self.unfinished_tasks += 1
- self.not_empty.notify()
- finally:
- self.not_full.release()
-
- def put_nowait(self, item):
- """Put an item into the queue without blocking.
-
- Only enqueue the item if a free slot is immediately available.
- Otherwise raise the Full exception.
- """
- return self.put(item, False)
-
- def get(self, block=True, timeout=None):
- """Remove and return an item from the queue.
-
- If optional args 'block' is true and 'timeout' is None (the default),
- block if necessary until an item is available. If 'timeout' is
- a positive number, it blocks at most 'timeout' seconds and raises
- the Empty exception if no item was available within that time.
- Otherwise ('block' is false), return an item if one is immediately
- available, else raise the Empty exception ('timeout' is ignored
- in that case).
- """
- self.not_empty.acquire()
- try:
- if not block:
- if not self._qsize():
- raise Empty
- elif timeout is None:
- while not self._qsize():
- self.not_empty.wait()
- elif timeout < 0:
- raise ValueError("'timeout' must be a positive number")
- else:
- endtime = _time() + timeout
- while not self._qsize():
- remaining = endtime - _time()
- if remaining <= 0.0:
- raise Empty
- self.not_empty.wait(remaining)
- item = self._get()
- self.not_full.notify()
- return item
- finally:
- self.not_empty.release()
-
- def get_nowait(self):
- """Remove and return an item from the queue without blocking.
-
- Only get an item if one is immediately available. Otherwise
- raise the Empty exception.
- """
- return self.get(False)
-
- # Override these methods to implement other queue organizations
- # (e.g. stack or priority queue).
- # These will only be called with appropriate locks held
-
- # Initialize the queue representation
- def _init(self, maxsize):
- self.queue = deque()
-
- def _qsize(self, len=len):
- return len(self.queue)
-
- # Put a new item in the queue
- def _put(self, item):
- self.queue.append(item)
-
- # Get an item from the queue
- def _get(self):
- return self.queue.popleft()
-
-
-class PriorityQueue(Queue):
- '''Variant of Queue that retrieves open entries in priority order (lowest first).
-
- Entries are typically tuples of the form: (priority number, data).
- '''
-
- def _init(self, maxsize):
- self.queue = []
-
- def _qsize(self, len=len):
- return len(self.queue)
-
- def _put(self, item, heappush=heapq.heappush):
- heappush(self.queue, item)
-
- def _get(self, heappop=heapq.heappop):
- return heappop(self.queue)
-
-
-class LifoQueue(Queue):
- '''Variant of Queue that retrieves most recently added entries first.'''
-
- def _init(self, maxsize):
- self.queue = []
-
- def _qsize(self, len=len):
- return len(self.queue)
-
- def _put(self, item):
- self.queue.append(item)
-
- def _get(self):
- return self.queue.pop()
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_SocketServer.py b/python/helpers/pydev/_pydev_imps/_pydev_SocketServer.py
index 991a1678b05a..7af2777ac7ea 100644
--- a/python/helpers/pydev/_pydev_imps/_pydev_SocketServer.py
+++ b/python/helpers/pydev/_pydev_imps/_pydev_SocketServer.py
@@ -129,12 +129,12 @@ BaseServer:
__version__ = "0.4"
-from _pydev_imps import _pydev_socket as socket
-from _pydev_imps import _pydev_select as select
+from _pydev_imps._pydev_saved_modules import socket
+from _pydev_imps._pydev_saved_modules import select
import sys
import os
try:
- from _pydev_imps import _pydev_threading as threading
+ from _pydev_imps._pydev_saved_modules import threading
except ImportError:
import dummy_threading as threading
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_saved_modules.py b/python/helpers/pydev/_pydev_imps/_pydev_saved_modules.py
new file mode 100644
index 000000000000..35dc0a6a9768
--- /dev/null
+++ b/python/helpers/pydev/_pydev_imps/_pydev_saved_modules.py
@@ -0,0 +1,32 @@
+import threading
+
+try:
+ import thread
+except:
+ import _thread as thread
+
+import time
+
+import socket
+
+import select
+
+try:
+ import Queue as _queue
+except:
+ import queue as _queue
+
+try:
+ import xmlrpclib
+except:
+ import xmlrpc.client as xmlrpclib
+
+try:
+ import SimpleXMLRPCServer as _pydev_SimpleXMLRPCServer
+except:
+ import xmlrpc.server as _pydev_SimpleXMLRPCServer
+
+try:
+ import BaseHTTPServer
+except:
+ import http.server as BaseHTTPServer
\ No newline at end of file
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_select.py b/python/helpers/pydev/_pydev_imps/_pydev_select.py
deleted file mode 100644
index d582beb80b72..000000000000
--- a/python/helpers/pydev/_pydev_imps/_pydev_select.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from select import *
-
-try:
- from gevent import monkey # @UnresolvedImport
- saved = monkey.saved['select']
- for key, val in saved.items():
- globals()[key] = val
-except:
- pass
\ No newline at end of file
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_socket.py b/python/helpers/pydev/_pydev_imps/_pydev_socket.py
deleted file mode 100644
index 84e29021c4a1..000000000000
--- a/python/helpers/pydev/_pydev_imps/_pydev_socket.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from socket import *
-
-try:
- from gevent import monkey # @UnresolvedImport
- saved = monkey.saved['socket']
- for key, val in saved.items():
- globals()[key] = val
-except:
- pass
\ No newline at end of file
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_thread.py b/python/helpers/pydev/_pydev_imps/_pydev_thread.py
deleted file mode 100644
index c996aef8a572..000000000000
--- a/python/helpers/pydev/_pydev_imps/_pydev_thread.py
+++ /dev/null
@@ -1,12 +0,0 @@
-try:
- from thread import *
-except:
- from _thread import * #Py3k
-
-try:
- from gevent import monkey # @UnresolvedImport
- saved = monkey.saved['thread']
- for key, val in saved.items():
- globals()[key] = val
-except:
- pass
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_threading.py b/python/helpers/pydev/_pydev_imps/_pydev_threading.py
deleted file mode 100644
index 9bb01ae42a33..000000000000
--- a/python/helpers/pydev/_pydev_imps/_pydev_threading.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from threading import * # Make up for things we may forget @UnusedWildImport
-
-# Force what we know we need
-from threading import enumerate, currentThread, Condition, Event, Thread, Lock
-try:
- from threading import settrace
-except:
- pass
-try:
- from threading import Timer
-except:
- pass # Jython 2.1
-
-
-try:
- from gevent import monkey # @UnresolvedImport
- saved = monkey.saved['threading']
- for key, val in saved.items():
- globals()[key] = val
-except:
- pass
diff --git a/python/helpers/pydev/_pydev_imps/_pydev_time.py b/python/helpers/pydev/_pydev_imps/_pydev_time.py
deleted file mode 100644
index 5a877d853ad0..000000000000
--- a/python/helpers/pydev/_pydev_imps/_pydev_time.py
+++ /dev/null
@@ -1,9 +0,0 @@
-from time import *
-
-try:
- from gevent import monkey # @UnresolvedImport
- saved = monkey.saved['time']
- for key, val in saved.items():
- globals()[key] = val
-except:
- pass
diff --git a/python/helpers/pydev/_pydev_runfiles/pydev_runfiles_parallel.py b/python/helpers/pydev/_pydev_runfiles/pydev_runfiles_parallel.py
index f91391bb5c39..f1c003f5221d 100644
--- a/python/helpers/pydev/_pydev_runfiles/pydev_runfiles_parallel.py
+++ b/python/helpers/pydev/_pydev_runfiles/pydev_runfiles_parallel.py
@@ -1,5 +1,5 @@
import unittest
-from _pydev_imps import _pydev_thread
+from _pydev_imps._pydev_saved_modules import thread
try:
import Queue
except:
@@ -283,9 +283,9 @@ class ClientThread(threading.Thread):
if False:
proc = subprocess.Popen(args, env=os.environ, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- _pydev_thread.start_new_thread(self._reader_thread,(proc.stdout, sys.stdout))
+ thread.start_new_thread(self._reader_thread,(proc.stdout, sys.stdout))
- _pydev_thread.start_new_thread(target=self._reader_thread,args=(proc.stderr, sys.stderr))
+ thread.start_new_thread(target=self._reader_thread,args=(proc.stderr, sys.stderr))
else:
proc = subprocess.Popen(args, env=os.environ, shell=False)
proc.wait()
diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_additional_thread_info_regular.py b/python/helpers/pydev/_pydevd_bundle/pydevd_additional_thread_info_regular.py
index fc0b564d9f3e..a5590627b3ba 100644
--- a/python/helpers/pydev/_pydevd_bundle/pydevd_additional_thread_info_regular.py
+++ b/python/helpers/pydev/_pydevd_bundle/pydevd_additional_thread_info_regular.py
@@ -1,6 +1,6 @@
import sys
import weakref
-from _pydev_imps import _pydev_thread
+from _pydev_imps._pydev_saved_modules import thread
from _pydevd_bundle.pydevd_constants import STATE_RUN, PYTHON_SUSPEND, dict_iter_items
from _pydevd_bundle.pydevd_frame import PyDBFrame
@@ -109,7 +109,7 @@ class PyDBAdditionalThreadInfoWithoutCurrentFramesSupport(PyDBAdditionalThreadIn
#Or if the user compiled threadframe (from http://www.majid.info/mylos/stories/2004/06/10/threadframe.html)
#NOT RLock!! (could deadlock if it was)
- self.lock = _pydev_thread.allocate_lock()
+ self.lock = thread.allocate_lock()
self._acquire_lock = self.lock.acquire
self._release_lock = self.lock.release
diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_breakpoints.py b/python/helpers/pydev/_pydevd_bundle/pydevd_breakpoints.py
index 2ecae4071ad8..ae990f130a8a 100644
--- a/python/helpers/pydev/_pydevd_bundle/pydevd_breakpoints.py
+++ b/python/helpers/pydev/_pydevd_bundle/pydevd_breakpoints.py
@@ -8,7 +8,7 @@ _original_excepthook = None
_handle_exceptions = None
-from _pydev_imps import _pydev_threading as threading
+from _pydev_imps._pydev_saved_modules import threading
threadingCurrentThread = threading.currentThread
diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py b/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py
index 60ba0ac8d049..14fb74d11792 100644
--- a/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py
+++ b/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py
@@ -59,8 +59,10 @@ each command has a format:
'''
from _pydev_bundle.pydev_imports import _queue
-from _pydev_imps import _pydev_time as time, _pydev_thread
-from _pydev_imps._pydev_socket import socket, AF_INET, SOCK_STREAM, SHUT_RD, SHUT_WR
+from _pydev_imps._pydev_saved_modules import time
+from _pydev_imps._pydev_saved_modules import thread
+from _pydev_imps._pydev_saved_modules import socket
+from socket import socket, AF_INET, SOCK_STREAM, SHUT_RD, SHUT_WR
from _pydevd_bundle.pydevd_constants import * #@UnusedWildImport
try:
@@ -812,7 +814,7 @@ class ReloadCodeCommand(InternalThreadCommand):
self.thread_id = thread_id
self.module_name = module_name
self.executed = False
- self.lock = _pydev_thread.allocate_lock()
+ self.lock = thread.allocate_lock()
def can_be_executed_by(self, thread_id):
diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_constants.py b/python/helpers/pydev/_pydevd_bundle/pydevd_constants.py
index cfc0f5de50c9..a7794b19bf3b 100644
--- a/python/helpers/pydev/_pydevd_bundle/pydevd_constants.py
+++ b/python/helpers/pydev/_pydevd_bundle/pydevd_constants.py
@@ -95,11 +95,43 @@ except:
# Jython 2.1 doesn't accept that construct
SUPPORT_GEVENT = False
-USE_LIB_COPY = SUPPORT_GEVENT and not IS_PY3K and sys.version_info[1] >= 6
-from _pydev_imps import _pydev_threading as threading
+# At the moment gevent supports Python >= 2.6 and Python >= 3.3
+USE_LIB_COPY = SUPPORT_GEVENT and \
+ ((not IS_PY3K and sys.version_info[1] >= 6) or
+ (IS_PY3K and sys.version_info[1] >= 3))
-from _pydev_imps import _pydev_thread
-_nextThreadIdLock = _pydev_thread.allocate_lock()
+
+def protect_libraries_from_patching():
+ patched = ['threading', 'thread', '_thread', 'time', 'socket', 'Queue', 'queue', 'select',
+ 'xmlrpclib', 'SimpleXMLRPCServer', 'BaseHTTPServer', 'SocketServer',
+ 'xmlrpc.client', 'xmlrpc.server', 'http.server', 'socketserver']
+
+ for name in patched:
+ try:
+ __import__(name)
+ except:
+ pass
+
+ patched_modules = dict([(k, v) for k, v in sys.modules.items()
+ if k in patched])
+
+ for name in patched_modules:
+ del sys.modules[name]
+
+ import _pydev_imps._pydev_saved_modules
+
+ for name in patched_modules:
+ sys.modules[name] = patched_modules[name]
+
+
+if USE_LIB_COPY:
+ protect_libraries_from_patching()
+
+
+from _pydev_imps._pydev_saved_modules import threading
+
+from _pydev_imps._pydev_saved_modules import thread
+_nextThreadIdLock = thread.allocate_lock()
#=======================================================================================================================
# Jython?
diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_custom_frames.py b/python/helpers/pydev/_pydevd_bundle/pydevd_custom_frames.py
index 0b72ca889cf5..79f77fd914ff 100644
--- a/python/helpers/pydev/_pydevd_bundle/pydevd_custom_frames.py
+++ b/python/helpers/pydev/_pydevd_bundle/pydevd_custom_frames.py
@@ -1,6 +1,6 @@
from _pydevd_bundle.pydevd_constants import * #@UnusedWildImport
from pydevd_file_utils import get_abs_path_real_path_and_base_from_frame
-from _pydev_imps import _pydev_thread
+from _pydev_imps._pydev_saved_modules import thread
threadingCurrentThread = threading.currentThread
DEBUG = False
@@ -22,7 +22,7 @@ class CustomFramesContainer:
def custom_frames_container_init(): #Note: no staticmethod on jython 2.1 (so, use free-function)
- CustomFramesContainer.custom_frames_lock = _pydev_thread.allocate_lock()
+ CustomFramesContainer.custom_frames_lock = thread.allocate_lock()
# custom_frames can only be accessed if properly locked with custom_frames_lock!
# Key is a string identifying the frame (as well as the thread it belongs to).
diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_trace_dispatch_regular.py b/python/helpers/pydev/_pydevd_bundle/pydevd_trace_dispatch_regular.py
index ec5f12d19c30..79d231878904 100644
--- a/python/helpers/pydev/_pydevd_bundle/pydevd_trace_dispatch_regular.py
+++ b/python/helpers/pydev/_pydevd_bundle/pydevd_trace_dispatch_regular.py
@@ -1,7 +1,7 @@
import traceback
from _pydev_bundle.pydev_is_thread_alive import is_thread_alive
-from _pydev_imps import _pydev_threading as threading
+from _pydev_imps._pydev_saved_modules import threading
from _pydevd_bundle.pydevd_constants import get_thread_id
from _pydevd_bundle.pydevd_dont_trace_files import DONT_TRACE
from _pydevd_bundle.pydevd_kill_all_pydevd_threads import kill_all_pydev_threads
diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_tracing.py b/python/helpers/pydev/_pydevd_bundle/pydevd_tracing.py
index 4674a928f9e7..c1c5a0fdb939 100644
--- a/python/helpers/pydev/_pydevd_bundle/pydevd_tracing.py
+++ b/python/helpers/pydev/_pydevd_bundle/pydevd_tracing.py
@@ -1,5 +1,5 @@
from _pydevd_bundle.pydevd_constants import * #@UnusedWildImport
-from _pydev_imps import _pydev_thread
+from _pydev_imps._pydev_saved_modules import thread
try:
import cStringIO as StringIO #may not always be available @UnusedImport
@@ -20,7 +20,7 @@ class TracingFunctionHolder:
'''
_original_tracing = None
_warn = True
- _lock = _pydev_thread.allocate_lock()
+ _lock = thread.allocate_lock()
_traceback_limit = 1
_warnings_shown = {}
diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_vars.py b/python/helpers/pydev/_pydevd_bundle/pydevd_vars.py
index 6f3b1841f9e6..d928528c038a 100644
--- a/python/helpers/pydev/_pydevd_bundle/pydevd_vars.py
+++ b/python/helpers/pydev/_pydevd_bundle/pydevd_vars.py
@@ -7,7 +7,7 @@ from types import * #@UnusedWildImport
from _pydevd_bundle.pydevd_custom_frames import get_custom_frame
from _pydevd_bundle.pydevd_xml import *
-from _pydev_imps import _pydev_thread
+from _pydev_imps._pydev_saved_modules import thread
try:
from StringIO import StringIO
@@ -15,7 +15,7 @@ except ImportError:
from io import StringIO
import sys #@Reimport
-from _pydev_imps import _pydev_threading as threading
+from _pydev_imps._pydev_saved_modules import threading
import traceback
from _pydevd_bundle import pydevd_save_locals
from _pydev_bundle.pydev_imports import Exec, quote, execfile
@@ -68,7 +68,7 @@ def dump_frames(thread_id):
# AdditionalFramesContainer
#===============================================================================
class AdditionalFramesContainer:
- lock = _pydev_thread.allocate_lock()
+ lock = thread.allocate_lock()
additional_frames = {} #dict of dicts
diff --git a/python/helpers/pydev/pycompletionserver.py b/python/helpers/pydev/pycompletionserver.py
index baa54c90628f..913951032ddb 100644
--- a/python/helpers/pydev/pycompletionserver.py
+++ b/python/helpers/pydev/pycompletionserver.py
@@ -32,7 +32,7 @@ else:
from _pydev_bundle import _pydev_imports_tipper
-from _pydev_imps import _pydev_socket as socket
+from _pydev_imps._pydev_saved_modules import socket
import sys
if sys.platform == "darwin":
@@ -57,7 +57,7 @@ for name, mod in sys.modules.items():
import traceback
-from _pydev_imps import _pydev_time as time
+from _pydev_imps._pydev_saved_modules import time
try:
import StringIO
@@ -194,7 +194,7 @@ class CompletionServer:
def connect_to_server(self):
- from _pydev_imps import _pydev_socket as socket
+ from _pydev_imps._pydev_saved_modules import socket
self.socket = s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
diff --git a/python/helpers/pydev/pydev_ipython/inputhookglut.py b/python/helpers/pydev/pydev_ipython/inputhookglut.py
index 6551bb99ace6..bbd6882fe8ec 100644
--- a/python/helpers/pydev/pydev_ipython/inputhookglut.py
+++ b/python/helpers/pydev/pydev_ipython/inputhookglut.py
@@ -31,7 +31,7 @@ GLUT Inputhook support functions
#-----------------------------------------------------------------------------
import os
import sys
-from _pydev_imps import _pydev_time as time
+from _pydev_imps._pydev_saved_modules import time
import signal
import OpenGL.GLUT as glut # @UnresolvedImport
import OpenGL.platform as platform # @UnresolvedImport
diff --git a/python/helpers/pydev/pydev_ipython/inputhookpyglet.py b/python/helpers/pydev/pydev_ipython/inputhookpyglet.py
index 98a7878ccb75..bf08afdc779d 100644
--- a/python/helpers/pydev/pydev_ipython/inputhookpyglet.py
+++ b/python/helpers/pydev/pydev_ipython/inputhookpyglet.py
@@ -22,7 +22,7 @@ Authors
import os
import sys
-from _pydev_imps import _pydev_time as time
+from _pydev_imps._pydev_saved_modules import time
from timeit import default_timer as clock
import pyglet # @UnresolvedImport
from pydev_ipython.inputhook import stdin_ready
diff --git a/python/helpers/pydev/pydev_ipython/inputhookwx.py b/python/helpers/pydev/pydev_ipython/inputhookwx.py
index 6b72d61091b4..88fe2c6e3ba1 100644
--- a/python/helpers/pydev/pydev_ipython/inputhookwx.py
+++ b/python/helpers/pydev/pydev_ipython/inputhookwx.py
@@ -18,7 +18,7 @@ Authors: Robin Dunn, Brian Granger, Ondrej Certik
import sys
import signal
-from _pydev_imps import _pydev_time as time
+from _pydev_imps._pydev_saved_modules import time
from timeit import default_timer as clock
import wx
diff --git a/python/helpers/pydev/pydevconsole.py b/python/helpers/pydev/pydevconsole.py
index bb1f48266c6d..92198f715aff 100644
--- a/python/helpers/pydev/pydevconsole.py
+++ b/python/helpers/pydev/pydevconsole.py
@@ -1,7 +1,8 @@
'''
Entry point module to start the interactive console.
'''
-from _pydev_imps._pydev_thread import start_new_thread
+from _pydev_imps._pydev_saved_modules import thread
+start_new_thread = thread.start_new_thread
try:
from code import InteractiveConsole
@@ -14,7 +15,7 @@ from code import InteractiveInterpreter
import os
import sys
-from _pydev_imps import _pydev_threading as threading
+from _pydev_imps._pydev_saved_modules import threading
import traceback
from _pydev_bundle import fix_getpass
diff --git a/python/helpers/pydev/pydevd.py b/python/helpers/pydev/pydevd.py
index baeadb3601e5..5c608e335704 100644
--- a/python/helpers/pydev/pydevd.py
+++ b/python/helpers/pydev/pydevd.py
@@ -10,12 +10,16 @@ import os
import sys
import traceback
+from _pydevd_bundle.pydevd_constants import IS_JYTH_LESS25, IS_PY3K, IS_PY34_OLDER, get_thread_id, dict_keys, dict_pop, dict_contains, \
+ dict_iter_items, DebugInfoHolder, PYTHON_SUSPEND, STATE_SUSPEND, STATE_RUN, get_frame, xrange, \
+ clear_cached_thread_id
from _pydev_bundle import fix_getpass
from _pydev_bundle import pydev_imports, pydev_log
from _pydev_bundle._pydev_filesystem_encoding import getfilesystemencoding
from _pydev_bundle.pydev_is_thread_alive import is_thread_alive
-from _pydev_imps import _pydev_threading as threading
-from _pydev_imps import _pydev_time as time, _pydev_thread
+from _pydev_imps._pydev_saved_modules import threading
+from _pydev_imps._pydev_saved_modules import time
+from _pydev_imps._pydev_saved_modules import thread
from _pydevd_bundle import pydevd_io, pydevd_vm_type, pydevd_tracing
from _pydevd_bundle import pydevd_utils
from _pydevd_bundle import pydevd_vars
@@ -28,9 +32,6 @@ from _pydevd_bundle.pydevd_comm import CMD_SET_BREAK, CMD_SET_NEXT_STATEMENT, CM
set_global_debugger, WriterThread, pydevd_find_thread_by_id, pydevd_log, \
start_client, start_server, InternalGetBreakpointException, InternalSendCurrExceptionTrace, \
InternalSendCurrExceptionTraceProceeded
-from _pydevd_bundle.pydevd_constants import IS_JYTH_LESS25, IS_PY3K, IS_PY34_OLDER, get_thread_id, dict_keys, dict_pop, dict_contains, \
- dict_iter_items, DebugInfoHolder, PYTHON_SUSPEND, STATE_SUSPEND, STATE_RUN, get_frame, xrange, \
- clear_cached_thread_id
from _pydevd_bundle.pydevd_custom_frames import CustomFramesContainer, custom_frames_container_init
from _pydevd_bundle.pydevd_frame_utils import add_exception_to_frame
from _pydevd_bundle.pydevd_kill_all_pydevd_threads import kill_all_pydev_threads
@@ -202,8 +203,8 @@ class PyDB:
self.break_on_caught_exceptions = {}
self.ready_to_run = False
- self._main_lock = _pydev_thread.allocate_lock()
- self._lock_running_thread_ids = _pydev_thread.allocate_lock()
+ self._main_lock = thread.allocate_lock()
+ self._lock_running_thread_ids = thread.allocate_lock()
self._py_db_command_thread_event = threading.Event()
CustomFramesContainer._py_db_command_thread_event = self._py_db_command_thread_event
self._finish_debugging_session = False
@@ -1131,7 +1132,7 @@ def settrace(
-_set_trace_lock = _pydev_thread.allocate_lock()
+_set_trace_lock = thread.allocate_lock()
def _locked_settrace(
host,
diff --git a/python/helpers/pydev/pydevd_concurrency_analyser/pydevd_concurrency_logger.py b/python/helpers/pydev/pydevd_concurrency_analyser/pydevd_concurrency_logger.py
index 4377421507c0..6fe9fe06a72a 100644
--- a/python/helpers/pydev/pydevd_concurrency_analyser/pydevd_concurrency_logger.py
+++ b/python/helpers/pydev/pydevd_concurrency_analyser/pydevd_concurrency_logger.py
@@ -13,7 +13,7 @@ try:
except:
from urllib.parse import quote # @UnresolvedImport
-from _pydev_imps import _pydev_threading as threading
+from _pydev_imps._pydev_saved_modules import threading
threadingCurrentThread = threading.currentThread
diff --git a/python/helpers/pydev/pydevd_concurrency_analyser/pydevd_thread_wrappers.py b/python/helpers/pydev/pydevd_concurrency_analyser/pydevd_thread_wrappers.py
index 1d093563f228..8658a7612457 100644
--- a/python/helpers/pydev/pydevd_concurrency_analyser/pydevd_thread_wrappers.py
+++ b/python/helpers/pydev/pydevd_concurrency_analyser/pydevd_thread_wrappers.py
@@ -1,4 +1,4 @@
-from _pydev_imps import _pydev_threading as threading
+from _pydev_imps._pydev_saved_modules import threading
def wrapper(fun):
diff --git a/python/helpers/pydev/tests/test_pyserver.py b/python/helpers/pydev/tests/test_pyserver.py
index 95e7471328b7..98fe2a97f7d0 100644
--- a/python/helpers/pydev/tests/test_pyserver.py
+++ b/python/helpers/pydev/tests/test_pyserver.py
@@ -4,10 +4,12 @@
import sys
import os
try:
- from _pydev_imps._pydev_thread import start_new_thread
+ from _pydev_imps._pydev_saved_modules import thread
+ start_new_thread = thread.start_new_thread
except:
sys.path.append(os.path.dirname(os.path.dirname(__file__)))
- from _pydev_imps._pydev_thread import start_new_thread
+ from _pydev_imps._pydev_saved_modules import thread
+ start_new_thread = thread.start_new_thread
#make it as if we were executing from the directory above this one (so that we can use pycompletionserver
diff --git a/python/helpers/python-skeletons/__builtin__.py b/python/helpers/python-skeletons/__builtin__.py
index d9f63538c4d9..95ace39a878a 100644
--- a/python/helpers/python-skeletons/__builtin__.py
+++ b/python/helpers/python-skeletons/__builtin__.py
@@ -2390,7 +2390,7 @@ class file(object):
def next(self):
"""Returns the next input line.
- :rtype: bytes | unicode
+ :rtype: bytes
"""
return ''
@@ -2399,7 +2399,7 @@ class file(object):
before obtaining size bytes).
:type size: numbers.Integral
- :rtype: bytes | unicode
+ :rtype: bytes
"""
return ''
@@ -2407,7 +2407,7 @@ class file(object):
"""Read one entire line from the file.
:type size: numbers.Integral
- :rtype: bytes | unicode
+ :rtype: bytes
"""
return ''
@@ -2416,14 +2416,14 @@ class file(object):
lines thus read.
:type sizehint: numbers.Integral
- :rtype: list[bytes | unicode]
+ :rtype: list[bytes]
"""
return []
def xreadlines(self):
"""This method returns the same thing as iter(f).
- :rtype: collections.Iterable[bytes | unicode]
+ :rtype: collections.Iterable[bytes]
"""
return []
@@ -2454,7 +2454,7 @@ class file(object):
def write(self, str):
""""Write a string to the file.
- :type str: bytes | unicode
+ :type str: bytes
:rtype: None
"""
pass
@@ -2462,7 +2462,7 @@ class file(object):
def writelines(self, sequence):
"""Write a sequence of strings to the file.
- :type sequence: collections.Iterable[bytes | unicode]
+ :type sequence: collections.Iterable[bytes]
:rtype: None
"""
pass
diff --git a/python/helpers/rest_formatter.py b/python/helpers/rest_formatter.py
index 76b988426139..b0241e4cd2f2 100644
--- a/python/helpers/rest_formatter.py
+++ b/python/helpers/rest_formatter.py
@@ -224,7 +224,7 @@ class RestHTMLTranslator(HTMLTranslator):
return HTMLTranslator.visit_problematic(self, node)
directive, text = self._strip_markup(node.astext())
- if directive[1:-1] in ('exc', 'class'):
+ if directive and directive[1:-1] in ('exc', 'class'):
self.body.append(self.starttag(node, 'a', '', href='psi_element://#typename#' + text))
self.body.append(text)
self.body.append('')
diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbConnectionManager.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbConnectionManager.java
index 18b259214ea7..27be6ff10510 100644
--- a/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbConnectionManager.java
+++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbConnectionManager.java
@@ -94,29 +94,22 @@ public final class IpnbConnectionManager implements ProjectComponent {
}
private void startConnection(@NotNull final IpnbCodePanel codePanel, final IpnbFileEditor fileEditor, final String path) {
- String url = IpnbSettings.getInstance(myProject).getURL();
- if (StringUtil.isEmptyOrSpaces(url)) {
- url = IpnbSettings.DEFAULT_URL;
- }
+ String url = getURL();
boolean connectionStarted = startConnection(codePanel, path, url, false);
if (!connectionStarted) {
- final String finalUrl = url;
- url = showDialogUrl(url);
- if (url == null) return;
- IpnbSettings.getInstance(myProject).setURL(url);
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
- final boolean serverStarted = startIpythonServer(finalUrl, fileEditor);
+ final boolean serverStarted = startIpythonServer(url, fileEditor);
if (!serverStarted) {
return;
}
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
- startConnection(codePanel, path, finalUrl, true);
+ startConnection(codePanel, path, url, true);
}
});
}
@@ -124,29 +117,39 @@ public final class IpnbConnectionManager implements ProjectComponent {
}
}
+ private String getURL() {
+ String url = IpnbSettings.getInstance(myProject).getURL();
+ return StringUtil.isEmptyOrSpaces(url) ? IpnbSettings.DEFAULT_URL : url;
+ }
+
@Nullable
public static String showDialogUrl(@NotNull final String initialUrl) {
- final String url = Messages.showInputDialog("Jupyter Notebook URL:", "Start Jupyter Notebook", null, initialUrl,
- new InputValidator() {
- @Override
- public boolean checkInput(String inputString) {
- try {
- final URI uri = new URI(inputString);
- if (uri.getPort() == -1 || StringUtil.isEmptyOrSpaces(uri.getHost())) {
- return false;
- }
- }
- catch (URISyntaxException e) {
- return false;
- }
- return !inputString.isEmpty();
- }
+ final String url = UIUtil.invokeAndWaitIfNeeded(new Computable() {
+ @Override
+ public String compute() {
+ return Messages.showInputDialog("Jupyter Notebook URL:", "Start Jupyter Notebook", null, initialUrl,
+ new InputValidator() {
+ @Override
+ public boolean checkInput(String inputString) {
+ try {
+ final URI uri = new URI(inputString);
+ if (uri.getPort() == -1 || StringUtil.isEmptyOrSpaces(uri.getHost())) {
+ return false;
+ }
+ }
+ catch (URISyntaxException e) {
+ return false;
+ }
+ return !inputString.isEmpty();
+ }
- @Override
- public boolean canClose(String inputString) {
- return true;
- }
- });
+ @Override
+ public boolean canClose(String inputString) {
+ return true;
+ }
+ });
+ }
+ });
return url == null ? null : StringUtil.trimEnd(url, "/");
}
@@ -258,7 +261,7 @@ public final class IpnbConnectionManager implements ProjectComponent {
});
}
- public boolean startIpythonServer(@NotNull final String url, @NotNull final IpnbFileEditor fileEditor) {
+ public boolean startIpythonServer(@NotNull final String initUrl, @NotNull final IpnbFileEditor fileEditor) {
final Module module = ProjectFileIndex.SERVICE.getInstance(myProject).getModuleForFile(fileEditor.getVirtualFile());
if (module == null) return false;
final Sdk sdk = PythonSdkType.findPythonSdk(module);
@@ -268,7 +271,8 @@ public final class IpnbConnectionManager implements ProjectComponent {
}
try {
final PyPackage ipythonPackage = PyPackageManager.getInstance(sdk).findPackage("ipython", false);
- if (ipythonPackage == null) {
+ final PyPackage jupyterPackage = PyPackageManager.getInstance(sdk).findPackage("jupyter", false);
+ if (ipythonPackage == null && jupyterPackage == null) {
showWarning(fileEditor, "Add Jupyter to the interpreter of the current project.", null);
return false;
}
@@ -276,6 +280,10 @@ public final class IpnbConnectionManager implements ProjectComponent {
catch (ExecutionException ignored) {
}
+ String url = showDialogUrl(initUrl);
+ if (url == null) return false;
+ IpnbSettings.getInstance(myProject).setURL(url);
+
final Pair hostPort = getHostPortFromUrl(url);
if (hostPort == null) {
showWarning(fileEditor, "Please, check Jupyter Notebook URL in Settings->Tools->Jupyter Notebook",
diff --git a/python/pluginJava/com/jetbrains/python/psi/impl/PyJavaClassType.java b/python/pluginJava/com/jetbrains/python/psi/impl/PyJavaClassType.java
index 651b55ad18c8..ef2526744022 100644
--- a/python/pluginJava/com/jetbrains/python/psi/impl/PyJavaClassType.java
+++ b/python/pluginJava/com/jetbrains/python/psi/impl/PyJavaClassType.java
@@ -31,9 +31,7 @@ import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
/**
* @author yole
@@ -49,7 +47,7 @@ public class PyJavaClassType implements PyClassLikeType {
@Nullable
public List extends RatedResolveResult> resolveMember(@NotNull final String name,
- PyExpression location,
+ @Nullable PyExpression location,
@NotNull AccessDirection direction,
@NotNull PyResolveContext resolveContext) {
return resolveMember(name, location, direction, resolveContext, true);
@@ -153,14 +151,72 @@ public class PyJavaClassType implements PyClassLikeType {
@Override
public void visitMembers(@NotNull final Processor processor, final boolean inherited, @NotNull TypeEvalContext context) {
- // TODO: Implement
+ for (PsiMethod method : myClass.getAllMethods()) {
+ processor.process(method);
+ }
+
+ for (PsiField field : myClass.getAllFields()) {
+ processor.process(field);
+ }
+
+ if (!inherited) {
+ return;
+ }
+
+ for (PyClassLikeType type : getAncestorTypes(context)) {
+ if (type != null) {
+ type.visitMembers(processor, false, context);
+ }
+ }
+ }
+
+ @NotNull
+ @Override
+ public Set getMemberNames(boolean inherited, @NotNull TypeEvalContext context) {
+ final Set result = new LinkedHashSet<>();
+
+ for (PsiMethod method : myClass.getAllMethods()) {
+ result.add(method.getName());
+ }
+
+ for (PsiField field : myClass.getAllFields()) {
+ result.add(field.getName());
+ }
+
+ if (inherited) {
+ for (PyClassLikeType type : getAncestorTypes(context)) {
+ if (type != null) {
+ result.addAll(type.getMemberNames(false, context));
+ }
+ }
+ }
+
+ return result;
}
@NotNull
@Override
public List getAncestorTypes(@NotNull final TypeEvalContext context) {
- // TODO: Implement
- return Collections.emptyList();
+ final List result = new ArrayList<>();
+
+ final Deque deque = new LinkedList<>();
+ final Set visited = new HashSet<>();
+
+ deque.addAll(Arrays.asList(myClass.getSupers()));
+
+ while (!deque.isEmpty()) {
+ final PsiClass current = deque.pollFirst();
+
+ if (current == null || !visited.add(current)) {
+ continue;
+ }
+
+ result.add(new PyJavaClassType(current, myDefinition));
+
+ deque.addAll(Arrays.asList(current.getSupers()));
+ }
+
+ return result;
}
@Override
diff --git a/python/psi-api/src/com/jetbrains/python/psi/types/PyClassLikeType.java b/python/psi-api/src/com/jetbrains/python/psi/types/PyClassLikeType.java
index 4cf201e14652..f7d40633fd48 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/types/PyClassLikeType.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/types/PyClassLikeType.java
@@ -26,6 +26,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
+import java.util.Set;
/**
* @author vlan
@@ -42,8 +43,10 @@ public interface PyClassLikeType extends PyCallableType, PyWithAncestors {
List getSuperClassTypes(@NotNull TypeEvalContext context);
@Nullable
- List extends RatedResolveResult> resolveMember(@NotNull final String name, @Nullable PyExpression location,
- @NotNull AccessDirection direction, @NotNull PyResolveContext resolveContext,
+ List extends RatedResolveResult> resolveMember(@NotNull final String name,
+ @Nullable PyExpression location,
+ @NotNull AccessDirection direction,
+ @NotNull PyResolveContext resolveContext,
boolean inherited);
// TODO: Pull to PyType at next iteration
@@ -58,6 +61,9 @@ public interface PyClassLikeType extends PyCallableType, PyWithAncestors {
*/
void visitMembers(@NotNull Processor processor, boolean inherited, @NotNull TypeEvalContext context);
+ @NotNull
+ Set getMemberNames(boolean inherited, @NotNull TypeEvalContext context);
+
boolean isValid();
@Nullable
diff --git a/python/src/com/jetbrains/python/PyCustomType.java b/python/src/com/jetbrains/python/PyCustomType.java
index d01170f9d40f..f8dd377fa589 100644
--- a/python/src/com/jetbrains/python/PyCustomType.java
+++ b/python/src/com/jetbrains/python/PyCustomType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -112,7 +112,10 @@ public class PyCustomType implements PyClassLikeType {
// Delegate calls to classes, we mimic but filter if filter is set.
for (final PyClassLikeType typeToMimic : myTypesToMimic) {
- final List extends RatedResolveResult> results = typeToMimic.toInstance().resolveMember(name, location, direction, resolveContext, inherited);
+ final List extends RatedResolveResult> results = typeToMimic.toInstance().resolveMember(
+ name, location, direction, resolveContext, inherited
+ );
+
if (results != null) {
globalResult.addAll(Collections2.filter(results, new ResolveFilter()));
}
@@ -253,7 +256,9 @@ public class PyCustomType implements PyClassLikeType {
}
@Override
- public final void visitMembers(@NotNull final Processor processor, final boolean inherited, @NotNull final TypeEvalContext context) {
+ public final void visitMembers(@NotNull final Processor processor,
+ final boolean inherited,
+ @NotNull final TypeEvalContext context) {
for (final PyClassLikeType type : myTypesToMimic) {
// Only visit methods that are allowed by filter (if any)
type.visitMembers(new Processor() {
@@ -271,6 +276,18 @@ public class PyCustomType implements PyClassLikeType {
}
}
+ @NotNull
+ @Override
+ public Set getMemberNames(boolean inherited, @NotNull TypeEvalContext context) {
+ final Set result = new LinkedHashSet<>();
+
+ for (PyClassLikeType type : myTypesToMimic) {
+ result.addAll(type.getMemberNames(inherited, context));
+ }
+
+ return result;
+ }
+
/**
* Predicate that filters completion using {@link #myFilter}
*/
diff --git a/python/src/com/jetbrains/python/codeInsight/PyTypingTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/PyTypingTypeProvider.java
index 8d267245eb8f..d414e9abead1 100644
--- a/python/src/com/jetbrains/python/codeInsight/PyTypingTypeProvider.java
+++ b/python/src/com/jetbrains/python/codeInsight/PyTypingTypeProvider.java
@@ -25,6 +25,7 @@ import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiPolyVariantReference;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.containers.HashSet;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyExpressionCodeFragmentImpl;
@@ -82,7 +83,7 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
// XXX: Requires switching from stub to AST
final PyExpression value = annotation.getValue();
if (value != null) {
- final PyType type = getType(value, context);
+ final PyType type = getType(value, new Context(context));
if (type != null) {
final PyType optionalType = getOptionalTypeFromDefaultNone(param, type, context);
return Ref.create(optionalType != null ? optionalType : type);
@@ -126,11 +127,11 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
// XXX: Requires switching from stub to AST
final PyExpression value = annotation.getValue();
if (value != null) {
- final PyType type = getType(value, context);
+ final PyType type = getType(value, new Context(context));
return type != null ? Ref.create(type) : null;
}
}
- final PyType constructorType = getGenericConstructorType(function, context);
+ final PyType constructorType = getGenericConstructorType(function, new Context(context));
if (constructorType != null) {
return Ref.create(constructorType);
}
@@ -154,7 +155,7 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
final PyExpression[] args = callExpr.getArguments();
if (args.length > 0) {
final PyExpression typeExpr = args[0];
- return getType(typeExpr, context);
+ return getType(typeExpr, new Context(context));
}
}
return null;
@@ -166,7 +167,7 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
final PyTargetExpression target = (PyTargetExpression)referenceTarget;
final String comment = getTypeComment(target);
if (comment != null) {
- final PyType type = getStringBasedType(comment, referenceTarget, context);
+ final PyType type = getStringBasedType(comment, referenceTarget, new Context(context));
if (type instanceof PyTupleType) {
final PyTupleExpression tupleExpr = PsiTreeUtil.getParentOfType(target, PyTupleExpression.class);
if (tupleExpr != null) {
@@ -243,7 +244,7 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
@Nullable
- private static PyType getGenericConstructorType(@NotNull PyFunction function, @NotNull TypeEvalContext context) {
+ private static PyType getGenericConstructorType(@NotNull PyFunction function, @NotNull Context context) {
if (PyUtil.isInit(function)) {
final PyClass cls = function.getContainingClass();
if (cls != null) {
@@ -258,9 +259,9 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
@NotNull
- private static List collectGenericTypes(@NotNull PyClass cls, @NotNull TypeEvalContext context) {
+ private static List collectGenericTypes(@NotNull PyClass cls, @NotNull Context context) {
boolean isGeneric = false;
- for (PyClass ancestor : cls.getAncestorClasses(context)) {
+ for (PyClass ancestor : cls.getAncestorClasses(context.getTypeContext())) {
if (GENERIC_CLASSES.contains(ancestor.getQualifiedName())) {
isGeneric = true;
break;
@@ -273,7 +274,7 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
if (expr instanceof PySubscriptionExpression) {
final PyExpression indexExpr = ((PySubscriptionExpression)expr).getIndexExpression();
if (indexExpr != null) {
- for (PsiElement resolved : tryResolving(indexExpr, context)) {
+ for (PsiElement resolved : tryResolving(indexExpr, context.getTypeContext())) {
final PyGenericType genericType = getGenericType(resolved, context);
if (genericType != null) {
results.add(genericType);
@@ -288,49 +289,60 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
@Nullable
- private static PyType getType(@NotNull PyExpression expression, @NotNull TypeEvalContext context) {
+ private static PyType getType(@NotNull PyExpression expression, @NotNull Context context) {
final List members = Lists.newArrayList();
- for (PsiElement resolved : tryResolving(expression, context)) {
+ for (PsiElement resolved : tryResolving(expression, context.getTypeContext())) {
members.add(getTypeForResolvedElement(resolved, context));
}
return PyUnionType.union(members);
}
@Nullable
- private static PyType getTypeForResolvedElement(@NotNull PsiElement resolved, @NotNull TypeEvalContext context) {
- final PyType unionType = getUnionType(resolved, context);
- if (unionType != null) {
- return unionType;
+ private static PyType getTypeForResolvedElement(@NotNull PsiElement resolved, @NotNull Context context) {
+ if (context.getExpressionCache().contains(resolved)) {
+ // Recursive types are not yet supported
+ return null;
}
- final Ref optionalType = getOptionalType(resolved, context);
- if (optionalType != null) {
- return optionalType.get();
+
+ context.getExpressionCache().add(resolved);
+ try {
+ final PyType unionType = getUnionType(resolved, context);
+ if (unionType != null) {
+ return unionType;
+ }
+ final Ref optionalType = getOptionalType(resolved, context);
+ if (optionalType != null) {
+ return optionalType.get();
+ }
+ final PyType callableType = getCallableType(resolved, context);
+ if (callableType != null) {
+ return callableType;
+ }
+ final PyType parameterizedType = getParameterizedType(resolved, context);
+ if (parameterizedType != null) {
+ return parameterizedType;
+ }
+ final PyType builtinCollection = getBuiltinCollection(resolved);
+ if (builtinCollection != null) {
+ return builtinCollection;
+ }
+ final PyType genericType = getGenericType(resolved, context);
+ if (genericType != null) {
+ return genericType;
+ }
+ final Ref classType = getClassType(resolved, context.getTypeContext());
+ if (classType != null) {
+ return classType.get();
+ }
+ final PyType stringBasedType = getStringBasedType(resolved, context);
+ if (stringBasedType != null) {
+ return stringBasedType;
+ }
+ return null;
}
- final PyType callableType = getCallableType(resolved, context);
- if (callableType != null) {
- return callableType;
+ finally {
+ context.getExpressionCache().remove(resolved);
}
- final PyType parameterizedType = getParameterizedType(resolved, context);
- if (parameterizedType != null) {
- return parameterizedType;
- }
- final PyType builtinCollection = getBuiltinCollection(resolved);
- if (builtinCollection != null) {
- return builtinCollection;
- }
- final PyType genericType = getGenericType(resolved, context);
- if (genericType != null) {
- return genericType;
- }
- final Ref classType = getClassType(resolved, context);
- if (classType != null) {
- return classType.get();
- }
- final PyType stringBasedType = getStringBasedType(resolved, context);
- if (stringBasedType != null) {
- return stringBasedType;
- }
- return null;
}
@Nullable
@@ -358,6 +370,12 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
@Nullable
public static PyType getTypeFromTargetExpression(@NotNull PyTargetExpression expression, @NotNull TypeEvalContext context) {
+ return getTypeFromTargetExpression(expression, new Context(context));
+ }
+
+ @Nullable
+ private static PyType getTypeFromTargetExpression(@NotNull PyTargetExpression expression,
+ @NotNull Context context) {
// XXX: Requires switching from stub to AST
final PyExpression assignedValue = expression.findAssignedValue();
return assignedValue != null ? getTypeForResolvedElement(assignedValue, context) : null;
@@ -385,11 +403,11 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
@Nullable
- private static Ref getOptionalType(@NotNull PsiElement element, @NotNull TypeEvalContext context) {
+ private static Ref getOptionalType(@NotNull PsiElement element, @NotNull Context context) {
if (element instanceof PySubscriptionExpression) {
final PySubscriptionExpression subscriptionExpr = (PySubscriptionExpression)element;
final PyExpression operand = subscriptionExpr.getOperand();
- final Collection operandNames = resolveToQualifiedNames(operand, context);
+ final Collection operandNames = resolveToQualifiedNames(operand, context.getTypeContext());
if (operandNames.contains("typing.Optional")) {
final PyExpression indexExpr = subscriptionExpr.getIndexExpression();
if (indexExpr != null) {
@@ -405,7 +423,7 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
@Nullable
- private static PyType getStringBasedType(@NotNull PsiElement element, @NotNull TypeEvalContext context) {
+ private static PyType getStringBasedType(@NotNull PsiElement element, @NotNull Context context) {
if (element instanceof PyStringLiteralExpression) {
// XXX: Requires switching from stub to AST
final String contents = ((PyStringLiteralExpression)element).getStringValue();
@@ -415,7 +433,7 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
@Nullable
- private static PyType getStringBasedType(@NotNull String contents, @NotNull PsiElement anchor, @NotNull TypeEvalContext context) {
+ private static PyType getStringBasedType(@NotNull String contents, @NotNull PsiElement anchor, @NotNull Context context) {
final Project project = anchor.getProject();
final PyExpressionCodeFragmentImpl codeFragment = new PyExpressionCodeFragmentImpl(project, "dummy.py", contents, false);
codeFragment.setContext(anchor.getContainingFile());
@@ -436,11 +454,11 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
@Nullable
- private static PyType getCallableType(@NotNull PsiElement resolved, @NotNull TypeEvalContext context) {
+ private static PyType getCallableType(@NotNull PsiElement resolved, @NotNull Context context) {
if (resolved instanceof PySubscriptionExpression) {
final PySubscriptionExpression subscriptionExpr = (PySubscriptionExpression)resolved;
final PyExpression operand = subscriptionExpr.getOperand();
- final Collection operandNames = resolveToQualifiedNames(operand, context);
+ final Collection operandNames = resolveToQualifiedNames(operand, context.getTypeContext());
if (operandNames.contains("typing.Callable")) {
final PyExpression indexExpr = subscriptionExpr.getIndexExpression();
if (indexExpr instanceof PyTupleExpression) {
@@ -466,11 +484,11 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
@Nullable
- private static PyType getUnionType(@NotNull PsiElement element, @NotNull TypeEvalContext context) {
+ private static PyType getUnionType(@NotNull PsiElement element, @NotNull Context context) {
if (element instanceof PySubscriptionExpression) {
final PySubscriptionExpression subscriptionExpr = (PySubscriptionExpression)element;
final PyExpression operand = subscriptionExpr.getOperand();
- final Collection operandNames = resolveToQualifiedNames(operand, context);
+ final Collection operandNames = resolveToQualifiedNames(operand, context.getTypeContext());
if (operandNames.contains("typing.Union")) {
return PyUnionType.union(getIndexTypes(subscriptionExpr, context));
}
@@ -479,12 +497,12 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
@Nullable
- private static PyGenericType getGenericType(@NotNull PsiElement element, @NotNull TypeEvalContext context) {
+ private static PyGenericType getGenericType(@NotNull PsiElement element, @NotNull Context context) {
if (element instanceof PyCallExpression) {
final PyCallExpression assignedCall = (PyCallExpression)element;
final PyExpression callee = assignedCall.getCallee();
if (callee != null) {
- final Collection calleeQNames = resolveToQualifiedNames(callee, context);
+ final Collection calleeQNames = resolveToQualifiedNames(callee, context.getTypeContext());
if (calleeQNames.contains("typing.TypeVar")) {
final PyExpression[] arguments = assignedCall.getArguments();
if (arguments.length > 0) {
@@ -503,8 +521,8 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
@Nullable
- private static PyType getGenericTypeBound(@NotNull PyExpression[] typeVarArguments, @NotNull TypeEvalContext context) {
- final List types = new ArrayList();
+ private static PyType getGenericTypeBound(@NotNull PyExpression[] typeVarArguments, @NotNull Context context) {
+ final List types = new ArrayList<>();
for (int i = 1; i < typeVarArguments.length; i++) {
types.add(getType(typeVarArguments[i], context));
}
@@ -512,7 +530,7 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
@NotNull
- private static List getIndexTypes(@NotNull PySubscriptionExpression expression, @NotNull TypeEvalContext context) {
+ private static List getIndexTypes(@NotNull PySubscriptionExpression expression, @NotNull Context context) {
final List types = new ArrayList();
final PyExpression indexExpr = expression.getIndexExpression();
if (indexExpr instanceof PyTupleExpression) {
@@ -528,7 +546,7 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
@Nullable
- private static PyType getParameterizedType(@NotNull PsiElement element, @NotNull TypeEvalContext context) {
+ private static PyType getParameterizedType(@NotNull PsiElement element, @NotNull Context context) {
if (element instanceof PySubscriptionExpression) {
final PySubscriptionExpression subscriptionExpr = (PySubscriptionExpression)element;
final PyExpression operand = subscriptionExpr.getOperand();
@@ -611,4 +629,23 @@ public class PyTypingTypeProvider extends PyTypeProviderBase {
}
return null;
}
+
+ private static class Context {
+ @NotNull private final TypeEvalContext myContext;
+ @NotNull private final Set myCache = new HashSet<>();
+
+ private Context(@NotNull TypeEvalContext context) {
+ myContext = context;
+ }
+
+ @NotNull
+ public TypeEvalContext getTypeContext() {
+ return myContext;
+ }
+
+ @NotNull
+ public Set getExpressionCache() {
+ return myCache;
+ }
+ }
}
diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyNamedTupleType.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyNamedTupleType.java
index 4de9ed6b41da..feaaceea053a 100644
--- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyNamedTupleType.java
+++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyNamedTupleType.java
@@ -35,6 +35,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Set;
/**
* @author yole
@@ -69,7 +70,7 @@ public class PyNamedTupleType extends PyClassTypeImpl implements PyCallableType
return classMembers;
}
if (myFields.contains(name)) {
- return Collections.singletonList(new RatedResolveResult(1000, new PyElementImpl(myDeclaration.getNode())));
+ return Collections.singletonList(new RatedResolveResult(RatedResolveResult.RATE_HIGH, new PyElementImpl(myDeclaration.getNode())));
}
return null;
}
@@ -98,7 +99,7 @@ public class PyNamedTupleType extends PyClassTypeImpl implements PyCallableType
@Override
public PyType getCallType(@NotNull TypeEvalContext context, @NotNull PyCallSiteExpression callSite) {
if (myDefinitionLevel > 0) {
- return new PyNamedTupleType(myClass, myDeclaration, myName, myFields, myDefinitionLevel-1);
+ return new PyNamedTupleType(myClass, myDeclaration, myName, myFields, myDefinitionLevel - 1);
}
return null;
}
@@ -113,6 +114,15 @@ public class PyNamedTupleType extends PyClassTypeImpl implements PyCallableType
return "PyNamedTupleType: " + myName;
}
+ @NotNull
+ @Override
+ public Set getMemberNames(boolean inherited, @NotNull TypeEvalContext context) {
+ final Set result = super.getMemberNames(inherited, context);
+ result.addAll(myFields);
+
+ return result;
+ }
+
@Nullable
public static PyType fromCall(@NotNull PyCallExpression call, @NotNull TypeEvalContext context, int level) {
final String name = PyPsiUtils.strValue(call.getArgument(0, PyExpression.class));
diff --git a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java
index b7a3c49c3bf4..ec08ba2ab102 100644
--- a/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java
+++ b/python/src/com/jetbrains/python/codeInsight/stdlib/PyStdlibTypeProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -44,8 +44,10 @@ import static com.jetbrains.python.psi.PyUtil.as;
public class PyStdlibTypeProvider extends PyTypeProviderBase {
private static final Set OPEN_FUNCTIONS = ImmutableSet.of("__builtin__.open", "io.open", "os.fdopen",
"pathlib.Path.open");
- private static final String BINARY_FILE_TYPE = "io.FileIO[bytes]";
- private static final String TEXT_FILE_TYPE = "io.TextIOWrapper[unicode]";
+
+ private static final String PY2K_FILE_TYPE = "file";
+ private static final String PY3K_BINARY_FILE_TYPE = "io.FileIO[bytes]";
+ private static final String PY3K_TEXT_FILE_TYPE = "io.TextIOWrapper[unicode]";
@Nullable
public static PyStdlibTypeProvider getInstance() {
@@ -275,19 +277,16 @@ public class PyStdlibTypeProvider extends PyTypeProviderBase {
}
}
final LanguageLevel level = LanguageLevel.forElement(anchor);
- // Binary mode
- if (mode.contains("b")) {
- return PyTypeParser.getTypeByName(anchor, BINARY_FILE_TYPE);
- }
- // Text mode
- else {
- if (level.isPy3K() || "io.open".equals(callQName)) {
- return PyTypeParser.getTypeByName(anchor, TEXT_FILE_TYPE);
- }
- else {
- return PyTypeParser.getTypeByName(anchor, BINARY_FILE_TYPE);
+
+ if (level.isPy3K() || "io.open".equals(callQName)) {
+ if (mode.contains("b")) {
+ return PyTypeParser.getTypeByName(anchor, PY3K_BINARY_FILE_TYPE);
+ } else {
+ return PyTypeParser.getTypeByName(anchor, PY3K_TEXT_FILE_TYPE);
}
}
+
+ return PyTypeParser.getTypeByName(anchor, PY2K_FILE_TYPE);
}
@Nullable
diff --git a/python/src/com/jetbrains/python/debugger/PySignatureCacheManagerImpl.java b/python/src/com/jetbrains/python/debugger/PySignatureCacheManagerImpl.java
index ac367f1de2cb..456b42f65c54 100644
--- a/python/src/com/jetbrains/python/debugger/PySignatureCacheManagerImpl.java
+++ b/python/src/com/jetbrains/python/debugger/PySignatureCacheManagerImpl.java
@@ -249,7 +249,11 @@ public class PySignatureCacheManagerImpl extends PySignatureCacheManager {
if (parts.length > 0) {
PySignature signature = new PySignature(path, parts[0]);
for (int i = 1; i < parts.length; i++) {
- String[] var = parts[i].split(":");
+ String part = parts[i];
+ if (part.isEmpty()) {
+ continue;
+ }
+ String[] var = part.split(":");
if (var.length == 2) {
if (RETURN_TYPE.equals(var[0])) {
signature = signature.addReturnType(var[1]);
@@ -260,7 +264,7 @@ public class PySignatureCacheManagerImpl extends PySignatureCacheManager {
}
else {
throw new IllegalStateException(
- "Should be : format for arg or " + RETURN_TYPE + ": for return type; '" + parts[i] + "' instead.");
+ "Should be : format for arg or " + RETURN_TYPE + ": for return type; '" + part + "' instead.");
}
}
return signature;
diff --git a/python/src/com/jetbrains/python/documentation/docstrings/PyDocstringGenerator.java b/python/src/com/jetbrains/python/documentation/docstrings/PyDocstringGenerator.java
index 50fea52fba76..d2456729a9e7 100644
--- a/python/src/com/jetbrains/python/documentation/docstrings/PyDocstringGenerator.java
+++ b/python/src/com/jetbrains/python/documentation/docstrings/PyDocstringGenerator.java
@@ -209,10 +209,7 @@ public class PyDocstringGenerator {
statementList.accept(visitor);
if (!isConstructor((PyFunction)myDocStringOwner) && (visitor.myHasReturn || addReturn)) {
// will add :return: placeholder in Sphinx/Epydoc docstrings
- myAddedParams.add(new DocstringParam("", null, true));
- if (PyCodeInsightSettings.getInstance().INSERT_TYPE_DOCSTUB) {
- withReturnValue("");
- }
+ withReturnValue(null);
}
}
return this;
@@ -274,7 +271,8 @@ public class PyDocstringGenerator {
String type = paramTypes.get(paramCoordinates);
if (type == null && PyCodeInsightSettings.getInstance().INSERT_TYPE_DOCSTUB) {
if (signature != null) {
- type = StringUtil.notNullize(param.isReturnValue() ? signature.getReturnTypeQualifiedName() :
+ type = StringUtil.notNullize(param.isReturnValue() ?
+ signature.getReturnTypeQualifiedName() :
signature.getArgTypeQualifiedName(param.getName()));
}
else {
diff --git a/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java b/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java
index 4438beb72e93..a4858898a3f2 100644
--- a/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyTypeCheckerInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -46,8 +46,9 @@ public class PyTypeCheckerInspection extends PyInspection {
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly, @NotNull LocalInspectionToolSession session) {
- if (LOG.isDebugEnabled())
+ if (LOG.isDebugEnabled()) {
session.putUserData(TIME_KEY, System.nanoTime());
+ }
return new Visitor(holder, session);
}
@@ -88,18 +89,22 @@ public class PyTypeCheckerInspection extends PyInspection {
private void checkCallSite(@Nullable PyCallSiteExpression callSite) {
final List resultsSet = PyTypeChecker.analyzeCallSite(callSite, myTypeEvalContext);
- final List