mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
Generated
+11
@@ -0,0 +1,11 @@
|
||||
<component name="libraryTable">
|
||||
<library name="junit5_rt">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/plugins/junit5_rt/lib/junit-commons-5.0.0-ALPHA.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/junit5_rt/lib/junit-engine-api-5.0.0-ALPHA.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/junit5_rt/lib/junit-launcher-5.0.0-ALPHA.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
Generated
+9
@@ -0,0 +1,9 @@
|
||||
<component name="libraryTable">
|
||||
<library name="opentest4j">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/plugins/junit5_rt/lib/opentest4j-1.0.0.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
</library>
|
||||
</component>
|
||||
Generated
+1
@@ -151,6 +151,7 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/java/jsp-openapi/jsp-openapi.iml" filepath="$PROJECT_DIR$/java/jsp-openapi/jsp-openapi.iml" group="java" />
|
||||
<module fileurl="file://$PROJECT_DIR$/java/jsp-spi/jsp-spi.iml" filepath="$PROJECT_DIR$/java/jsp-spi/jsp-spi.iml" group="java" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/junit/junit.iml" filepath="$PROJECT_DIR$/plugins/junit/junit.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/junit5_rt/junit5_rt.iml" filepath="$PROJECT_DIR$/plugins/junit5_rt/junit5_rt.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/junit_rt/junit_rt.iml" filepath="$PROJECT_DIR$/plugins/junit_rt/junit_rt.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/lang-api/lang-api.iml" filepath="$PROJECT_DIR$/platform/lang-api/lang-api.iml" group="platform" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/lang-impl/lang-impl.iml" filepath="$PROJECT_DIR$/platform/lang-impl/lang-impl.iml" group="platform" />
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -21,8 +21,6 @@
|
||||
<orderEntry type="module" module-name="java-impl" />
|
||||
<orderEntry type="module" module-name="platform-impl" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
<orderEntry type="module" module-name="diff-api" />
|
||||
<orderEntry type="module" module-name="jps-builders" />
|
||||
</component>
|
||||
<component name="copyright">
|
||||
<Base>
|
||||
|
||||
+2
-1
@@ -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<ObjectReference, ValueMarkup> markupMap = ValueDescriptorImpl.getMarkupMap(process);
|
||||
if (markupMap != null && markupMap.size() > 0) {
|
||||
if (!ContainerUtil.isEmpty(markupMap)) {
|
||||
final Pair<String, Map<String, ObjectReference>> markupVariables = createMarkupVariablesText(markupMap);
|
||||
int offset = markupVariables.getFirst().length() - 1;
|
||||
final TextWithImportsImpl textWithImports = new TextWithImportsImpl(CodeFragmentKind.CODE_BLOCK, markupVariables.getFirst(), "", myDelegate.getFileType());
|
||||
|
||||
+54
@@ -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;
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -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);
|
||||
}
|
||||
|
||||
+81
-27
@@ -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<CatchEvaluator> 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<PsiType> 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) {
|
||||
|
||||
+4
-1
@@ -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);
|
||||
|
||||
+57
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+47
@@ -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;
|
||||
}
|
||||
}
|
||||
+75
@@ -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<CatchEvaluator> myCatchBlockEvaluators;
|
||||
@Nullable private final Evaluator myFinallyEvaluator;
|
||||
|
||||
public TryEvaluator(@NotNull Evaluator bodyEvaluator,
|
||||
List<CatchEvaluator> 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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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<Boolean>)() -> JUnitUtil.isJUnit5(containingClass));
|
||||
ClassInheritorsSearch.search(containingClass).forEach(new Processor<PsiClass>() {
|
||||
@Override
|
||||
public boolean process(PsiClass aClass) {
|
||||
if (PsiClassUtil.isRunnableClass(aClass, true, true)) {
|
||||
if (PsiClassUtil.isRunnableClass(aClass, !isJUnit5, true)) {
|
||||
classes.add(aClass);
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -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<String> TEST_ANNOTATIONS = Collections.unmodifiableList(Arrays.asList(TEST_ANNOTATION, TEST5_ANNOTATION));
|
||||
|
||||
private static final List<String> INSTANCE_CONFIGS = Arrays.asList(BEFORE_ANNOTATION_NAME, AFTER_ANNOTATION_NAME);
|
||||
private static final List<String> INSTANCE_5_CONFIGS = Arrays.asList(BEFORE_EACH_ANNOTATION_NAME, AFTER_EACH_ANNOTATION_NAME);
|
||||
|
||||
private static final List<String> STATIC_5_CONFIGS = Arrays.asList(BEFORE_ALL_ANNOTATION_NAME, AFTER_ALL_ANNOTATION_NAME);
|
||||
|
||||
private static final List<String> STATIC_CONFIGS = Arrays.asList(BEFORE_CLASS_ANNOTATION_NAME, AFTER_CLASS_ANNOTATION_NAME,
|
||||
PARAMETRIZED_PARAMETERS_ANNOTATION_NAME);
|
||||
private static final Collection<String> 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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+5
-10
@@ -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) {
|
||||
|
||||
+1
-1
@@ -248,7 +248,7 @@ public class JavaDocReferenceInspectionBase extends BaseJavaBatchLocalInspectio
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return getName();
|
||||
return "Remove tag";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+18
-2
@@ -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<String> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
+11
-5
@@ -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<LocalQuickFix> result = new ArrayList<LocalQuickFix>();
|
||||
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
|
||||
|
||||
+11
-2
@@ -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() {
|
||||
|
||||
+5
@@ -115,6 +115,11 @@ public class MethodParameterFix extends LocalQuickFixAndIntentionActionOnPsiElem
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private ParameterInfoImpl[] getNewParametersInfo(PsiMethod method) throws IncorrectOperationException {
|
||||
List<ParameterInfoImpl> result = new ArrayList<ParameterInfoImpl>();
|
||||
PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
|
||||
+1
-1
@@ -46,7 +46,7 @@ public class ReplacePrimitiveWithBoxedTypeAction extends LocalQuickFixAndIntenti
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return getText();
|
||||
return "Convert primitive to boxed type";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
-4
@@ -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();
|
||||
|
||||
@@ -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("<code class=\"package\">").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("<code class=\"package\">").append("(");
|
||||
myComposer.appendQualifiedName(buf, owner);
|
||||
// buf.append(RefUtil.getPackageName(refElement));
|
||||
buf.append(")").append(HTMLComposerImpl.CODE_CLOSING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<Element> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
-1
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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<String, PsiType> map = new THashMap<String, PsiType>();
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
+10
-13
@@ -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<PsiClass
|
||||
public static final DirectClassInheritorsSearch INSTANCE = new DirectClassInheritorsSearch();
|
||||
|
||||
public static class SearchParameters {
|
||||
private final PsiClass myClass;
|
||||
private final SearchScope myScope;
|
||||
@NotNull private final PsiClass myClass;
|
||||
@NotNull private final SearchScope myScope;
|
||||
private final boolean myIncludeAnonymous;
|
||||
private final boolean myCheckInheritance;
|
||||
|
||||
public SearchParameters(PsiClass aClass, SearchScope scope, boolean includeAnonymous, boolean checkInheritance) {
|
||||
public SearchParameters(@NotNull PsiClass aClass, @NotNull SearchScope scope, boolean includeAnonymous, boolean checkInheritance) {
|
||||
myClass = aClass;
|
||||
myScope = scope;
|
||||
myIncludeAnonymous = includeAnonymous;
|
||||
myCheckInheritance = checkInheritance;
|
||||
}
|
||||
|
||||
public SearchParameters(final PsiClass aClass, SearchScope scope, final boolean includeAnonymous) {
|
||||
public SearchParameters(@NotNull PsiClass aClass, @NotNull SearchScope scope, final boolean includeAnonymous) {
|
||||
this(aClass, scope, includeAnonymous, true);
|
||||
}
|
||||
|
||||
public SearchParameters(final PsiClass aClass, final SearchScope scope) {
|
||||
public SearchParameters(@NotNull PsiClass aClass, @NotNull SearchScope scope) {
|
||||
this(aClass, scope, true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiClass getClassToProcess() {
|
||||
return myClass;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public SearchScope getScope() {
|
||||
return myScope;
|
||||
}
|
||||
@@ -92,12 +94,7 @@ public class DirectClassInheritorsSearch extends ExtensibleQueryFactory<PsiClass
|
||||
final Query<PsiClass> raw = INSTANCE.createUniqueResultsQuery(new SearchParameters(aClass, scope, includeAnonymous, checkInheritance));
|
||||
|
||||
if (!includeAnonymous) {
|
||||
return new FilteredQuery<PsiClass>(raw, new Condition<PsiClass>() {
|
||||
@Override
|
||||
public boolean value(final PsiClass psiClass) {
|
||||
return !(psiClass instanceof PsiAnonymousClass);
|
||||
}
|
||||
});
|
||||
return new FilteredQuery<>(raw, psiClass -> !(psiClass instanceof PsiAnonymousClass));
|
||||
}
|
||||
|
||||
return raw;
|
||||
|
||||
+37
-104
@@ -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<PsiClass, Dir
|
||||
public boolean execute(@NotNull final DirectClassInheritorsSearch.SearchParameters p, @NotNull final Processor<PsiClass> consumer) {
|
||||
final PsiClass aClass = p.getClassToProcess();
|
||||
|
||||
final SearchScope useScope = ApplicationManager.getApplication().runReadAction(new Computable<SearchScope>() {
|
||||
@Override
|
||||
public SearchScope compute() {
|
||||
return aClass.getUseScope();
|
||||
}
|
||||
});
|
||||
final SearchScope useScope = ApplicationManager.getApplication().runReadAction((Computable<SearchScope>)aClass::getUseScope);
|
||||
|
||||
final String qualifiedName = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
|
||||
@Override
|
||||
public String compute() {
|
||||
return aClass.getQualifiedName();
|
||||
}
|
||||
});
|
||||
final String qualifiedName = ApplicationManager.getApplication().runReadAction((Computable<String>)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<PsiClass>() {
|
||||
@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<String>() {
|
||||
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<String>)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<String>() {
|
||||
@Override
|
||||
public String compute() {
|
||||
return aClass.getName();
|
||||
}
|
||||
});
|
||||
final String searchKey = ApplicationManager.getApplication().runReadAction((Computable<String>)aClass::getName);
|
||||
if (StringUtil.isEmpty(searchKey)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Collection<PsiReferenceList> candidates = MethodUsagesSearcher.resolveInReadAction(project,
|
||||
new Computable<Collection<PsiReferenceList>>() {
|
||||
@Override
|
||||
public Collection<PsiReferenceList> compute() {
|
||||
return JavaSuperClassNameOccurenceIndex
|
||||
.getInstance().get(searchKey, project, scope);
|
||||
}
|
||||
});
|
||||
Collection<PsiReferenceList> candidates =
|
||||
MethodUsagesSearcher.resolveInReadAction(project, () -> JavaSuperClassNameOccurenceIndex.getInstance().get(searchKey, project, scope));
|
||||
|
||||
Map<String, List<PsiClass>> classes = new HashMap<String, List<PsiClass>>();
|
||||
Map<String, List<PsiClass>> classes = new HashMap<>();
|
||||
|
||||
for (final PsiReferenceList referenceList : candidates) {
|
||||
ProgressManager.checkCanceled();
|
||||
final PsiClass candidate = (PsiClass)ApplicationManager.getApplication().runReadAction(new Computable<PsiElement>() {
|
||||
@Override
|
||||
public PsiElement compute() {
|
||||
return referenceList.getParent();
|
||||
}
|
||||
});
|
||||
final PsiClass candidate = (PsiClass)ApplicationManager.getApplication().runReadAction((Computable<PsiElement>)referenceList::getParent);
|
||||
if (!checkInheritance(p, aClass, candidate, project)) continue;
|
||||
|
||||
String fqn = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
|
||||
@Override
|
||||
public String compute() {
|
||||
return candidate.getQualifiedName();
|
||||
}
|
||||
});
|
||||
String fqn = ApplicationManager.getApplication().runReadAction((Computable<String>)candidate::getQualifiedName);
|
||||
List<PsiClass> list = classes.get(fqn);
|
||||
if (list == null) {
|
||||
list = new ArrayList<PsiClass>();
|
||||
list = new ArrayList<>();
|
||||
classes.put(fqn, list);
|
||||
}
|
||||
list.add(candidate);
|
||||
@@ -141,20 +101,13 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
|
||||
final VirtualFile jarFile = getJarFile(aClass);
|
||||
for (List<PsiClass> sameNamedClasses : classes.values()) {
|
||||
ProgressManager.checkCanceled();
|
||||
if (!processSameNamedClasses(consumer, sameNamedClasses, jarFile)) return false;
|
||||
if (!processSameNamedClasses(sameNamedClasses, jarFile, consumer)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (p.includeAnonymous()) {
|
||||
Collection<PsiAnonymousClass> anonymousCandidates = MethodUsagesSearcher.resolveInReadAction(project,
|
||||
new Computable<Collection<PsiAnonymousClass>>() {
|
||||
@Override
|
||||
public Collection<PsiAnonymousClass> compute() {
|
||||
return JavaAnonymousClassBaseRefOccurenceIndex
|
||||
.getInstance()
|
||||
.get(searchKey, project, scope);
|
||||
}
|
||||
});
|
||||
Collection<PsiAnonymousClass> 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<PsiClass, Dir
|
||||
if (!consumer.process(candidate)) return false;
|
||||
}
|
||||
|
||||
boolean isEnum = ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return aClass.isEnum();
|
||||
}
|
||||
});
|
||||
boolean isEnum = ApplicationManager.getApplication().runReadAction((Computable<Boolean>)aClass::isEnum);
|
||||
if (isEnum) {
|
||||
// abstract enum can be subclassed in the body
|
||||
PsiField[] fields = ApplicationManager.getApplication().runReadAction(new Computable<PsiField[]>() {
|
||||
@Override
|
||||
public PsiField[] compute() {
|
||||
return aClass.getFields();
|
||||
}
|
||||
});
|
||||
PsiField[] fields = ApplicationManager.getApplication().runReadAction((Computable<PsiField[]>)aClass::getFields);
|
||||
for (final PsiField field : fields) {
|
||||
ProgressManager.checkCanceled();
|
||||
if (field instanceof PsiEnumConstant) {
|
||||
PsiEnumConstantInitializer initializingClass =
|
||||
ApplicationManager.getApplication().runReadAction(new Computable<PsiEnumConstantInitializer>() {
|
||||
@Override
|
||||
public PsiEnumConstantInitializer compute() {
|
||||
return ((PsiEnumConstant)field).getInitializingClass();
|
||||
}
|
||||
});
|
||||
ApplicationManager.getApplication().runReadAction((Computable<PsiEnumConstantInitializer>)((PsiEnumConstant)field)::getInitializingClass);
|
||||
if (initializingClass != null) {
|
||||
if (!consumer.process(initializingClass)) return false;
|
||||
}
|
||||
@@ -198,16 +136,16 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean checkInheritance(final DirectClassInheritorsSearch.SearchParameters p, final PsiClass aClass, final PsiClass candidate, Project project) {
|
||||
return MethodUsagesSearcher.resolveInReadAction(project, new Computable<Boolean>() {
|
||||
@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<PsiClass> consumer, List<PsiClass> sameNamedClasses, final VirtualFile jarFile) {
|
||||
private static boolean processSameNamedClasses(@NotNull List<PsiClass> sameNamedClasses,
|
||||
@Nullable VirtualFile jarFile,
|
||||
@NotNull Processor<PsiClass> consumer) {
|
||||
// if there is a class from the same jar, prefer it
|
||||
boolean sameJarClassFound = false;
|
||||
|
||||
@@ -225,12 +163,7 @@ public class JavaDirectInheritorsSearcher implements QueryExecutor<PsiClass, Dir
|
||||
return sameJarClassFound || ContainerUtil.process(sameNamedClasses, consumer);
|
||||
}
|
||||
|
||||
private static VirtualFile getJarFile(final PsiClass aClass) {
|
||||
return ApplicationManager.getApplication().runReadAction(new Computable<VirtualFile>() {
|
||||
@Override
|
||||
public VirtualFile compute() {
|
||||
return PsiUtil.getJarFile(aClass);
|
||||
}
|
||||
});
|
||||
private static VirtualFile getJarFile(@NotNull PsiClass aClass) {
|
||||
return ApplicationManager.getApplication().runReadAction((Computable<VirtualFile>)() -> PsiUtil.getJarFile(aClass));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<String> set = annotationNames.length == 1 ? Collections.singleton(annotationNames[0]) : new HashSet<String>(Arrays.asList(annotationNames));
|
||||
Set<String> 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<String> annotationNames,
|
||||
final boolean skipExternal) {
|
||||
public static PsiAnnotation findAnnotation(@Nullable PsiModifierListOwner listOwner, @NotNull Collection<String> annotationNames, boolean skipExternal) {
|
||||
if (listOwner == null) return null;
|
||||
|
||||
PsiAnnotation annotation = findOwnAnnotation(listOwner, annotationNames);
|
||||
|
||||
@@ -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<JavadocTagInfo> 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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<PsiNamedElement> result = new ArrayList<PsiNamedElement>(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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<PsiMethod> result = new ArrayList<PsiMethod>();
|
||||
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<PsiModifierListOwner> result = new ArrayList<PsiModifierListOwner>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -41,8 +41,11 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
|
||||
@Override
|
||||
public boolean reduce(InferenceSession session, List<ConstraintFormula> 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;
|
||||
}
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class Test {
|
||||
|
||||
{
|
||||
pair<error descr="'pair(byte)' in 'Test' cannot be applied to '(int)'">(2)</error>;
|
||||
}
|
||||
|
||||
static <T> void pair( byte b) {}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
class Foo {
|
||||
/**
|
||||
* {<warning descr="Javadoc pointing to itself">@link</warning> #foo()}
|
||||
*/
|
||||
void foo(){}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
class Test {
|
||||
/**
|
||||
* @see A#<EOLWarning/>
|
||||
* @see A#<EOLWarning descr="Name expected"></EOLWarning>
|
||||
*/
|
||||
public void i() {}
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
class Foo {
|
||||
/**
|
||||
* {<warning>@link</warning> #foo()}
|
||||
*/
|
||||
void foo(){}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* <warning descr="Class or method reference is expected after @see tag">@see</warning>
|
||||
* @see <warning descr="Class or method reference is expected after @see tag">{@link C}</warning> clarification
|
||||
*
|
||||
* @see C a correct one
|
||||
* @see C#f
|
||||
*/
|
||||
class C {
|
||||
int f;
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
|
||||
interface X {
|
||||
void foo(int[] x);
|
||||
}
|
||||
|
||||
class C {
|
||||
static void main(String[] args){
|
||||
X a = (int x[]) -> { };
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
import java.util.*;
|
||||
|
||||
class X<A extends Comparable<A>, B extends Comparable<B>> {
|
||||
|
||||
class Pair implements Comparable<Pair> {
|
||||
A a;
|
||||
B b;
|
||||
|
||||
|
||||
public A getA() {
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
public B getB() {
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int compareTo(Pair other) {
|
||||
Comparator<Pair> comparator = Comparator.comparing(Pair::getA).thenComparing(Pair::getB);
|
||||
|
||||
return comparator.compare(this, other);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
// "Try to generify 'before2.java'" "true"
|
||||
import java.util.ArrayList;
|
||||
class Use {
|
||||
void f() {
|
||||
ArrayList<String> s = new ArrayLi<caret>st();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
java.util.ArrayList<java.lang.String>\nnew
|
||||
@@ -0,0 +1 @@
|
||||
java.util.ArrayList\nnew
|
||||
@@ -0,0 +1,6 @@
|
||||
import java.util.ArrayList;
|
||||
|
||||
class Test
|
||||
{
|
||||
ArrayList<String> l = new ArrayList();
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import java.util.ArrayList;
|
||||
|
||||
class Test
|
||||
{
|
||||
ArrayList<String> l = new ArrayList();
|
||||
}
|
||||
+2
-1
@@ -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(); }
|
||||
|
||||
+4
@@ -978,4 +978,8 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
|
||||
public void testIDEA152179() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testLooseInvocationContextForProperPrimitiveTypes() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -276,6 +276,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testCLikeArrayDeclarationInLambdaWithExplicitTypes() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
+4
@@ -498,6 +498,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIDEA152659() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
+1
-1
@@ -77,7 +77,7 @@ public class ConvertAtomicToLongAdderIntention extends PsiElementBaseIntentionAc
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<D extends CommonProblemDescriptor> {
|
||||
public interface QuickFix<D extends CommonProblemDescriptor> extends WriteActionAware {
|
||||
QuickFix[] EMPTY_ARRAY = new QuickFix[0];
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module relativePaths="true" type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="true">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="jdk" jdkName="IDEA jdk" jdkType="JavaSDK" />
|
||||
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
|
||||
</component>
|
||||
<component name="copyright">
|
||||
<Base>
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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<myBufferEnd;i+=2) {
|
||||
@@ -213,13 +218,7 @@ public class StringLiteralLexer extends LexerBase {
|
||||
}
|
||||
|
||||
if (myBuffer.charAt(i) == 'u') {
|
||||
i++;
|
||||
for (; i < start + 6; i++) {
|
||||
if (i == myBufferEnd || myBuffer.charAt(i) == '\n' || myBuffer.charAt(i) == myQuoteChar) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
return locateUnicodeEscapeSequence(start, i);
|
||||
}
|
||||
else {
|
||||
return i + 1;
|
||||
@@ -241,6 +240,16 @@ public class StringLiteralLexer extends LexerBase {
|
||||
return i;
|
||||
}
|
||||
|
||||
protected int locateUnicodeEscapeSequence(int start, int i) {
|
||||
i++;
|
||||
for (; i < start + 6; i++) {
|
||||
if (i == myBufferEnd || myBuffer.charAt(i) == '\n' || myBuffer.charAt(i) == myQuoteChar) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void advance() {
|
||||
myLastState = myState;
|
||||
|
||||
@@ -17,6 +17,8 @@ package com.intellij.openapi.application;
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -96,14 +98,27 @@ public abstract class TransactionGuard {
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules a transaction and waits for it to be completed. Only allowed to be invoked on non-UI thread and outside read action.
|
||||
* Schedules a transaction and waits for it to be completed. Fails if invoked on UI thread inside an incompatible transaction,
|
||||
* or inside a read action on non-UI thread.
|
||||
* @see #submitMergeableTransaction(TransactionKind, Runnable)
|
||||
* @param kind
|
||||
* @param transaction
|
||||
* @throws ProcessCanceledException if current thread is interrupted
|
||||
*/
|
||||
public abstract void submitTransactionAndWait(@NotNull TransactionKind kind, @NotNull Runnable transaction) throws ProcessCanceledException;
|
||||
|
||||
/**
|
||||
* Same as {@link #submitTransactionAndWait(TransactionKind, Runnable)}, but returns a value computed by the transaction.
|
||||
*/
|
||||
public <T> T submitTransactionAndWait(@NotNull TransactionKind kind, @NotNull final Computable<T> transaction) throws ProcessCanceledException {
|
||||
final Ref<T> 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.
|
||||
|
||||
@@ -76,7 +76,7 @@ public class PsiCacheKey<T, H extends PsiElement> extends Key<SoftReference<Pair
|
||||
*/
|
||||
private long getModificationCount(@NotNull PsiElement element) {
|
||||
PsiFile file = element.getContainingFile();
|
||||
long fileStamp = file == null ? 0 : file.getModificationStamp();
|
||||
long fileStamp = file == null || file.isPhysical() ? 0 : file.getModificationStamp();
|
||||
PsiModificationTracker tracker = file == null ? element.getManager().getModificationTracker()
|
||||
: file.getManager().getModificationTracker();
|
||||
|
||||
|
||||
+1
-1
@@ -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.
|
||||
@@ -48,7 +48,6 @@ public class TransactionGuardImpl extends TransactionGuard {
|
||||
// please assign exceptions that occur here to Peter
|
||||
LOG.error("Nested transactions are not allowed, see FAQ in TransactionGuard class javadoc. Transaction start trace is in attachment. Kind is " + kind,
|
||||
new Attachment("trace.txt", myTransactionStartTrace));
|
||||
//throw new IllegalStateException("Nested transactions are not allowed");
|
||||
}
|
||||
myTransactionStartTrace = DebugUtil.currentStackTrace();
|
||||
return new AccessToken() {
|
||||
@@ -99,7 +98,7 @@ public class TransactionGuardImpl extends TransactionGuard {
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!isInsideTransaction() || kind != TransactionKind.NO_MERGE && myMergeableKinds.contains(kind)) {
|
||||
if (canRunTransactionNow(kind)) {
|
||||
runSyncTransaction(kind, transaction);
|
||||
}
|
||||
else {
|
||||
@@ -118,6 +117,10 @@ public class TransactionGuardImpl extends TransactionGuard {
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean canRunTransactionNow(@NotNull TransactionKind kind) {
|
||||
return !isInsideTransaction() || kind != TransactionKind.NO_MERGE && myMergeableKinds.contains(kind);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public AccessToken acceptNestedTransactions(TransactionKind... kinds) {
|
||||
@@ -144,9 +147,15 @@ public class TransactionGuardImpl extends TransactionGuard {
|
||||
@Override
|
||||
public void submitTransactionAndWait(@NotNull TransactionKind kind, @NotNull final Runnable transaction) throws ProcessCanceledException {
|
||||
Application app = ApplicationManager.getApplication();
|
||||
assert !app.isDispatchThread() : "submitTransactionAndWait should not be invoked on dispatch thread";
|
||||
assert !app.isReadAccessAllowed() : "submitTransactionAndWait should not be invoked from a read action";
|
||||
if (app.isDispatchThread()) {
|
||||
if (!canRunTransactionNow(kind)) {
|
||||
throw new AssertionError("Cannot run submitTransactionAndWait from another transaction, kind " + kind + " is not allowed");
|
||||
}
|
||||
runSyncTransaction(kind, transaction);
|
||||
return;
|
||||
}
|
||||
|
||||
assert !app.isReadAccessAllowed() : "submitTransactionAndWait should not be invoked from a read action";
|
||||
final Semaphore semaphore = new Semaphore();
|
||||
semaphore.down();
|
||||
final Throwable[] exception = {null};
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.intellij.ui.AutoScrollToSourceHandler;
|
||||
import com.intellij.util.xmlb.XmlSerializerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
/**
|
||||
* User: anna
|
||||
* Date: 28-Feb-2006
|
||||
@@ -83,9 +84,10 @@ public class AnalysisUIOptions implements PersistentStateComponent<AnalysisUIOpt
|
||||
}
|
||||
|
||||
public AnAction createGroupBySeverityAction(final InspectionResultsView view) {
|
||||
return new ToggleAction(InspectionsBundle.message("inspection.action.group.by.severity"),
|
||||
InspectionsBundle.message("inspection.action.group.by.severity.description"),
|
||||
AllIcons.Nodes.SortBySeverity) {
|
||||
return new InspectionResultsViewToggleAction(view,
|
||||
InspectionsBundle.message("inspection.action.group.by.severity"),
|
||||
InspectionsBundle.message("inspection.action.group.by.severity.description"),
|
||||
AllIcons.Nodes.SortBySeverity) {
|
||||
|
||||
|
||||
@Override
|
||||
@@ -94,17 +96,17 @@ public class AnalysisUIOptions implements PersistentStateComponent<AnalysisUIOpt
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
protected void setSelected(boolean state) {
|
||||
GROUP_BY_SEVERITY = state;
|
||||
view.update();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public AnAction createFilterResolvedItemsAction(final InspectionResultsView view){
|
||||
return new ToggleAction(InspectionsBundle.message("inspection.filter.resolved.action.text"),
|
||||
InspectionsBundle.message("inspection.filter.resolved.action.text"),
|
||||
AllIcons.General.Filter) {
|
||||
return new InspectionResultsViewToggleAction(view,
|
||||
InspectionsBundle.message("inspection.filter.resolved.action.text"),
|
||||
InspectionsBundle.message("inspection.filter.resolved.action.text"),
|
||||
AllIcons.General.Filter) {
|
||||
|
||||
|
||||
@Override
|
||||
@@ -113,17 +115,17 @@ public class AnalysisUIOptions implements PersistentStateComponent<AnalysisUIOpt
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
public void setSelected(boolean state) {
|
||||
FILTER_RESOLVED_ITEMS = state;
|
||||
view.update();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public AnAction createShowOutdatedProblemsAction(final InspectionResultsView view) {
|
||||
return new ToggleAction(InspectionsBundle.message("inspection.filter.show.diff.action.text"),
|
||||
InspectionsBundle.message("inspection.filter.show.diff.action.text"),
|
||||
AllIcons.Actions.Diff) {
|
||||
return new InspectionResultsViewToggleAction(view,
|
||||
InspectionsBundle.message("inspection.filter.show.diff.action.text"),
|
||||
InspectionsBundle.message("inspection.filter.show.diff.action.text"),
|
||||
AllIcons.Actions.Diff) {
|
||||
|
||||
|
||||
@Override
|
||||
@@ -132,20 +134,20 @@ public class AnalysisUIOptions implements PersistentStateComponent<AnalysisUIOpt
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
public void setSelected(boolean state) {
|
||||
SHOW_DIFF_WITH_PREVIOUS_RUN = state;
|
||||
if (!SHOW_DIFF_WITH_PREVIOUS_RUN) {
|
||||
SHOW_ONLY_DIFF = false;
|
||||
}
|
||||
view.update();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public AnAction createGroupByDirectoryAction(final InspectionResultsView view) {
|
||||
return new ToggleAction("Group by directory",
|
||||
"Group by directory",
|
||||
AllIcons.Actions.GroupByPackage) {
|
||||
return new InspectionResultsViewToggleAction(view,
|
||||
"Group by directory",
|
||||
"Group by directory",
|
||||
AllIcons.Actions.GroupByPackage) {
|
||||
|
||||
@Override
|
||||
public boolean isSelected(AnActionEvent e) {
|
||||
@@ -153,17 +155,17 @@ public class AnalysisUIOptions implements PersistentStateComponent<AnalysisUIOpt
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
public void setSelected(boolean state) {
|
||||
SHOW_STRUCTURE = state;
|
||||
view.update();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public AnAction createShowDiffOnlyAction(final InspectionResultsView view) {
|
||||
return new ToggleAction(InspectionsBundle.message("inspection.filter.show.diff.only.action.text"),
|
||||
InspectionsBundle.message("inspection.filter.show.diff.only.action.text"),
|
||||
AllIcons.Actions.ShowChangesOnly) {
|
||||
return new InspectionResultsViewToggleAction(view,
|
||||
InspectionsBundle.message("inspection.filter.show.diff.only.action.text"),
|
||||
InspectionsBundle.message("inspection.filter.show.diff.only.action.text"),
|
||||
AllIcons.Actions.ShowChangesOnly) {
|
||||
|
||||
|
||||
@Override
|
||||
@@ -172,9 +174,8 @@ public class AnalysisUIOptions implements PersistentStateComponent<AnalysisUIOpt
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelected(AnActionEvent e, boolean state) {
|
||||
public void setSelected(boolean state) {
|
||||
SHOW_ONLY_DIFF = state;
|
||||
view.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -194,4 +195,29 @@ public class AnalysisUIOptions implements PersistentStateComponent<AnalysisUIOpt
|
||||
public void loadState(AnalysisUIOptions state) {
|
||||
XmlSerializerUtil.copyBean(state, this);
|
||||
}
|
||||
|
||||
private abstract static class InspectionResultsViewToggleAction extends ToggleAction {
|
||||
@NotNull private final InspectionResultsView myView;
|
||||
|
||||
public InspectionResultsViewToggleAction(@NotNull InspectionResultsView view,
|
||||
@NotNull String text,
|
||||
@NotNull String description,
|
||||
@NotNull Icon icon) {
|
||||
super(text, description, icon);
|
||||
myView = view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(@NotNull AnActionEvent e) {
|
||||
e.getPresentation().setEnabled(!myView.isUpdating());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setSelected(AnActionEvent e, boolean state) {
|
||||
setSelected(state);
|
||||
myView.update();
|
||||
}
|
||||
|
||||
protected abstract void setSelected(boolean state);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-10
@@ -75,15 +75,10 @@ public class RenameElementFix extends LocalQuickFixAndIntentionActionOnPsiElemen
|
||||
@NotNull final PsiElement startElement,
|
||||
@NotNull PsiElement endElement) {
|
||||
if (isAvailable(project, null, file)) {
|
||||
new WriteCommandAction(project) {
|
||||
@Override
|
||||
protected void run(@NotNull Result result) throws Throwable {
|
||||
LOG.assertTrue(file == startElement.getContainingFile());
|
||||
if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
|
||||
RenameProcessor processor = new RenameProcessor(project, startElement, myNewName, false, false);
|
||||
processor.run();
|
||||
}
|
||||
}.execute();
|
||||
LOG.assertTrue(file == startElement.getContainingFile());
|
||||
if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
|
||||
RenameProcessor processor = new RenameProcessor(project, startElement, myNewName, false, false);
|
||||
processor.run();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,6 +97,6 @@ public class RenameElementFix extends LocalQuickFixAndIntentionActionOnPsiElemen
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+13
-5
@@ -23,11 +23,14 @@ import com.intellij.codeInsight.lookup.Lookup;
|
||||
import com.intellij.codeInsight.lookup.LookupManager;
|
||||
import com.intellij.codeInsight.lookup.impl.LookupImpl;
|
||||
import com.intellij.codeInsight.template.impl.*;
|
||||
import com.intellij.codeInsight.template.impl.editorActions.ExpandLiveTemplateCustomAction;
|
||||
import com.intellij.featureStatistics.FeatureUsageTracker;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorAction;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -55,7 +58,16 @@ public abstract class ChooseItemAction extends EditorAction {
|
||||
if (lookup == null) {
|
||||
throw new AssertionError("The last lookup disposed at: " + LookupImpl.getLastLookupDisposeTrace() + "\n-----------------------\n");
|
||||
}
|
||||
|
||||
|
||||
if ((finishingChar == Lookup.NORMAL_SELECT_CHAR || finishingChar == Lookup.REPLACE_SELECT_CHAR) &&
|
||||
hasTemplatePrefix(lookup, finishingChar)) {
|
||||
lookup.hideLookup(true);
|
||||
|
||||
ExpandLiveTemplateCustomAction.createExpandTemplateHandler(finishingChar).execute(editor, null, dataContext);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (finishingChar == Lookup.NORMAL_SELECT_CHAR) {
|
||||
if (!lookup.isFocused()) {
|
||||
FeatureUsageTracker.getInstance().triggerFeatureUsed(CodeCompletionFeatures.EDITING_COMPLETION_CONTROL_ENTER);
|
||||
@@ -78,10 +90,6 @@ public abstract class ChooseItemAction extends EditorAction {
|
||||
if (lookup == null) return false;
|
||||
if (!lookup.isAvailableToUser()) return false;
|
||||
if (focusedOnly && lookup.getFocusDegree() == LookupImpl.FocusDegree.UNFOCUSED) return false;
|
||||
if (finishingChar == Lookup.NORMAL_SELECT_CHAR && hasTemplatePrefix(lookup, TemplateSettings.ENTER_CHAR) ||
|
||||
finishingChar == Lookup.REPLACE_SELECT_CHAR && hasTemplatePrefix(lookup, TemplateSettings.TAB_CHAR)) {
|
||||
return false;
|
||||
}
|
||||
if (finishingChar == Lookup.REPLACE_SELECT_CHAR) {
|
||||
return !lookup.getItems().isEmpty();
|
||||
}
|
||||
|
||||
+47
-36
@@ -23,7 +23,6 @@ import com.intellij.lang.Language;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.event.EditorFactoryAdapter;
|
||||
import com.intellij.openapi.editor.event.EditorFactoryEvent;
|
||||
@@ -33,11 +32,15 @@ import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Trinity;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiUtilBase;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.PairProcessor;
|
||||
import com.intellij.util.containers.ConcurrentFactoryMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -132,6 +135,7 @@ public class TemplateManagerImpl extends TemplateManager implements Disposable {
|
||||
public boolean startTemplate(@NotNull Editor editor, char shortcutChar) {
|
||||
Runnable runnable = prepareTemplate(editor, shortcutChar, null);
|
||||
if (runnable != null) {
|
||||
PsiDocumentManager.getInstance(myProject).commitDocument(editor.getDocument());
|
||||
runnable.run();
|
||||
}
|
||||
return runnable != null;
|
||||
@@ -260,36 +264,31 @@ public class TemplateManagerImpl extends TemplateManager implements Disposable {
|
||||
|
||||
PsiFile file = PsiUtilBase.getPsiFileInEditor(editor, myProject);
|
||||
if (file == null) return null;
|
||||
TemplateSettings templateSettings = TemplateSettings.getInstance();
|
||||
|
||||
Map<TemplateImpl, String> template2argument = findMatchingTemplates(file, editor, shortcutChar, templateSettings);
|
||||
Map<TemplateImpl, String> 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<CustomLiveTemplate> 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<TemplateImpl, String> candidate2Argument = new HashMap<TemplateImpl, String>();
|
||||
@@ -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<TemplateImpl> result = new ArrayList<TemplateImpl>();
|
||||
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<Trinity<Integer, Integer, String>, PsiFile> map =
|
||||
CachedValuesManager.getCachedValue(file, () -> CachedValueProvider.Result.create(new ConcurrentFactoryMap<Trinity<Integer, Integer, String>, PsiFile>() {
|
||||
@Nullable
|
||||
@Override
|
||||
protected PsiFile create(Trinity<Integer, Integer, String> 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));
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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) {
|
||||
|
||||
+1
-3
@@ -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;
|
||||
|
||||
+14
-6
@@ -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<ContentManager> 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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+34
-37
@@ -77,7 +77,7 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro
|
||||
|
||||
private Map<RefEntity, CommonProblemDescriptor[]> 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<RefEntity, CommonProblemDescriptor[]> problems = new HashMap<RefEntity, CommonProblemDescriptor[]>();
|
||||
problems.put(refElement, descriptors);
|
||||
final Map<String, Set<RefEntity>> contents = new HashMap<String, Set<RefEntity>>();
|
||||
final String groupName = refElement.getRefManager().getGroupName((RefElement)refElement);
|
||||
Set<RefEntity> content = contents.get(groupName);
|
||||
if (content == null) {
|
||||
content = new HashSet<RefEntity>();
|
||||
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<RefEntity, CommonProblemDescriptor[]> problems = new HashMap<RefEntity, CommonProblemDescriptor[]>();
|
||||
problems.put(refElement, descriptors);
|
||||
final Map<String, Set<RefEntity>> contents = new HashMap<String, Set<RefEntity>>();
|
||||
final String groupName = refElement.getRefManager().getGroupName((RefElement)refElement);
|
||||
Set<RefEntity> content = contents.get(groupName);
|
||||
if (content == null) {
|
||||
content = new HashSet<RefEntity>();
|
||||
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());
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<HighlightDisplayLevel, ConcurrentMap<String, InspectionGroupNode>> myGroups = ContainerUtil.newConcurrentMap();
|
||||
private final ConcurrentMap<HighlightDisplayLevel, ConcurrentMap<String, InspectionGroupNode>> 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<String, Tools> 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<String, Tools> 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<String, Tools> 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()) {
|
||||
|
||||
@@ -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());
|
||||
|
||||
+32
@@ -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() {
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+43
-16
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<JComponent> 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<JComponent> 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) {
|
||||
|
||||
@@ -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<Object, String>() {
|
||||
@Override
|
||||
public String convert(Object o) {
|
||||
return ((UsageInfo2UsageAdapter)o).getFile().getName();
|
||||
}
|
||||
});
|
||||
myResultsPreviewTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(ListSelectionEvent e) {
|
||||
|
||||
+1
-1
@@ -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.
|
||||
|
||||
@@ -543,7 +543,7 @@ public abstract class BaseRefactoringProcessor implements Runnable {
|
||||
return;
|
||||
}
|
||||
if (ApplicationManager.getApplication().isWriteAccessAllowed()) {
|
||||
LOG.error(new Exception());
|
||||
LOG.error("Refactorings should not be started inside write action\n because they start progress inside and any read action from the progress task would cause the deadlock", new Exception());
|
||||
DumbService.getInstance(myProject).smartInvokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
package com.intellij.ide;
|
||||
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.util.text.StringTokenizer;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
/**
|
||||
* Utility class for working with Preferences
|
||||
* todo: in one year the migration code could be removed
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 05-Mar-16
|
||||
*/
|
||||
public class Prefs {
|
||||
|
||||
public static void put(String key, String value) {
|
||||
Preferences.userRoot().remove(key); // remove from old location
|
||||
getPreferences(key).put(getNodeKey(key), value);
|
||||
}
|
||||
|
||||
public static String get(String key, String def) {
|
||||
migrate(key, def, Preferences::get, Preferences::put);
|
||||
return getPreferences(key).get(getNodeKey(key), def);
|
||||
}
|
||||
|
||||
public static void putInt(String key, int value) {
|
||||
Preferences.userRoot().remove(key); // remove from old location
|
||||
getPreferences(key).putInt(getNodeKey(key), value);
|
||||
}
|
||||
|
||||
public static int getInt(String key, int def) {
|
||||
migrate(key, def, Preferences::getInt, Preferences::putInt);
|
||||
return getPreferences(key).getInt(getNodeKey(key), def);
|
||||
}
|
||||
|
||||
public static void putLong(String key, long value) {
|
||||
Preferences.userRoot().remove(key); // remove from old location
|
||||
getPreferences(key).putLong(getNodeKey(key), value);
|
||||
}
|
||||
|
||||
public static long getLong(String key, long def) {
|
||||
migrate(key, def, Preferences::getLong, Preferences::putLong);
|
||||
return getPreferences(key).getLong(getNodeKey(key), def);
|
||||
}
|
||||
|
||||
public static void putBoolean(String key, boolean value) {
|
||||
Preferences.userRoot().remove(key); // remove from old location
|
||||
getPreferences(key).putBoolean(getNodeKey(key), value);
|
||||
}
|
||||
|
||||
public static boolean getBoolean(String key, boolean def) {
|
||||
migrate(key, def, Preferences::getBoolean, Preferences::putBoolean);
|
||||
return getPreferences(key).getBoolean(getNodeKey(key), def);
|
||||
}
|
||||
|
||||
public static void putFloat(String key, float value) {
|
||||
Preferences.userRoot().remove(key); // remove from old location
|
||||
getPreferences(key).putFloat(getNodeKey(key), value);
|
||||
}
|
||||
|
||||
public static float getFloat(String key, float def) {
|
||||
migrate(key, def, Preferences::getFloat, Preferences::putFloat);
|
||||
return getPreferences(key).getFloat(getNodeKey(key), def);
|
||||
}
|
||||
|
||||
public static void putDouble(String key, double value) {
|
||||
Preferences.userRoot().remove(key); // remove from old location
|
||||
getPreferences(key).putDouble(getNodeKey(key), value);
|
||||
}
|
||||
|
||||
public static double getDouble(String key, double def) {
|
||||
migrate(key, def, Preferences::getDouble, Preferences::putDouble);
|
||||
return getPreferences(key).getDouble(getNodeKey(key), def);
|
||||
}
|
||||
|
||||
public static void putByteArray(String key, byte[] value) {
|
||||
Preferences.userRoot().remove(key); // remove from old location
|
||||
getPreferences(key).putByteArray(getNodeKey(key), value);
|
||||
}
|
||||
|
||||
public static byte[] getByteArray(String key, byte[] def) {
|
||||
migrate(key, def, Preferences::getByteArray, Preferences::putByteArray);
|
||||
return getPreferences(key).getByteArray(getNodeKey(key), def);
|
||||
}
|
||||
|
||||
public static void remove(String key) {
|
||||
getPreferences(key).remove(getNodeKey(key));
|
||||
}
|
||||
|
||||
private static String getNodeKey(String key) {
|
||||
final int dotIndex = key.lastIndexOf('.');
|
||||
return (dotIndex >= 0 ? key.substring(dotIndex + 1) : key).toLowerCase(Locale.US);
|
||||
}
|
||||
|
||||
private static Preferences getPreferences(String key) {
|
||||
Preferences prefs = Preferences.userRoot();
|
||||
final int dotIndex = key.lastIndexOf('.');
|
||||
if (dotIndex > 0) {
|
||||
final StringTokenizer tokenizer = new StringTokenizer(key.substring(0, dotIndex), ".", false);
|
||||
while (tokenizer.hasMoreElements()) {
|
||||
prefs = prefs.node(tokenizer.nextElement().toLowerCase(Locale.US));
|
||||
}
|
||||
}
|
||||
return prefs;
|
||||
}
|
||||
|
||||
private interface Getter<T> {
|
||||
T get(Preferences prefs, String key, T def);
|
||||
}
|
||||
|
||||
private interface Setter<T> {
|
||||
void set(Preferences prefs, String key, T value);
|
||||
}
|
||||
|
||||
private static <T> void migrate(String key, T def, Getter<T> getter, Setter<T> setter) {
|
||||
// rewrite from old location into the new one
|
||||
final Preferences prefs = Preferences.userRoot();
|
||||
final T val = getter.get(prefs, key, def);
|
||||
if (!Comparing.equal(val, def)) {
|
||||
setter.set(getPreferences(key), getNodeKey(key), val);
|
||||
prefs.remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* 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.ide;
|
||||
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 09-Mar-16
|
||||
*/
|
||||
public final class PrivacyPolicy {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.PrivacyPolicy");
|
||||
private static final String CACHED_RESOURCE_NAME = "Cached";
|
||||
private static final String RELATIVE_RESOURCE_PATH = "JetBrains/PrivacyPolicy";
|
||||
private static final String VERSION_COMMENT_START = "<!--";
|
||||
private static final String VERSION_COMMENT_END = "-->";
|
||||
private static final String ACCEPTED_VERSION_KEY = "JetBrains.privacy_policy.accepted_version";
|
||||
private static final Version EMBEDDED_VERSION = new Version(1, 0);
|
||||
@Nullable
|
||||
private static volatile Version ourLatestVersion;
|
||||
|
||||
private static final File ourCachedPolicyFile;
|
||||
static {
|
||||
File dataDir = null;
|
||||
if (SystemInfo.isWindows) {
|
||||
final String appdata = System.getenv("APPDATA");
|
||||
if (appdata != null) {
|
||||
dataDir = new File(appdata, RELATIVE_RESOURCE_PATH);
|
||||
}
|
||||
}
|
||||
else {
|
||||
final String userHome = System.getProperty("user.home");
|
||||
if (userHome != null) {
|
||||
if (SystemInfo.isMac) {
|
||||
final File dataRoot = new File(userHome, "/Library/Application Support");
|
||||
if (dataRoot.exists()) {
|
||||
dataDir = new File(dataRoot, RELATIVE_RESOURCE_PATH);
|
||||
}
|
||||
}
|
||||
else if (SystemInfo.isUnix) {
|
||||
final String dataHome = System.getenv("XDG_DATA_HOME");
|
||||
final File dataRoot = dataHome == null ? new File(userHome, ".local/share") : new File(dataHome);
|
||||
if (dataRoot.exists()) {
|
||||
dataDir = new File(dataRoot, RELATIVE_RESOURCE_PATH);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dataDir == null) {
|
||||
// default location
|
||||
dataDir = new File(PathManager.getSystemPath(), "PrivacyPolicy");
|
||||
}
|
||||
dataDir.mkdirs();
|
||||
ourCachedPolicyFile = new File(dataDir, CACHED_RESOURCE_NAME);
|
||||
}
|
||||
|
||||
public static boolean isLatestVersionAccepted() {
|
||||
return getAcceptedVersion().equals(getLatestVersion());
|
||||
}
|
||||
|
||||
public static void setVersionAccepted(@NotNull Version version) {
|
||||
if (version.isUnknown()) {
|
||||
Prefs.remove(ACCEPTED_VERSION_KEY);
|
||||
}
|
||||
else {
|
||||
Prefs.put(ACCEPTED_VERSION_KEY, version.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Version getLatestVersion() {
|
||||
final Version cached = ourLatestVersion;
|
||||
if (cached != null) {
|
||||
return cached;
|
||||
}
|
||||
Version latest = EMBEDDED_VERSION;
|
||||
if (ourCachedPolicyFile.exists()) {
|
||||
try {
|
||||
final Version version = loadVersion(new FileInputStream(ourCachedPolicyFile));
|
||||
if (!version.isUnknown() && version.compareTo(latest) > 0) {
|
||||
latest = version;
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException ignored) {
|
||||
}
|
||||
}
|
||||
ourLatestVersion = latest;
|
||||
return latest;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Version getAcceptedVersion() {
|
||||
return new Version(Prefs.get(ACCEPTED_VERSION_KEY, null));
|
||||
}
|
||||
|
||||
public static String getText() {
|
||||
return getText(getLatestVersion());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getText(@NotNull Version version) {
|
||||
String text = null;
|
||||
try {
|
||||
if (EMBEDDED_VERSION.equals(version)) {
|
||||
text = loadText(PrivacyPolicy.class.getResourceAsStream("/PrivacyPolicy-" + EMBEDDED_VERSION + ".html"));
|
||||
}
|
||||
else {
|
||||
text = loadText(new FileInputStream(ourCachedPolicyFile));
|
||||
}
|
||||
}
|
||||
catch (Exception ignored) {
|
||||
}
|
||||
return text == null? "" : text;
|
||||
}
|
||||
|
||||
public static void updateText(String text) {
|
||||
try {
|
||||
FileUtil.writeToFile(ourCachedPolicyFile, text);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
finally {
|
||||
ourLatestVersion = null; // clear cache
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String loadText(InputStream stream) {
|
||||
try {
|
||||
if (stream != null) {
|
||||
final Reader reader = new InputStreamReader(stream, "utf-8");
|
||||
try {
|
||||
return new String(FileUtil.adaptiveLoadText(reader));
|
||||
}
|
||||
finally {
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Version loadVersion(final InputStream is) {
|
||||
try {
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"));
|
||||
try {
|
||||
final String line = reader.readLine();
|
||||
if (line != null) {
|
||||
final int startComment = line.indexOf(VERSION_COMMENT_START);
|
||||
if (startComment >= 0 ) {
|
||||
final int endComment = line.indexOf(VERSION_COMMENT_END);
|
||||
if (endComment > startComment) {
|
||||
return new Version(line.substring(startComment + VERSION_COMMENT_START.length(), endComment).trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
reader.close();
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
return Version.UNKNOWN;
|
||||
}
|
||||
|
||||
public static final class Version implements Comparable<PrivacyPolicy.Version>{
|
||||
public static final Version UNKNOWN = new Version(-1, -1);
|
||||
|
||||
private final int myMajor;
|
||||
private final int myMinor;
|
||||
|
||||
/**
|
||||
* @param version string in format "[major].[minor]"
|
||||
*/
|
||||
public Version(@Nullable String version) {
|
||||
final int dot = version == null? -1 : version.indexOf('.');
|
||||
if (dot > 0) {
|
||||
myMajor = Integer.parseInt(version.substring(0, dot));
|
||||
myMinor = Integer.parseInt(version.substring(dot + 1));
|
||||
}
|
||||
else {
|
||||
myMajor = -1;
|
||||
myMinor = -1;
|
||||
}
|
||||
}
|
||||
|
||||
private Version(int major, int minor) {
|
||||
myMajor = major;
|
||||
myMinor = minor;
|
||||
}
|
||||
|
||||
public boolean isUnknown() {
|
||||
return myMajor < 0 || myMinor < 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Version other) {
|
||||
if (isUnknown()) {
|
||||
return other.isUnknown()? 0 : -1;
|
||||
}
|
||||
final int majorDiff = myMajor - other.myMajor;
|
||||
return majorDiff != 0? majorDiff : myMinor - other.myMinor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Version version = (Version)o;
|
||||
|
||||
if (myMajor != version.myMajor) return false;
|
||||
if (myMinor != version.myMinor) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = myMajor;
|
||||
result = 31 * result + myMinor;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return isUnknown()? "unknown" : myMajor + "." + myMinor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,8 +31,10 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.ui.mac.foundation.Foundation.*;
|
||||
@@ -42,7 +44,7 @@ import static com.intellij.ui.mac.foundation.Foundation.*;
|
||||
*/
|
||||
final class MacScrollBarUI extends DefaultScrollBarUI {
|
||||
private static final RegistryValue DISABLED = Registry.get("ide.mac.disableMacScrollbars");
|
||||
private static final List<MacScrollBarUI> UI = Collections.synchronizedList(new ArrayList<MacScrollBarUI>());
|
||||
private static final List<Reference<MacScrollBarUI>> UI = new ArrayList<>();
|
||||
private final Alarm myAlarm = new Alarm();
|
||||
private boolean myTrackHovered;
|
||||
|
||||
@@ -119,16 +121,45 @@ final class MacScrollBarUI extends DefaultScrollBarUI {
|
||||
public void installUI(JComponent c) {
|
||||
super.installUI(c);
|
||||
updateStyle(Style.CURRENT.get());
|
||||
UI.add(this);
|
||||
processReferences(this, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstallUI(JComponent c) {
|
||||
UI.remove(this);
|
||||
processReferences(null, this, null);
|
||||
myAlarm.cancelAllRequests();
|
||||
super.uninstallUI(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes references in the static list of references synchronously.
|
||||
* This method removes all cleared references and the reference specified to remove,
|
||||
* collects objects from other references into the specified list and
|
||||
* adds the reference specified to add.
|
||||
*
|
||||
* @param toAdd the object to add to the static list of references (ignored if {@code null})
|
||||
* @param toRemove the object to remove from the static list of references (ignored if {@code null})
|
||||
* @param list the list to collect all available objects (ignored if {@code null})
|
||||
*/
|
||||
private static void processReferences(MacScrollBarUI toAdd, MacScrollBarUI toRemove, List<MacScrollBarUI> list) {
|
||||
synchronized (UI) {
|
||||
Iterator<Reference<MacScrollBarUI>> iterator = UI.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Reference<MacScrollBarUI> reference = iterator.next();
|
||||
MacScrollBarUI ui = reference.get();
|
||||
if (ui == null || ui == toRemove) {
|
||||
iterator.remove();
|
||||
}
|
||||
else if (list != null) {
|
||||
list.add(ui);
|
||||
}
|
||||
}
|
||||
if (toAdd != null) {
|
||||
UI.add(new WeakReference<MacScrollBarUI>(toAdd));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStyle(Style style) {
|
||||
if (myScrollBar != null) {
|
||||
myScrollBar.setOpaque(style != Style.Overlay);
|
||||
@@ -209,7 +240,9 @@ final class MacScrollBarUI extends DefaultScrollBarUI {
|
||||
if (!DISABLED.asBoolean() && SystemInfo.isMacOSMountainLion) super.run();
|
||||
Style newStyle = get();
|
||||
if (newStyle != oldStyle) {
|
||||
for (MacScrollBarUI ui : UI.toArray(new MacScrollBarUI[0])) {
|
||||
List<MacScrollBarUI> list = new ArrayList<>();
|
||||
processReferences(null, null, list);
|
||||
for (MacScrollBarUI ui : list) {
|
||||
ui.updateStyle(newStyle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,12 @@ import com.sun.jna.Pointer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.event.EventListenerList;
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EventListener;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import static com.intellij.ui.mac.foundation.Foundation.invoke;
|
||||
|
||||
@@ -57,7 +61,7 @@ class NSScrollerHelper {
|
||||
public enum Style {Legacy, Overlay}
|
||||
|
||||
private static ClickBehavior ourClickBehavior = null;
|
||||
private static final EventListenerList ourStyleListeners = new EventListenerList();
|
||||
private static final List<Reference<ScrollbarStyleListener>> ourStyleListeners = new ArrayList<>();
|
||||
|
||||
static {
|
||||
if (SystemInfo.isMac) {
|
||||
@@ -152,19 +156,37 @@ class NSScrollerHelper {
|
||||
}
|
||||
|
||||
public static void addScrollbarStyleListener(@NotNull ScrollbarStyleListener listener) {
|
||||
ourStyleListeners.add(ScrollbarStyleListener.class, listener);
|
||||
processReferences(listener, null, null);
|
||||
}
|
||||
|
||||
public static void removeScrollbarStyleListener(@NotNull ScrollbarStyleListener listener) {
|
||||
ourStyleListeners.remove(ScrollbarStyleListener.class, listener);
|
||||
processReferences(null, listener, null);
|
||||
}
|
||||
|
||||
private static void processReferences(ScrollbarStyleListener toAdd, ScrollbarStyleListener toRemove, List<ScrollbarStyleListener> list) {
|
||||
synchronized (ourStyleListeners) {
|
||||
Iterator<Reference<ScrollbarStyleListener>> iterator = ourStyleListeners.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Reference<ScrollbarStyleListener> reference = iterator.next();
|
||||
ScrollbarStyleListener ui = reference.get();
|
||||
if (ui == null || ui == toRemove) {
|
||||
iterator.remove();
|
||||
}
|
||||
else if (list != null) {
|
||||
list.add(ui);
|
||||
}
|
||||
}
|
||||
if (toAdd != null) {
|
||||
ourStyleListeners.add(new WeakReference<ScrollbarStyleListener>(toAdd));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void fireStyleChanged() {
|
||||
Object[] listeners = ourStyleListeners.getListenerList();
|
||||
for (int i = listeners.length - 2; i >= 0; i -= 2) {
|
||||
if (listeners[i] == ScrollbarStyleListener.class) {
|
||||
((ScrollbarStyleListener)listeners[i + 1]).styleChanged();
|
||||
}
|
||||
List<ScrollbarStyleListener> list = new ArrayList<>();
|
||||
processReferences(null, null, list);
|
||||
for (ScrollbarStyleListener listener : list) {
|
||||
listener.styleChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -21,12 +21,12 @@ import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.concurrency.AtomicFieldUpdater;
|
||||
import jsr166e.CountedCompleter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountedCompleter;
|
||||
|
||||
/**
|
||||
* Executes processor on array elements in range from lo (inclusive) to hi (exclusive).
|
||||
@@ -38,7 +38,7 @@ import java.util.List;
|
||||
* After that, the task completes itself.
|
||||
* The process of completing traverses task parent hierarchy, decrementing each pending count until it either
|
||||
* decrements not-zero pending count and stops or
|
||||
* reaches the top, in which case it invokes {@link jsr166e.ForkJoinTask#quietlyComplete()} which causes the top level task to wake up and join successfully.
|
||||
* reaches the top, in which case it invokes {@link java.util.concurrent.ForkJoinTask#quietlyComplete()} which causes the top level task to wake up and join successfully.
|
||||
* The exceptions from the sub tasks bubble up to the top and saved in {@link #throwable}.
|
||||
*/
|
||||
class ApplierCompleter<T> extends CountedCompleter<Void> {
|
||||
@@ -55,7 +55,7 @@ class ApplierCompleter<T> extends CountedCompleter<Void> {
|
||||
private static final AtomicFieldUpdater<ApplierCompleter, Throwable> throwableUpdater = AtomicFieldUpdater.forFieldOfType(ApplierCompleter.class, Throwable.class);
|
||||
|
||||
// if not null, the read action has failed and this list contains unfinished subtasks
|
||||
private List<ApplierCompleter<T>> failedSubTasks;
|
||||
private final Collection<ApplierCompleter<T>> failedSubTasks;
|
||||
|
||||
//private final List<ApplierCompleter> children = new ArrayList<ApplierCompleter>();
|
||||
|
||||
@@ -72,6 +72,7 @@ class ApplierCompleter<T> extends CountedCompleter<Void> {
|
||||
@NotNull Processor<? super T> processor,
|
||||
int lo,
|
||||
int hi,
|
||||
@NotNull Collection<ApplierCompleter<T>> failedSubTasks,
|
||||
ApplierCompleter<T> next) {
|
||||
super(parent);
|
||||
this.runInReadAction = runInReadAction;
|
||||
@@ -80,28 +81,20 @@ class ApplierCompleter<T> extends CountedCompleter<Void> {
|
||||
this.processor = processor;
|
||||
this.lo = lo;
|
||||
this.hi = hi;
|
||||
this.failedSubTasks = failedSubTasks;
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void compute() {
|
||||
wrapInReadActionAndIndicator(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
execAndForkSubTasks();
|
||||
}
|
||||
});
|
||||
wrapInReadActionAndIndicator(this::execAndForkSubTasks);
|
||||
}
|
||||
|
||||
private void wrapInReadActionAndIndicator(@NotNull final Runnable process) {
|
||||
Runnable toRun = runInReadAction ? new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!ApplicationManagerEx.getApplicationEx().tryRunReadAction(process)) {
|
||||
failedSubTasks = new ArrayList<ApplierCompleter<T>>();
|
||||
failedSubTasks.add(ApplierCompleter.this);
|
||||
doComplete(throwable);
|
||||
}
|
||||
Runnable toRun = runInReadAction ? () -> {
|
||||
if (!ApplicationManagerEx.getApplicationEx().tryRunReadAction(process)) {
|
||||
failedSubTasks.add(this);
|
||||
doComplete(throwable);
|
||||
}
|
||||
} : process;
|
||||
ProgressIndicator existing = ProgressManager.getInstance().getProgressIndicator();
|
||||
@@ -122,6 +115,7 @@ class ApplierCompleter<T> extends CountedCompleter<Void> {
|
||||
long start = System.currentTimeMillis();
|
||||
ApplierCompleter<T> right = null;
|
||||
Throwable throwable = null;
|
||||
|
||||
try {
|
||||
for (int i = lo; i < hi; ++i) {
|
||||
progressIndicator.checkCanceled();
|
||||
@@ -132,7 +126,7 @@ class ApplierCompleter<T> extends CountedCompleter<Void> {
|
||||
long elapsed = finish - start;
|
||||
if (elapsed > 5 && hi - i >= 2 && getSurplusQueuedTaskCount() <= JobSchedulerImpl.CORES_COUNT) {
|
||||
int mid = i + hi >>> 1;
|
||||
right = new ApplierCompleter<T>(this, runInReadAction, progressIndicator, array, processor, mid, hi, right);
|
||||
right = new ApplierCompleter<>(this, runInReadAction, progressIndicator, array, processor, mid, hi, failedSubTasks, right);
|
||||
//children.add(right);
|
||||
addToPendingCount(1);
|
||||
right.fork();
|
||||
@@ -223,34 +217,23 @@ class ApplierCompleter<T> extends CountedCompleter<Void> {
|
||||
}
|
||||
|
||||
boolean completeTaskWhichFailToAcquireReadAction() {
|
||||
if (failedSubTasks == null) {
|
||||
return true;
|
||||
}
|
||||
final boolean[] result = {true};
|
||||
// these tasks could not be executed in the other thread; do them here
|
||||
for (final ApplierCompleter<T> task : failedSubTasks) {
|
||||
task.failedSubTasks = null;
|
||||
task.wrapInReadActionAndIndicator(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (int i = task.lo; i < task.hi; ++i) {
|
||||
if (!task.processor.process(task.array.get(i))) {
|
||||
result[0] = false;
|
||||
break;
|
||||
}
|
||||
task.wrapInReadActionAndIndicator(() -> {
|
||||
for (int i = task.lo; i < task.hi; ++i) {
|
||||
if (!task.processor.process(task.array.get(i))) {
|
||||
result[0] = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (task.failedSubTasks != null) {
|
||||
result[0] = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return System.identityHashCode(this) + " ("+lo+"-"+hi+")";
|
||||
return "("+lo+"-"+hi+")"+(getCompleter() == null ? "" : " parent: "+getCompleter());
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user