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:
+35
-26
@@ -119,14 +119,14 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
|
||||
|
||||
@Override
|
||||
public void visitErrorElement(PsiErrorElement element) {
|
||||
throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", element.getText()));
|
||||
throwExpressionInvalid(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitAssignmentExpression(PsiAssignmentExpression expression) {
|
||||
final PsiExpression rExpression = expression.getRExpression();
|
||||
if(rExpression == null) {
|
||||
throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", expression.getText())); return;
|
||||
throwExpressionInvalid(expression);
|
||||
}
|
||||
|
||||
rExpression.accept(this);
|
||||
@@ -344,8 +344,7 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
|
||||
for (int i = 1; i < operands.length; i++) {
|
||||
PsiExpression expression = operands[i];
|
||||
if (expression == null) {
|
||||
throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", wideExpression.getText()));
|
||||
return;
|
||||
throwExpressionInvalid(wideExpression);
|
||||
}
|
||||
expression.accept(this);
|
||||
Evaluator rResult = myResult;
|
||||
@@ -585,22 +584,22 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
|
||||
final PsiExpression thenExpression = expression.getThenExpression();
|
||||
final PsiExpression elseExpression = expression.getElseExpression();
|
||||
if (thenExpression == null || elseExpression == null){
|
||||
throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", expression.getText())); return;
|
||||
throwExpressionInvalid(expression);
|
||||
}
|
||||
PsiExpression condition = expression.getCondition();
|
||||
condition.accept(this);
|
||||
if (myResult == null) {
|
||||
throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", condition.getText())); return;
|
||||
throwExpressionInvalid(condition);
|
||||
}
|
||||
Evaluator conditionEvaluator = new UnBoxingEvaluator(myResult);
|
||||
thenExpression.accept(this);
|
||||
if (myResult == null) {
|
||||
throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", thenExpression.getText())); return;
|
||||
throwExpressionInvalid(thenExpression);
|
||||
}
|
||||
Evaluator thenEvaluator = myResult;
|
||||
elseExpression.accept(this);
|
||||
if (myResult == null) {
|
||||
throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", elseExpression.getText())); return;
|
||||
throwExpressionInvalid(elseExpression);
|
||||
}
|
||||
Evaluator elseEvaluator = myResult;
|
||||
myResult = new ConditionalExpressionEvaluator(conditionEvaluator, thenEvaluator, elseEvaluator);
|
||||
@@ -743,8 +742,11 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
private static void throwExpressionInvalid(PsiElement expression) {
|
||||
throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", expression.getText()));
|
||||
}
|
||||
|
||||
private static void throwEvaluateException(String message) throws EvaluateRuntimeException {
|
||||
//noinspection ThrowableResultOfMethodCallIgnored
|
||||
throw new EvaluateRuntimeException(EvaluateExceptionUtil.createEvaluateException(message));
|
||||
}
|
||||
|
||||
@@ -799,8 +801,7 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
|
||||
}
|
||||
PsiTypeElement checkType = expression.getCheckType();
|
||||
if(checkType == null) {
|
||||
throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", expression.getText()));
|
||||
return;
|
||||
throwExpressionInvalid(expression);
|
||||
}
|
||||
PsiType type = checkType.getType();
|
||||
expression.getOperand().accept(this);
|
||||
@@ -910,7 +911,7 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
|
||||
psiExpression.accept(this);
|
||||
if (myResult == null) {
|
||||
// cannot build evaluator
|
||||
throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", psiExpression.getText()));
|
||||
throwExpressionInvalid(psiExpression);
|
||||
}
|
||||
argumentEvaluators[idx] = new DisableGC(myResult);
|
||||
}
|
||||
@@ -982,7 +983,7 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
|
||||
}
|
||||
|
||||
if (objectEvaluator == null) {
|
||||
throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", expression.getText()));
|
||||
throwExpressionInvalid(expression);
|
||||
}
|
||||
|
||||
if (psiMethod != null && !psiMethod.isConstructor()) {
|
||||
@@ -1027,7 +1028,7 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
|
||||
public void visitArrayAccessExpression(PsiArrayAccessExpression expression) {
|
||||
final PsiExpression indexExpression = expression.getIndexExpression();
|
||||
if(indexExpression == null) {
|
||||
throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", expression.getText())); return;
|
||||
throwExpressionInvalid(expression);
|
||||
}
|
||||
indexExpression.accept(this);
|
||||
final Evaluator indexEvaluator = handleUnaryNumericPromotion(indexExpression.getType(), myResult);
|
||||
@@ -1064,24 +1065,32 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
|
||||
return operandEvaluator;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"ConstantConditions"})
|
||||
@Override
|
||||
public void visitTypeCastExpression(PsiTypeCastExpression expression) {
|
||||
final PsiExpression operandExpr = expression.getOperand();
|
||||
PsiExpression operandExpr = expression.getOperand();
|
||||
if (operandExpr == null) {
|
||||
throwExpressionInvalid(expression);
|
||||
}
|
||||
operandExpr.accept(this);
|
||||
Evaluator operandEvaluator = myResult;
|
||||
final PsiType castType = expression.getCastType().getType();
|
||||
final PsiType operandType = operandExpr.getType();
|
||||
PsiTypeElement castTypeElem = expression.getCastType();
|
||||
if (castTypeElem == null) {
|
||||
throwExpressionInvalid(expression);
|
||||
}
|
||||
PsiType castType = castTypeElem.getType();
|
||||
PsiType operandType = operandExpr.getType();
|
||||
|
||||
// if operand type can not be resolved in current context - leave it for runtime checks
|
||||
if (castType != null && operandType != null && !TypeConversionUtil.areTypesConvertible(operandType, castType) && PsiUtil.resolveClassInType(operandType) != null) {
|
||||
if (operandType != null &&
|
||||
!TypeConversionUtil.areTypesConvertible(operandType, castType) &&
|
||||
PsiUtil.resolveClassInType(operandType) != null) {
|
||||
throw new EvaluateRuntimeException(
|
||||
new EvaluateException(JavaErrorMessages.message("inconvertible.type.cast", JavaHighlightUtil.formatType(operandType), JavaHighlightUtil
|
||||
.formatType(castType)))
|
||||
);
|
||||
}
|
||||
|
||||
final boolean shouldPerformBoxingConversion = castType != null && operandType != null && TypeConversionUtil.boxingConversionApplicable(castType, operandType);
|
||||
boolean shouldPerformBoxingConversion = operandType != null && TypeConversionUtil.boxingConversionApplicable(castType, operandType);
|
||||
final boolean castingToPrimitive = castType instanceof PsiPrimitiveType;
|
||||
if (shouldPerformBoxingConversion && castingToPrimitive) {
|
||||
operandEvaluator = new UnBoxingEvaluator(operandEvaluator);
|
||||
@@ -1154,14 +1163,14 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
|
||||
PsiArrayInitializerExpression arrayInitializer = expression.getArrayInitializer();
|
||||
if (arrayInitializer != null) {
|
||||
if (dimensionEvaluator != null) { // initializer already exists
|
||||
throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", expression.getText()));
|
||||
throwExpressionInvalid(expression);
|
||||
}
|
||||
arrayInitializer.accept(this);
|
||||
if (myResult != null) {
|
||||
initializerEvaluator = handleUnaryNumericPromotion(arrayInitializer.getType(), myResult);
|
||||
}
|
||||
else {
|
||||
throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", arrayInitializer.getText()));
|
||||
throwExpressionInvalid(arrayInitializer);
|
||||
}
|
||||
/*
|
||||
PsiExpression[] initializers = arrayInitializer.getInitializers();
|
||||
@@ -1179,7 +1188,7 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
|
||||
*/
|
||||
}
|
||||
if (dimensionEvaluator == null && initializerEvaluator == null) {
|
||||
throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", expression.getText()));
|
||||
throwExpressionInvalid(expression);
|
||||
}
|
||||
myResult = new NewArrayInstanceEvaluator(
|
||||
new TypeEvaluator(JVMNameUtil.getJVMQualifiedName(expressionPsiType)),
|
||||
@@ -1194,7 +1203,7 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
|
||||
}
|
||||
PsiExpressionList argumentList = expression.getArgumentList();
|
||||
if (argumentList == null) {
|
||||
throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", expression.getText())); return;
|
||||
throwExpressionInvalid(expression);
|
||||
}
|
||||
final PsiExpression[] argExpressions = argumentList.getExpressions();
|
||||
final JavaResolveResult constructorResolveResult = expression.resolveMethodGenerics();
|
||||
@@ -1212,7 +1221,7 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
|
||||
argumentEvaluators[idx] = new DisableGC(myResult);
|
||||
}
|
||||
else {
|
||||
throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", argExpression.getText()));
|
||||
throwExpressionInvalid(argExpression);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1265,7 +1274,7 @@ public class EvaluatorBuilderImpl implements EvaluatorBuilder {
|
||||
evaluators[idx] = new DisableGC(coerced);
|
||||
}
|
||||
else {
|
||||
throwEvaluateException(DebuggerBundle.message("evaluation.error.invalid.expression", initializer.getText()));
|
||||
throwExpressionInvalid(initializer);
|
||||
}
|
||||
}
|
||||
myResult = new ArrayInitializerEvaluator(evaluators);
|
||||
|
||||
+11
-8
@@ -26,12 +26,11 @@ import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.PopupStep;
|
||||
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.search.PsiElementProcessor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
public abstract class AbstractAddToTestsPatternAction<T extends ModuleBasedConfiguration> extends AnAction {
|
||||
@NotNull protected abstract AbstractPatternBasedConfigurationProducer<T> getPatternBasedProducer();
|
||||
@@ -46,7 +45,9 @@ public abstract class AbstractAddToTestsPatternAction<T extends ModuleBasedConfi
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final DataContext dataContext = e.getDataContext();
|
||||
final PsiElement[] psiElements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(dataContext);
|
||||
final Set<PsiElement> classes = getPatternBasedProducer().collectTestMembers(psiElements, true);
|
||||
final LinkedHashSet<PsiElement> classes = new LinkedHashSet<PsiElement>();
|
||||
PsiElementProcessor.CollectElements<PsiElement> processor = new PsiElementProcessor.CollectElements<PsiElement>(classes);
|
||||
getPatternBasedProducer().collectTestMembers(psiElements, true, true, processor);
|
||||
|
||||
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
|
||||
final List<T> patternConfigurations = collectPatternConfigurations(classes, project);
|
||||
@@ -86,11 +87,13 @@ public abstract class AbstractAddToTestsPatternAction<T extends ModuleBasedConfi
|
||||
final DataContext dataContext = e.getDataContext();
|
||||
final PsiElement[] psiElements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(dataContext);
|
||||
if (psiElements != null) {
|
||||
final Set<PsiElement> foundMembers = getPatternBasedProducer().collectTestMembers(psiElements, true);
|
||||
if (foundMembers.isEmpty()) return;
|
||||
PsiElementProcessor.CollectElementsWithLimit<PsiElement> processor = new PsiElementProcessor.CollectElementsWithLimit<PsiElement>(2);
|
||||
getPatternBasedProducer().collectTestMembers(psiElements, false, false, processor);
|
||||
Collection<PsiElement> collection = processor.getCollection();
|
||||
if (collection.isEmpty()) return;
|
||||
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
|
||||
if (project != null) {
|
||||
final List<T> foundConfigurations = collectPatternConfigurations(foundMembers, project);
|
||||
final List<T> foundConfigurations = collectPatternConfigurations(collection, project);
|
||||
if (!foundConfigurations.isEmpty()) {
|
||||
presentation.setVisible(true);
|
||||
if (foundConfigurations.size() == 1) {
|
||||
@@ -101,7 +104,7 @@ public abstract class AbstractAddToTestsPatternAction<T extends ModuleBasedConfi
|
||||
}
|
||||
}
|
||||
|
||||
private List<T> collectPatternConfigurations(Set<PsiElement> foundClasses, Project project) {
|
||||
private List<T> collectPatternConfigurations(Collection<PsiElement> foundClasses, Project project) {
|
||||
final List<RunConfiguration> configurations = RunManager.getInstance(project).getConfigurationsList(getConfigurationType());
|
||||
final List<T> foundConfigurations = new ArrayList<T>();
|
||||
for (RunConfiguration configuration : configurations) {
|
||||
|
||||
+82
-46
@@ -26,10 +26,12 @@ import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.PsiElementProcessor;
|
||||
import com.intellij.psi.util.ClassUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -55,18 +57,27 @@ public abstract class AbstractPatternBasedConfigurationProducer<T extends Module
|
||||
}
|
||||
|
||||
public boolean isMultipleElementsSelected(ConfigurationContext context) {
|
||||
if (TestsUIUtil.isMultipleSelectionImpossible(context.getDataContext())) return false;
|
||||
final DataContext dataContext = context.getDataContext();
|
||||
if (TestsUIUtil.isMultipleSelectionImpossible(dataContext)) return false;
|
||||
final LinkedHashSet<String> classes = new LinkedHashSet<String>();
|
||||
final PsiElement[] elements = collectPatternElements(context, classes);
|
||||
if (elements != null && collectTestMembers(elements, false).size() > 1) {
|
||||
return true;
|
||||
final PsiElementProcessor.CollectElementsWithLimit<PsiElement> processor = new PsiElementProcessor.CollectElementsWithLimit<PsiElement>(2);
|
||||
final PsiElement[] locationElements = collectLocationElements(classes, dataContext);
|
||||
if (locationElements != null) {
|
||||
collectTestMembers(locationElements, false, false, processor);
|
||||
}
|
||||
return false;
|
||||
else {
|
||||
collectContextElements(dataContext, false, false, classes, processor);
|
||||
}
|
||||
return processor.getCollection().size() > 1;
|
||||
}
|
||||
|
||||
public boolean isConfiguredFromContext(ConfigurationContext context, Set<String> patterns) {
|
||||
final LinkedHashSet<String> classes = new LinkedHashSet<String>();
|
||||
collectPatternElements(context, classes);
|
||||
final DataContext dataContext = context.getDataContext();
|
||||
final PsiElement[] locationElements = collectLocationElements(classes, dataContext);
|
||||
if (locationElements == null) {
|
||||
collectContextElements(dataContext, true, false, classes, new PsiElementProcessor.CollectElements<PsiElement>());
|
||||
}
|
||||
if (Comparing.equal(classes, patterns)) {
|
||||
return true;
|
||||
}
|
||||
@@ -74,43 +85,91 @@ public abstract class AbstractPatternBasedConfigurationProducer<T extends Module
|
||||
}
|
||||
|
||||
public PsiElement checkPatterns(ConfigurationContext context, LinkedHashSet<String> classes) {
|
||||
PsiElement[] elements = collectPatternElements(context, classes);
|
||||
if (elements == null || collectTestMembers(elements, false).size() <= 1) {
|
||||
PsiElement[] result;
|
||||
final DataContext dataContext = context.getDataContext();
|
||||
final PsiElement[] locationElements = collectLocationElements(classes, dataContext);
|
||||
PsiElementProcessor.CollectElements<PsiElement> processor = new PsiElementProcessor.CollectElements<PsiElement>();
|
||||
if (locationElements != null) {
|
||||
collectTestMembers(locationElements, false, true, processor);
|
||||
result = processor.toArray();
|
||||
}
|
||||
else if (collectContextElements(dataContext, true, true, classes, processor)) {
|
||||
result = processor.toArray();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
return elements[0];
|
||||
if (result.length <= 1) {
|
||||
return null;
|
||||
}
|
||||
return result[0];
|
||||
}
|
||||
|
||||
public Set<PsiElement> collectTestMembers(PsiElement[] psiElements, boolean checkAbstract) {
|
||||
final Set<PsiElement> foundMembers = new LinkedHashSet<PsiElement>();
|
||||
public void collectTestMembers(PsiElement[] psiElements,
|
||||
boolean checkAbstract,
|
||||
boolean checkIsTest,
|
||||
PsiElementProcessor.CollectElements<PsiElement> collectingProcessor) {
|
||||
for (PsiElement psiElement : psiElements) {
|
||||
if (psiElement instanceof PsiClassOwner) {
|
||||
final PsiClass[] classes = ((PsiClassOwner)psiElement).getClasses();
|
||||
for (PsiClass aClass : classes) {
|
||||
if (isTestClass(aClass)) {
|
||||
foundMembers.add(aClass);
|
||||
if ((!checkIsTest || isTestClass(aClass)) && !collectingProcessor.execute(aClass)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (psiElement instanceof PsiClass) {
|
||||
if (isTestClass((PsiClass)psiElement)) {
|
||||
foundMembers.add(psiElement);
|
||||
if ((!checkIsTest || isTestClass((PsiClass)psiElement)) && !collectingProcessor.execute(psiElement)) {
|
||||
return;
|
||||
}
|
||||
} else if (psiElement instanceof PsiMethod) {
|
||||
if (isTestMethod(checkAbstract, psiElement)) {
|
||||
foundMembers.add(psiElement);
|
||||
if ((!checkIsTest || isTestMethod(checkAbstract, psiElement)) && !collectingProcessor.execute(psiElement)) {
|
||||
return;
|
||||
}
|
||||
} else if (psiElement instanceof PsiDirectory) {
|
||||
final PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage((PsiDirectory)psiElement);
|
||||
if (aPackage != null) {
|
||||
foundMembers.add(aPackage);
|
||||
if (aPackage != null && !collectingProcessor.execute(aPackage)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
return foundMembers;
|
||||
}
|
||||
|
||||
private PsiElement[] collectPatternElements(ConfigurationContext context, LinkedHashSet<String> classes) {
|
||||
final DataContext dataContext = context.getDataContext();
|
||||
|
||||
private boolean collectContextElements(DataContext dataContext,
|
||||
boolean checkAbstract,
|
||||
boolean checkIsTest,
|
||||
LinkedHashSet<String> classes,
|
||||
PsiElementProcessor.CollectElements<PsiElement> processor) {
|
||||
PsiElement[] elements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(dataContext);
|
||||
if (elements != null) {
|
||||
collectTestMembers(elements, checkAbstract, checkIsTest, processor);
|
||||
for (PsiElement psiClass : processor.getCollection()) {
|
||||
classes.add(getQName(psiClass));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
final VirtualFile[] files = CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext);
|
||||
if (files != null) {
|
||||
Project project = CommonDataKeys.PROJECT.getData(dataContext);
|
||||
if (project != null) {
|
||||
final PsiManager psiManager = PsiManager.getInstance(project);
|
||||
for (VirtualFile file : files) {
|
||||
final PsiFile psiFile = psiManager.findFile(file);
|
||||
if (psiFile instanceof PsiClassOwner) {
|
||||
collectTestMembers(((PsiClassOwner)psiFile).getClasses(), checkAbstract, checkIsTest, processor);
|
||||
for (PsiElement psiMember : processor.getCollection()) {
|
||||
classes.add(((PsiClass)psiMember).getQualifiedName());
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static PsiElement[] collectLocationElements(LinkedHashSet<String> classes, DataContext dataContext) {
|
||||
final Location<?>[] locations = Location.DATA_KEYS.getData(dataContext);
|
||||
if (locations != null) {
|
||||
List<PsiElement> elements = new ArrayList<PsiElement>();
|
||||
@@ -121,29 +180,6 @@ public abstract class AbstractPatternBasedConfigurationProducer<T extends Module
|
||||
}
|
||||
return elements.toArray(new PsiElement[elements.size()]);
|
||||
}
|
||||
PsiElement[] elements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(dataContext);
|
||||
if (elements != null) {
|
||||
for (PsiElement psiClass : collectTestMembers(elements, true)) {
|
||||
classes.add(getQName(psiClass));
|
||||
}
|
||||
return elements;
|
||||
} else {
|
||||
final VirtualFile[] files = CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext);
|
||||
if (files != null) {
|
||||
final List<PsiFile> psiFiles = new ArrayList<PsiFile>();
|
||||
final PsiManager psiManager = PsiManager.getInstance(context.getProject());
|
||||
for (VirtualFile file : files) {
|
||||
final PsiFile psiFile = psiManager.findFile(file);
|
||||
if (psiFile instanceof PsiClassOwner) {
|
||||
for (PsiElement psiMember : collectTestMembers(((PsiClassOwner)psiFile).getClasses(), true)) {
|
||||
classes.add(((PsiClass)psiMember).getQualifiedName());
|
||||
}
|
||||
psiFiles.add(psiFile);
|
||||
}
|
||||
}
|
||||
return psiFiles.toArray(new PsiElement[psiFiles.size()]);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+16
@@ -767,4 +767,20 @@ public class SmartPsiElementPointersTest extends CodeInsightTestCase {
|
||||
|
||||
assertNotNull(pointer.getElement());
|
||||
}
|
||||
|
||||
public void testPointerToEmptyElement() {
|
||||
PsiFile file = configureByText(JavaFileType.INSTANCE, "class Foo {\n" +
|
||||
" Test<String> test = new Test<>();\n" +
|
||||
"}");
|
||||
PsiJavaCodeReferenceElement ref = PsiTreeUtil.findElementOfClassAtOffset(file, file.getText().indexOf("<>"), PsiJavaCodeReferenceElement.class, false);
|
||||
SmartPointerEx pointer = (SmartPointerEx)SmartPointerManager.getInstance(myProject).createSmartPsiElementPointer(
|
||||
ref.getParameterList().getTypeParameterElements()[0]);
|
||||
ref = null;
|
||||
|
||||
PlatformTestUtil.tryGcSoftlyReachableObjects();
|
||||
assertNull(pointer.getCachedElement());
|
||||
|
||||
assertInstanceOf(pointer.getElement(), PsiTypeElement.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -60,13 +60,9 @@ public abstract class InspectionToolWrapper<T extends InspectionProfileEntry, E
|
||||
protected InspectionToolWrapper(@NotNull InspectionToolWrapper<T, E> other) {
|
||||
myEP = other.myEP;
|
||||
// we need to create a copy for buffering
|
||||
if (myEP != null) {
|
||||
if (other.myTool != null) {
|
||||
//noinspection unchecked
|
||||
myTool = (T)myEP.instantiateTool();
|
||||
}
|
||||
else if (other.myTool != null) {
|
||||
//noinspection unchecked
|
||||
myTool = (T)InspectionToolsRegistrarCore.instantiateTool(other.myTool.getClass());
|
||||
myTool = myEP != null ? (T)myEP.instantiateTool() : (T)InspectionToolsRegistrarCore.instantiateTool(other.myTool.getClass());
|
||||
}
|
||||
else {
|
||||
myTool = null;
|
||||
|
||||
@@ -70,7 +70,7 @@ public class SyntaxTraverser<T> extends FilteredTraverserBase<T, SyntaxTraverser
|
||||
@NotNull
|
||||
public static SyntaxTraverser<LighterASTNode> lightTraverser(@NotNull PsiBuilder builder) {
|
||||
LighterASTApi api = new LighterASTApi(builder);
|
||||
return new SyntaxTraverser<LighterASTNode>(api, Meta.<LighterASTNode>empty().withRoots(JBIterable.of(api.flyweightStructure.getRoot())));
|
||||
return new SyntaxTraverser<LighterASTNode>(api, Meta.<LighterASTNode>empty().withRoots(JBIterable.of(api.getStructure().getRoot())));
|
||||
}
|
||||
|
||||
public final Api<T> api;
|
||||
@@ -363,16 +363,14 @@ public class SyntaxTraverser<T> extends FilteredTraverserBase<T, SyntaxTraverser
|
||||
}
|
||||
|
||||
private abstract static class FlyweightApi<T> extends Api<T> {
|
||||
final FlyweightCapableTreeStructure<T> flyweightStructure;
|
||||
|
||||
public FlyweightApi(@NotNull FlyweightCapableTreeStructure<T> structure) {
|
||||
flyweightStructure = structure;
|
||||
}
|
||||
@NotNull
|
||||
abstract FlyweightCapableTreeStructure<T> getStructure();
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public T parent(@NotNull T node) {
|
||||
return flyweightStructure.getParent(node);
|
||||
return getStructure().getParent(node);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -381,8 +379,9 @@ public class SyntaxTraverser<T> extends FilteredTraverserBase<T, SyntaxTraverser
|
||||
return new JBIterable<T>() {
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
FlyweightCapableTreeStructure<T> structure = getStructure();
|
||||
Ref<T[]> ref = Ref.create();
|
||||
int count = flyweightStructure.getChildren(flyweightStructure.prepareForGetChildren(node), ref);
|
||||
int count = structure.getChildren(structure.prepareForGetChildren(node), ref);
|
||||
if (count == 0) return ContainerUtil.emptyIterator();
|
||||
T[] array = ref.get();
|
||||
LinkedList<T> list = ContainerUtil.newLinkedList();
|
||||
@@ -399,7 +398,7 @@ public class SyntaxTraverser<T> extends FilteredTraverserBase<T, SyntaxTraverser
|
||||
array[i] = null; // do not dispose meaningful TokenNodes
|
||||
list.addLast(child);
|
||||
}
|
||||
flyweightStructure.disposeChildren(array, count);
|
||||
structure.disposeChildren(array, count);
|
||||
return list.iterator();
|
||||
}
|
||||
};
|
||||
@@ -408,12 +407,24 @@ public class SyntaxTraverser<T> extends FilteredTraverserBase<T, SyntaxTraverser
|
||||
|
||||
private static class LighterASTApi extends FlyweightApi<LighterASTNode> {
|
||||
private final PsiBuilder builder;
|
||||
private final ThreadLocalCachedValue<FlyweightCapableTreeStructure<LighterASTNode>> structure =
|
||||
new ThreadLocalCachedValue<FlyweightCapableTreeStructure<LighterASTNode>>() {
|
||||
@Override
|
||||
protected FlyweightCapableTreeStructure<LighterASTNode> create() {
|
||||
return builder.getLightTree();
|
||||
}
|
||||
};
|
||||
|
||||
public LighterASTApi(PsiBuilder builder) {
|
||||
super(builder.getLightTree());
|
||||
public LighterASTApi(final PsiBuilder builder) {
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
FlyweightCapableTreeStructure<LighterASTNode> getStructure() {
|
||||
return structure.getValue();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public IElementType typeOf(@NotNull LighterASTNode node) {
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiDocumentManagerBase;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -133,6 +134,18 @@ public class SelfElementInfo extends SmartPointerElementInfo {
|
||||
PsiElement anchor = file.getViewProvider().findElementAt(syncStartOffset, language);
|
||||
if (anchor == null) return null;
|
||||
|
||||
PsiElement result = findParent(syncStartOffset, syncEndOffset, type, anchor);
|
||||
if (result == null && syncEndOffset == syncStartOffset && anchor.getTextRange().getStartOffset() == syncEndOffset) {
|
||||
anchor = PsiTreeUtil.prevLeaf(anchor, false);
|
||||
if (anchor != null) {
|
||||
result = findParent(syncStartOffset, syncEndOffset, type, anchor);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement findParent(int syncStartOffset, int syncEndOffset, @NotNull Class type, PsiElement anchor) {
|
||||
TextRange range = anchor.getTextRange();
|
||||
|
||||
if (range.getStartOffset() != syncStartOffset) return null;
|
||||
|
||||
+3
-47
@@ -16,23 +16,20 @@
|
||||
package com.intellij.codeInsight.intention.impl;
|
||||
|
||||
import com.intellij.codeInsight.editorActions.CopyPastePreProcessor;
|
||||
import com.intellij.codeInsight.lookup.LookupManager;
|
||||
import com.intellij.codeInsight.template.TemplateManager;
|
||||
import com.intellij.injected.editor.DocumentWindow;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.CommonShortcuts;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.undo.UndoManager;
|
||||
import com.intellij.openapi.editor.*;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
|
||||
import com.intellij.openapi.editor.actionSystem.ReadonlyFragmentModificationHandler;
|
||||
import com.intellij.openapi.editor.event.DocumentAdapter;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.editor.event.EditorFactoryAdapter;
|
||||
import com.intellij.openapi.editor.event.EditorFactoryEvent;
|
||||
import com.intellij.openapi.editor.ex.DocumentEx;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileEditor.FileEditor;
|
||||
@@ -41,7 +38,6 @@ import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
|
||||
import com.intellij.openapi.fileEditor.impl.EditorWindow;
|
||||
import com.intellij.openapi.fileEditor.impl.EditorWithProviderComposite;
|
||||
import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.Balloon;
|
||||
@@ -138,46 +134,6 @@ public class QuickEditHandler extends DocumentAdapter implements Disposable {
|
||||
myOrigCreationStamp = myOrigDocument.getModificationStamp(); // store creation stamp for UNDO tracking
|
||||
myOrigDocument.addDocumentListener(this, this);
|
||||
myNewDocument.addDocumentListener(this, this);
|
||||
EditorFactory editorFactory = ObjectUtils.assertNotNull(EditorFactory.getInstance());
|
||||
// not FileEditorManager listener because of RegExp checker and alike
|
||||
editorFactory.addEditorFactoryListener(new EditorFactoryAdapter() {
|
||||
|
||||
int myEditorCount;
|
||||
|
||||
@Override
|
||||
public void editorCreated(@NotNull EditorFactoryEvent event) {
|
||||
if (event.getEditor().getDocument() != myNewDocument) return;
|
||||
myEditorCount ++;
|
||||
final EditorActionHandler editorEscape = EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_ESCAPE);
|
||||
if (!myAction.isShowInBalloon()) {
|
||||
new AnAction() {
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
Editor editor = CommonDataKeys.EDITOR.getData(e.getDataContext());
|
||||
e.getPresentation().setEnabled(
|
||||
editor != null && LookupManager.getActiveLookup(editor) == null &&
|
||||
TemplateManager.getInstance(myProject).getActiveTemplate(editor) == null &&
|
||||
(editorEscape == null || !editorEscape.isEnabled(editor, e.getDataContext())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
closeEditor();
|
||||
}
|
||||
}.registerCustomShortcutSet(CommonShortcuts.ESCAPE, event.getEditor().getContentComponent());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void editorReleased(@NotNull EditorFactoryEvent event) {
|
||||
if (event.getEditor().getDocument() != myNewDocument) return;
|
||||
if (-- myEditorCount > 0) return;
|
||||
|
||||
if (Boolean.TRUE.equals(myNewVirtualFile.getUserData(FileEditorManagerImpl.CLOSING_TO_REOPEN))) return;
|
||||
|
||||
Disposer.dispose(QuickEditHandler.this);
|
||||
}
|
||||
}, this);
|
||||
|
||||
if ("JAVA".equals(firstShred.getHost().getLanguage().getID())) {
|
||||
PsiLanguageInjectionHost.Shred lastShred = ContainerUtil.getLastItem(shreds);
|
||||
|
||||
@@ -17,12 +17,15 @@ package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.application.options.CodeStyleSchemesConfigurable;
|
||||
import com.intellij.ide.DataManager;
|
||||
import com.intellij.injected.editor.VirtualFileWindow;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.options.ex.Settings;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.ui.HyperlinkLabel;
|
||||
@@ -77,8 +80,11 @@ public class LongLineInspection extends LocalInspectionTool {
|
||||
public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
|
||||
final Project project = manager.getProject();
|
||||
final int codeStyleRightMargin = CodeStyleSettingsManager.getSettings(project).getRightMargin(file.getLanguage());
|
||||
final PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(project);
|
||||
final Document document = psiDocumentManager.getDocument(file);
|
||||
final VirtualFile vFile = file.getVirtualFile();
|
||||
if (vFile instanceof VirtualFileWindow) {
|
||||
return null;
|
||||
}
|
||||
final Document document = FileDocumentManager.getInstance().getDocument(vFile);
|
||||
if (document == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,9 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.event.*;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.MouseWheelEvent;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
@@ -524,29 +526,25 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
|
||||
myEditor = createConsoleEditor();
|
||||
registerConsoleEditorActions();
|
||||
myEditor.getScrollPane().setBorder(null);
|
||||
myEditor.getScrollPane().addMouseWheelListener(new MouseWheelListener() {
|
||||
MouseAdapter mouseListener = new MouseAdapter() {
|
||||
@Override
|
||||
public void mousePressed(MouseEvent e) {
|
||||
updateStickToEndState(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent e) {
|
||||
updateStickToEndState(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||
if (e.getWheelRotation() < 0) {
|
||||
myCancelStickToEnd = true;
|
||||
}
|
||||
updateStickToEndState(false);
|
||||
}
|
||||
});
|
||||
myEditor.getScrollPane().getVerticalScrollBar().addAdjustmentListener(new AdjustmentListener() {
|
||||
@Override
|
||||
public void adjustmentValueChanged(AdjustmentEvent e) {
|
||||
Adjustable scrollBar = e.getAdjustable();
|
||||
boolean vscrollAtBottom = scrollBar.getValue() == scrollBar.getMaximum() - scrollBar.getVisibleAmount();
|
||||
|
||||
if (e.getValueIsAdjusting()) {
|
||||
myCancelStickToEnd = !vscrollAtBottom;
|
||||
}
|
||||
|
||||
if (vscrollAtBottom && !isStickingToEnd()) {
|
||||
scrollToEnd();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
myEditor.getScrollPane().addMouseWheelListener(mouseListener);
|
||||
myEditor.getScrollPane().getVerticalScrollBar().addMouseListener(mouseListener);
|
||||
myEditor.getScrollPane().getVerticalScrollBar().addMouseMotionListener(mouseListener);
|
||||
myHyperlinks = new EditorHyperlinkSupport(myEditor, myProject);
|
||||
myEditor.getScrollingModel().addVisibleAreaListener(new VisibleAreaListener() {
|
||||
@Override
|
||||
@@ -565,6 +563,22 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
|
||||
});
|
||||
}
|
||||
|
||||
private void updateStickToEndState(boolean useImmediatePosition) {
|
||||
if (myEditor == null) return;
|
||||
|
||||
JScrollBar scrollBar = myEditor.getScrollPane().getVerticalScrollBar();
|
||||
int scrollBarPosition = useImmediatePosition ? scrollBar.getValue() :
|
||||
myEditor.getScrollingModel().getVisibleAreaOnScrollingFinished().y;
|
||||
boolean vscrollAtBottom = scrollBarPosition == scrollBar.getMaximum() - scrollBar.getVisibleAmount();
|
||||
boolean stickingToEnd = isStickingToEnd();
|
||||
|
||||
if (!vscrollAtBottom && stickingToEnd) {
|
||||
myCancelStickToEnd = true;
|
||||
} else if (vscrollAtBottom && !stickingToEnd) {
|
||||
scrollToEnd();
|
||||
}
|
||||
}
|
||||
|
||||
protected JComponent createCenterComponent() {
|
||||
return myEditor.getComponent();
|
||||
}
|
||||
|
||||
+1
-1
@@ -196,7 +196,7 @@ public class FileEncodingConfigurable implements SearchableConfigurable, Configu
|
||||
mySelectedCharsetForPropertiesFiles.set(encodingManager.getDefaultCharsetForPropertiesFiles(null));
|
||||
|
||||
mySelectedIdeCharset.set(EncodingManager.getInstance().getDefaultCharsetName().isEmpty() ? null : EncodingManager.getInstance().getDefaultCharset());
|
||||
mySelectedProjectCharset.set(EncodingProjectManager.getInstance(myProject).getDefaultCharsetName().isEmpty() ? null : EncodingProjectManager.getInstance(myProject).getDefaultCharset());
|
||||
mySelectedProjectCharset.set(encodingManager.getDefaultCharsetName().isEmpty() ? null : encodingManager.getDefaultCharset());
|
||||
myPropertiesEncodingAction.update(null);
|
||||
myIdeEncodingAction.update(null);
|
||||
myProjectEncodingAction.update(null);
|
||||
|
||||
+1
-1
@@ -117,7 +117,7 @@ public abstract class InspectionsFilter {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (myAvailableOnlyForAnalyze != isAvailableOnlyForAnalyze(tools)) {
|
||||
if (myAvailableOnlyForAnalyze && !isAvailableOnlyForAnalyze(tools)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ public class LongLineInspectionTest extends LightPlatformCodeInsightFixtureTestC
|
||||
doTest("java");
|
||||
}
|
||||
|
||||
public void testLongLine() {
|
||||
public void _testLongLine() {
|
||||
doTest("java");
|
||||
}
|
||||
|
||||
|
||||
@@ -121,9 +121,9 @@ public class IdeEventQueue extends EventQueue {
|
||||
*/
|
||||
private int myEventCount;
|
||||
|
||||
private boolean myIsInInputEvent = false;
|
||||
private boolean myIsInInputEvent;
|
||||
|
||||
private AWTEvent myCurrentEvent = null;
|
||||
private AWTEvent myCurrentEvent;
|
||||
|
||||
private long myLastActiveTime;
|
||||
|
||||
@@ -156,7 +156,7 @@ public class IdeEventQueue extends EventQueue {
|
||||
keyboardFocusManager.addPropertyChangeListener("permanentFocusOwner", new PropertyChangeListener() {
|
||||
|
||||
@Override
|
||||
public void propertyChange(final PropertyChangeEvent e) {
|
||||
public void propertyChange(@NotNull final PropertyChangeEvent e) {
|
||||
final Application application = ApplicationManager.getApplication();
|
||||
if (application == null) {
|
||||
// We can get focus event before application is initialized
|
||||
@@ -324,8 +324,8 @@ public class IdeEventQueue extends EventQueue {
|
||||
|
||||
private static class InertialMouseRouter {
|
||||
private static final int MOUSE_WHEEL_RESTART_THRESHOLD = 50;
|
||||
private static Component wheelDestinationComponent = null;
|
||||
private static long lastMouseWheel = 0;
|
||||
private static Component wheelDestinationComponent;
|
||||
private static long lastMouseWheel;
|
||||
|
||||
private static AWTEvent changeSourceIfNeeded(AWTEvent awtEvent) {
|
||||
if (SystemInfo.isMac && Registry.is("ide.inertial.mouse.fix") && awtEvent instanceof MouseWheelEvent) {
|
||||
@@ -342,7 +342,7 @@ public class IdeEventQueue extends EventQueue {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean ourAppIsLoaded = false;
|
||||
private static boolean ourAppIsLoaded;
|
||||
|
||||
private static boolean appIsLoaded() {
|
||||
if (ourAppIsLoaded) return true;
|
||||
@@ -352,7 +352,7 @@ public class IdeEventQueue extends EventQueue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatchEvent(AWTEvent e) {
|
||||
public void dispatchEvent(@NotNull AWTEvent e) {
|
||||
if (!appIsLoaded()) {
|
||||
try {
|
||||
super.dispatchEvent(e);
|
||||
@@ -400,8 +400,8 @@ public class IdeEventQueue extends EventQueue {
|
||||
}
|
||||
}
|
||||
|
||||
private static int ctrlIsPressedCount = 0;
|
||||
private static boolean leftAltIsPressed = false;
|
||||
private static int ctrlIsPressedCount;
|
||||
private static boolean leftAltIsPressed;
|
||||
//private static boolean altGrIsPressed = false;
|
||||
|
||||
private static AWTEvent fixNonEnglishKeyboardLayouts(AWTEvent e) {
|
||||
@@ -417,12 +417,12 @@ public class IdeEventQueue extends EventQueue {
|
||||
|
||||
if (ke.getID() == KeyEvent.KEY_PRESSED) {
|
||||
switch (ke.getKeyCode()) {
|
||||
case (KeyEvent.VK_CONTROL):
|
||||
case KeyEvent.VK_CONTROL:
|
||||
if ((ke.getModifiersEx() & (InputEvent.ALT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK)) != (InputEvent.ALT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK)) {
|
||||
ctrlIsPressedCount++;
|
||||
}
|
||||
break;
|
||||
case (KeyEvent.VK_ALT):
|
||||
case KeyEvent.VK_ALT:
|
||||
if (ke.getKeyLocation() == KeyEvent.KEY_LOCATION_LEFT) {
|
||||
if ((ke.getModifiersEx() & (InputEvent.ALT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK)) != (InputEvent.ALT_DOWN_MASK | InputEvent.CTRL_DOWN_MASK)) {
|
||||
leftAltIsPressed = true;
|
||||
@@ -433,10 +433,10 @@ public class IdeEventQueue extends EventQueue {
|
||||
}
|
||||
else if (ke.getID() == KeyEvent.KEY_RELEASED) {
|
||||
switch (ke.getKeyCode()) {
|
||||
case (KeyEvent.VK_CONTROL):
|
||||
case KeyEvent.VK_CONTROL:
|
||||
ctrlIsPressedCount--;
|
||||
break;
|
||||
case (KeyEvent.VK_ALT):
|
||||
case KeyEvent.VK_ALT:
|
||||
if (ke.getKeyLocation() == KeyEvent.KEY_LOCATION_LEFT) {
|
||||
leftAltIsPressed = false;
|
||||
}
|
||||
@@ -684,8 +684,8 @@ public class IdeEventQueue extends EventQueue {
|
||||
}
|
||||
}
|
||||
|
||||
private MouseEvent lastClickEvent = null;
|
||||
private long lastClickTime = 0L;
|
||||
private MouseEvent lastClickEvent;
|
||||
private long lastClickTime;
|
||||
|
||||
private void setLastClickEvent(@Nullable MouseEvent event) {
|
||||
lastClickEvent = event;
|
||||
@@ -1151,7 +1151,7 @@ public class IdeEventQueue extends EventQueue {
|
||||
|
||||
private final FrequentEventDetector myFrequentEventDetector = new FrequentEventDetector(1009, 100);
|
||||
@Override
|
||||
public void postEvent(AWTEvent theEvent) {
|
||||
public void postEvent(@NotNull AWTEvent theEvent) {
|
||||
myFrequentEventDetector.eventHappened();
|
||||
super.postEvent(theEvent);
|
||||
}
|
||||
|
||||
+21
-13
@@ -15,18 +15,20 @@
|
||||
*/
|
||||
package com.intellij.internal.statistic.updater;
|
||||
|
||||
import com.intellij.ide.AppLifecycleListener;
|
||||
import com.intellij.ide.FrameStateListener;
|
||||
import com.intellij.ide.FrameStateManager;
|
||||
import com.intellij.internal.statistic.StatisticsUploadAssistant;
|
||||
import com.intellij.internal.statistic.connect.StatisticsService;
|
||||
import com.intellij.internal.statistic.connect.StatisticsServiceEP;
|
||||
import com.intellij.notification.NotificationDisplayType;
|
||||
import com.intellij.notification.NotificationsConfiguration;
|
||||
import com.intellij.notification.impl.NotificationsConfigurationImpl;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.ApplicationComponent;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.openapi.wm.ex.WindowManagerEx;
|
||||
import com.intellij.openapi.wm.impl.IdeFrameImpl;
|
||||
import com.intellij.util.Alarm;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -40,7 +42,9 @@ public class SendStatisticsComponent implements ApplicationComponent {
|
||||
|
||||
private final Alarm myAlarm;
|
||||
|
||||
public SendStatisticsComponent() {
|
||||
private final FrameStateManager myFrameStateManager;
|
||||
|
||||
public SendStatisticsComponent(@NotNull FrameStateManager frameStateManager) {
|
||||
myAlarm = new Alarm(Alarm.ThreadToUse.POOLED_THREAD, ApplicationManager.getApplication());
|
||||
|
||||
NotificationsConfigurationImpl.remove("SendUsagesStatistics");
|
||||
@@ -48,22 +52,26 @@ public class SendStatisticsComponent implements ApplicationComponent {
|
||||
StatisticsNotificationManager.GROUP_DISPLAY_ID,
|
||||
NotificationDisplayType.STICKY_BALLOON,
|
||||
false);
|
||||
|
||||
myFrameStateManager = frameStateManager;
|
||||
}
|
||||
|
||||
private void runStatisticsService() {
|
||||
final StatisticsService statisticsService = StatisticsUploadAssistant.getStatisticsService();
|
||||
|
||||
if (StatisticsUploadAssistant.isShouldShowNotification()) {
|
||||
Application app = ApplicationManager.getApplication();
|
||||
app.getMessageBus().connect(app).subscribe(AppLifecycleListener.TOPIC, new AppLifecycleListener.Adapter() {
|
||||
myFrameStateManager.addListener(new FrameStateListener.Adapter() {
|
||||
@Override
|
||||
public void appFrameCreated(String[] commandLineArgs, @NotNull Ref<Boolean> willOpenProject) {
|
||||
myAlarm.addRequest(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
StatisticsNotificationManager.showNotification(statisticsService);
|
||||
}
|
||||
}, 30 * 1000);
|
||||
public void onFrameActivated() {
|
||||
if (((WindowManagerEx)WindowManager.getInstance()).getMostRecentFocusedWindow() instanceof IdeFrameImpl) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
StatisticsNotificationManager.showNotification(statisticsService);
|
||||
}
|
||||
});
|
||||
myFrameStateManager.removeListener(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -58,15 +58,14 @@ class ProgressDialog implements Disposable {
|
||||
double fraction = myProgressWindow.getFraction();
|
||||
String text2 = myProgressWindow.getText2();
|
||||
|
||||
myTextLabel.setText(text != null && !text.isEmpty() ? text : " ");
|
||||
|
||||
if (myProgressBar.isShowing()) {
|
||||
final int perc = (int)(fraction * 100);
|
||||
myProgressBar.setIndeterminate(perc == 0 || myProgressWindow.isIndeterminate());
|
||||
myProgressBar.setValue(perc);
|
||||
}
|
||||
|
||||
myText2Label.setText(getTitle2Text(text2, myText2Label.getWidth()));
|
||||
myTextLabel.setText(fitTextToLabel(text, myTextLabel));
|
||||
myText2Label.setText(fitTextToLabel(text2, myText2Label));
|
||||
|
||||
myTitlePanel.setText(myProgressWindow.getTitle() != null && !myProgressWindow.getTitle().isEmpty() ? myProgressWindow.getTitle() : " ");
|
||||
|
||||
@@ -77,14 +76,14 @@ class ProgressDialog implements Disposable {
|
||||
}
|
||||
};
|
||||
|
||||
private String getTitle2Text(String fullText, int labelWidth) {
|
||||
@NotNull
|
||||
private static String fitTextToLabel(@Nullable String fullText, @NotNull JLabel label) {
|
||||
if (fullText == null || fullText.isEmpty()) return " ";
|
||||
while (myText2Label.getFontMetrics(myText2Label.getFont()).stringWidth(fullText) > labelWidth) {
|
||||
while (label.getFontMetrics(label.getFont()).stringWidth(fullText) > label.getWidth()) {
|
||||
int sep = fullText.indexOf(File.separatorChar, 4);
|
||||
if (sep < 0) return fullText;
|
||||
fullText = "..." + fullText.substring(sep);
|
||||
}
|
||||
|
||||
return fullText;
|
||||
}
|
||||
|
||||
|
||||
@@ -205,6 +205,7 @@ public class EncodingManagerImpl extends EncodingManager implements PersistentSt
|
||||
for (Project project : projects) {
|
||||
result.addAll(EncodingProjectManager.getInstance(project).getFavorites());
|
||||
}
|
||||
result.addAll(EncodingProjectManagerImpl.widelyKnownCharsets());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+8
-4
@@ -85,7 +85,6 @@ public class EncodingProjectManagerImpl extends EncodingProjectManager implement
|
||||
});
|
||||
}
|
||||
|
||||
//null key means project
|
||||
private final Map<VirtualFile, Charset> myMapping = ContainerUtil.newConcurrentMap();
|
||||
private volatile Charset myProjectCharset;
|
||||
|
||||
@@ -96,7 +95,7 @@ public class EncodingProjectManagerImpl extends EncodingProjectManager implement
|
||||
List<VirtualFile> files = new ArrayList<VirtualFile>(myMapping.keySet());
|
||||
ContainerUtil.quickSort(files, new Comparator<VirtualFile>() {
|
||||
@Override
|
||||
public int compare(final VirtualFile o1, final VirtualFile o2) {
|
||||
public int compare(@NotNull final VirtualFile o1, @NotNull final VirtualFile o2) {
|
||||
return o1.getPath().compareTo(o2.getPath());
|
||||
}
|
||||
});
|
||||
@@ -235,9 +234,15 @@ public class EncodingProjectManagerImpl extends EncodingProjectManager implement
|
||||
@Override
|
||||
@NotNull
|
||||
public Collection<Charset> getFavorites() {
|
||||
Set<Charset> result = new HashSet<Charset>();
|
||||
Set<Charset> result = widelyKnownCharsets();
|
||||
result.addAll(myMapping.values());
|
||||
result.add(getDefaultCharset());
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static Set<Charset> widelyKnownCharsets() {
|
||||
Set<Charset> result = new HashSet<Charset>();
|
||||
result.add(CharsetToolkit.UTF8_CHARSET);
|
||||
result.add(CharsetToolkit.getDefaultSystemCharset());
|
||||
result.add(CharsetToolkit.UTF_16_CHARSET);
|
||||
@@ -245,7 +250,6 @@ public class EncodingProjectManagerImpl extends EncodingProjectManager implement
|
||||
result.add(CharsetToolkit.forName("US-ASCII"));
|
||||
result.add(EncodingManager.getInstance().getDefaultCharset());
|
||||
result.add(EncodingManager.getInstance().getDefaultCharsetForPropertiesFiles(null));
|
||||
|
||||
result.remove(null);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.openapi.vfs.newvfs.impl;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationAdapter;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.vfs.InvalidVirtualFileAccessException;
|
||||
import com.intellij.openapi.vfs.newvfs.persistent.FSRecords;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
@@ -73,6 +74,7 @@ import static com.intellij.util.ObjectUtils.assertNotNull;
|
||||
* @author peter
|
||||
*/
|
||||
public class VfsData {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.newvfs.impl.VfsData");
|
||||
private static final int SEGMENT_BITS = 9;
|
||||
private static final int SEGMENT_SIZE = 1 << SEGMENT_BITS;
|
||||
private static final int OFFSET_MASK = SEGMENT_SIZE - 1;
|
||||
@@ -223,6 +225,9 @@ public class VfsData {
|
||||
}
|
||||
|
||||
void setFlag(int id, int mask, boolean value) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Set flag " + Integer.toHexString(mask) + "=" + value + " for id=" + id);
|
||||
}
|
||||
assert (mask & ~ALL_FLAGS_MASK) == 0 : "Unexpected flag";
|
||||
int offset = getOffset(id) * 2 + 1;
|
||||
while (true) {
|
||||
|
||||
+1
-1
@@ -1061,7 +1061,7 @@ public class PersistentFSImpl extends PersistentFS implements ApplicationCompone
|
||||
else if (VirtualFile.PROP_WRITABLE.equals(propertyChangeEvent.getPropertyName())) {
|
||||
executeSetWritable(file, ((Boolean)newValue).booleanValue());
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("File " + file + " writable=" + file.isWritable());
|
||||
LOG.debug("File " + file + " writable=" + file.isWritable() + " id=" + getFileId(file));
|
||||
}
|
||||
}
|
||||
else if (VirtualFile.PROP_HIDDEN.equals(propertyChangeEvent.getPropertyName())) {
|
||||
|
||||
@@ -30,6 +30,8 @@ public interface RemoteSdkFactory<T extends RemoteSdkAdditionalData> {
|
||||
Sdk createRemoteSdk(@Nullable Project project, @NotNull T data, @Nullable String sdkName, Collection<Sdk> existingSdks)
|
||||
throws RemoteSdkException;
|
||||
|
||||
String generateSdkHomePath(@NotNull T data);
|
||||
|
||||
Sdk createUnfinished(T data, Collection<Sdk> existingSdks);
|
||||
|
||||
String getDefaultUnfinishedName();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This file contains list of broken plugins.
|
||||
// Each line contains plugin ID and list of versions that are broken.
|
||||
// If plugin name or version contains a space you can quote it like in command line.
|
||||
NodeJS 142.3224 142.2650 142.2492 142.2481 142.2064 141.1108 140.2045 140.1669 140.642 139.173 139.105 139.496 139.1 139.8 138.2196 138.2254 138.1684 138.1744 138.1879 138.2051 138.1367 138.1495 138.1189 138.1145 138.937 138.1013 138.921 138.447 138.172 138.317 138.21 138.35 138.96 138.85 136.1205 134.1276 134.1163 134.1145 134.1081 134.1039 134.985 134.680 134.31 134.307 134.262 134.198 134.125 136.1141
|
||||
NodeJS 142.4100 142.3224 142.2650 142.2492 142.2481 142.2064 141.1108 140.2045 140.1669 140.642 139.173 139.105 139.496 139.1 139.8 138.2196 138.2254 138.1684 138.1744 138.1879 138.2051 138.1367 138.1495 138.1189 138.1145 138.937 138.1013 138.921 138.447 138.172 138.317 138.21 138.35 138.96 138.85 136.1205 134.1276 134.1163 134.1145 134.1081 134.1039 134.985 134.680 134.31 134.307 134.262 134.198 134.125 136.1141
|
||||
com.jetbrains.php 140.2765 141.332 139.732 139.659 139.496 139.173 139.105 138.2502 138.2000.2262 138.1751 138.1806 138.1505 138.1161 138.826 136.1768 136.1672 134.1456 133.982 133.679 133.51 133.326 131.98 131.374 131.332 131.235 131.205 130.1639 130.1481 130.1176 129.91 129.814 129.672 129.362 127.67 127.100 126.334 123.66 122.875 121.62 121.390 121.215 121.12
|
||||
com.jetbrains.lang.ejs 131.17 131.12
|
||||
com.jetbrains.twig 133.51 130.1639
|
||||
|
||||
@@ -390,7 +390,7 @@ public class JobUtilTest extends PlatformTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testTasksIsDoneAfterCancelInTheMiddleOfTheExecutionReturnsFalseUntilFinished() throws ExecutionException, InterruptedException {
|
||||
public void testAfterCancelInTheMiddleOfTheExecutionTaskIsDoneReturnsFalseUntilFinished() throws ExecutionException, InterruptedException {
|
||||
Random random = new Random();
|
||||
for (int i=0; i<100; i++) {
|
||||
final AtomicBoolean finished = new AtomicBoolean();
|
||||
@@ -407,7 +407,7 @@ public class JobUtilTest extends PlatformTestCase {
|
||||
TimeoutUtil.sleep(random.nextInt(100));
|
||||
job.cancel();
|
||||
long start = System.currentTimeMillis();
|
||||
while (!finished.get() && (started.get() || System.currentTimeMillis() < start + 2000)) {
|
||||
while (!job.isDone() && (started.get() || System.currentTimeMillis() < start + 2000)) {
|
||||
boolean wasDone = job.isDone();
|
||||
boolean wasStarted = started.get();
|
||||
boolean wasFinished = finished.get();
|
||||
@@ -415,6 +415,10 @@ public class JobUtilTest extends PlatformTestCase {
|
||||
assertTrue(wasStarted+", "+wasDone, wasDone == !wasStarted);
|
||||
}
|
||||
// else no guarantees
|
||||
|
||||
if (wasDone) {
|
||||
assertTrue(wasFinished);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-2
@@ -14,7 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.testFramework.fixtures
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionPhase
|
||||
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl
|
||||
import com.intellij.codeInsight.editorActions.CompletionAutoPopupHandler
|
||||
@@ -22,6 +21,8 @@ import com.intellij.codeInsight.lookup.LookupManager
|
||||
import com.intellij.codeInsight.lookup.impl.LookupImpl
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.editor.ex.DocumentEx
|
||||
import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.testFramework.UsefulTestCase
|
||||
import com.intellij.util.ui.UIUtil
|
||||
@@ -54,7 +55,7 @@ class CompletionAutoPopupTester {
|
||||
waitPhase { !(it instanceof CompletionPhase.CommittingDocuments || it instanceof CompletionPhase.Synchronous || it instanceof CompletionPhase.BgCalculation) }
|
||||
}
|
||||
|
||||
private void waitPhase(Closure condition) {
|
||||
private static void waitPhase(Closure condition) {
|
||||
for (j in 1..1000) {
|
||||
def phase = null
|
||||
UsefulTestCase.edt { phase = CompletionServiceImpl.completionPhase }
|
||||
@@ -65,6 +66,16 @@ class CompletionAutoPopupTester {
|
||||
println "Free memory: " + Runtime.runtime.freeMemory() + " of " + Runtime.runtime.totalMemory() + "\n"
|
||||
UsefulTestCase.printThreadDump()
|
||||
println "\n\n----------------------------\n\n"
|
||||
if (SystemInfo.isLinux) {
|
||||
try {
|
||||
Process process = new ProcessBuilder().command(["top", "-b", "-n", "1"] as String[]).redirectErrorStream(true).start();
|
||||
println FileUtil.loadTextAndClose(process.getInputStream())
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
println "\n\n----------------------------\n\n"
|
||||
}
|
||||
Thread.sleep(10)
|
||||
}
|
||||
|
||||
@@ -78,7 +78,6 @@ public class GitCherryPicker extends VcsCherryPicker {
|
||||
private static final String CHERRY_PICK_HEAD_FILE = "CHERRY_PICK_HEAD";
|
||||
|
||||
private static final Logger LOG = Logger.getInstance(GitCherryPicker.class);
|
||||
private static final String NAME = "Cherry-Pick";
|
||||
|
||||
@NotNull private final Project myProject;
|
||||
@NotNull private final Git myGit;
|
||||
@@ -521,7 +520,7 @@ public class GitCherryPicker extends VcsCherryPicker {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getActionTitle() {
|
||||
return isAutoCommit() ? NAME : NAME + "...";
|
||||
return "Cherry-Pick";
|
||||
}
|
||||
|
||||
private boolean isAutoCommit() {
|
||||
|
||||
@@ -18,6 +18,7 @@ package git4idea.commands;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
@@ -149,6 +150,7 @@ public class GitImpl implements Git {
|
||||
handler.setUrl(url);
|
||||
handler.addParameters("--progress");
|
||||
handler.addParameters(url);
|
||||
handler.endOptions();
|
||||
handler.addParameters(clonedDirectoryName);
|
||||
addListeners(handler, listeners);
|
||||
return handler;
|
||||
@@ -604,7 +606,7 @@ public class GitImpl implements Git {
|
||||
GitLineHandler handler = handlerConstructor.compute();
|
||||
handler.addLineListener(new GitLineHandlerListener() {
|
||||
@Override public void onLineAvailable(String line, Key outputType) {
|
||||
if (isError(line)) {
|
||||
if (looksLikeError(line)) {
|
||||
errorOutput.add(line);
|
||||
} else {
|
||||
output.add(line);
|
||||
@@ -624,7 +626,7 @@ public class GitImpl implements Git {
|
||||
|
||||
handler.runInCurrentThread(null);
|
||||
authFailed = handler.hasHttpAuthFailed();
|
||||
success = !startFailed.get() && errorOutput.isEmpty() && (handler.isIgnoredErrorCode(exitCode.get()) || exitCode.get() == 0);
|
||||
success = !startFailed.get() && (handler.isIgnoredErrorCode(exitCode.get()) || exitCode.get() == 0);
|
||||
}
|
||||
while (authFailed && authAttempt++ < 2);
|
||||
return new GitCommandResult(success, exitCode.get(), errorOutput, output, null);
|
||||
@@ -668,21 +670,18 @@ public class GitImpl implements Git {
|
||||
return ObjectUtils.assertNotNull(compoundResult);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the line looks line an error message
|
||||
*/
|
||||
private static boolean isError(String text) {
|
||||
for (String indicator : ERROR_INDICATORS) {
|
||||
if (text.trim().toLowerCase().startsWith(indicator.toLowerCase())) {
|
||||
return true;
|
||||
private static boolean looksLikeError(@NotNull final String text) {
|
||||
return ContainerUtil.exists(ERROR_INDICATORS, new Condition<String>() {
|
||||
@Override
|
||||
public boolean value(@NotNull String indicator) {
|
||||
return StringUtil.startsWithIgnoreCase(text.trim(), indicator);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
// could be upper-cased, so should check case-insensitively
|
||||
public static final String[] ERROR_INDICATORS = {
|
||||
"error", "remote: error", "fatal",
|
||||
"error:", "remote: error", "fatal:",
|
||||
"Cannot", "Could not", "Interactive rebase already started", "refusing to pull", "cannot rebase:", "conflict",
|
||||
"unable"
|
||||
};
|
||||
|
||||
+35
-27
@@ -322,31 +322,16 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl<GrCodeRef
|
||||
case PACKAGE_FQ:
|
||||
String qName = PsiUtil.getQualifiedReferenceText(ref);
|
||||
LOG.assertTrue(qName != null, ref.getText());
|
||||
|
||||
JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject());
|
||||
if (kind == ReferenceKind.CLASS_OR_PACKAGE_FQ || kind == ReferenceKind.CLASS_FQ) {
|
||||
final PsiFile file = ref.getContainingFile();
|
||||
if (qName.indexOf('.') > 0 || file instanceof GroovyFile && ((GroovyFile)file).getPackageName().isEmpty()) {
|
||||
PsiClass aClass = facade.findClass(qName, ref.getResolveScope());
|
||||
if (aClass != null) {
|
||||
boolean isAccessible = PsiUtil.isAccessible(ref, aClass);
|
||||
return new GroovyResolveResult[]{new GroovyResolveResultImpl(aClass, isAccessible)};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (kind == ReferenceKind.CLASS_OR_PACKAGE_FQ || kind == ReferenceKind.PACKAGE_FQ) {
|
||||
PsiPackage aPackage = facade.findPackage(qName);
|
||||
if (aPackage != null) {
|
||||
return new GroovyResolveResult[]{new GroovyResolveResultImpl(aPackage, true)};
|
||||
}
|
||||
PsiElement element = resolveClassOrPackagePreferInner(ref, kind, qName, JavaPsiFacade.getInstance(manager.getProject()));
|
||||
if (element != null) {
|
||||
boolean accessible = !(element instanceof PsiClass) || PsiUtil.isAccessible(ref, (PsiClass)element);
|
||||
return new GroovyResolveResult[]{new GroovyResolveResultImpl(element, accessible)};
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CLASS: {
|
||||
EnumSet<ClassHint.ResolveKind> kinds = kind == ReferenceKind.CLASS
|
||||
? ClassHint.RESOLVE_KINDS_CLASS : ClassHint.RESOLVE_KINDS_CLASS_PACKAGE;
|
||||
EnumSet<ClassHint.ResolveKind> kinds = ClassHint.RESOLVE_KINDS_CLASS;
|
||||
ResolverProcessor processor = new ClassResolverProcessor(refName, ref, kinds);
|
||||
GrCodeReferenceElement qualifier = ref.getQualifier();
|
||||
if (qualifier != null) {
|
||||
@@ -365,13 +350,6 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl<GrCodeRef
|
||||
GroovyResolveResult[] candidates = processor.getCandidates();
|
||||
if (candidates.length > 0) return candidates;
|
||||
}
|
||||
|
||||
if (kind == ReferenceKind.CLASS_OR_PACKAGE) {
|
||||
PsiPackage pkg = JavaPsiFacade.getInstance(ref.getProject()).findPackage(refName);
|
||||
if (pkg != null) {
|
||||
return new GroovyResolveResult[]{new GroovyResolveResultImpl(pkg, true)};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -444,6 +422,36 @@ public class GrCodeReferenceElementImpl extends GrReferenceElementImpl<GrCodeRef
|
||||
return GroovyResolveResult.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement resolveClassOrPackagePreferInner(@NotNull GrCodeReferenceElementImpl ref,
|
||||
@NotNull ReferenceKind kind,
|
||||
String qName,
|
||||
JavaPsiFacade facade) {
|
||||
if (kind == ReferenceKind.CLASS_OR_PACKAGE_FQ || kind == ReferenceKind.CLASS_FQ) {
|
||||
final PsiFile file = ref.getContainingFile();
|
||||
boolean qualified = qName.indexOf('.') > 0;
|
||||
if (qualified || file instanceof GroovyFile && ((GroovyFile)file).getPackageName().isEmpty()) {
|
||||
//prefer inner classes, because groovyc does that as well
|
||||
PsiElement container = qualified ? resolveClassOrPackagePreferInner(ref, kind, StringUtil.getPackageName(qName), facade) : null;
|
||||
PsiClass aClass = container instanceof PsiClass && PsiUtil.isAccessible(ref, (PsiClass)container)
|
||||
? ((PsiClass)container).findInnerClassByName(StringUtil.getShortName(qName), true)
|
||||
: null;
|
||||
if (aClass == null) {
|
||||
aClass = facade.findClass(qName, ref.getResolveScope());
|
||||
}
|
||||
if (aClass != null) {
|
||||
return aClass;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (kind == ReferenceKind.CLASS_OR_PACKAGE_FQ || kind == ReferenceKind.PACKAGE_FQ) {
|
||||
return facade.findPackage(qName);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static PsiFile getContainingFileSkippingStubFiles(GrCodeReferenceElementImpl ref) {
|
||||
PsiFile file = ref.getContainingFile();
|
||||
while (file != null && !file.isPhysical() && file.getContext() != null) {
|
||||
|
||||
+58
-42
@@ -17,6 +17,7 @@ package org.jetbrains.plugins.groovy.lang.psi.util;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.compiled.ClsClassImpl;
|
||||
import com.intellij.util.Function;
|
||||
@@ -36,6 +37,12 @@ import static com.intellij.psi.PsiModifier.ABSTRACT;
|
||||
*/
|
||||
public class GrTraitUtil {
|
||||
private static final Logger LOG = Logger.getInstance(GrTraitUtil.class);
|
||||
private static final PsiTypeMapper ID_MAPPER = new PsiTypeMapper() {
|
||||
@Override
|
||||
public PsiType visitClassType(PsiClassType classType) {
|
||||
return classType;
|
||||
}
|
||||
};
|
||||
|
||||
@Contract("null -> false")
|
||||
public static boolean isInterface(@Nullable PsiClass aClass) {
|
||||
@@ -73,7 +80,7 @@ public class GrTraitUtil {
|
||||
&& AnnotationUtil.isAnnotated(containingClass, "groovy.transform.Trait", false);
|
||||
}
|
||||
|
||||
public static PsiMethod createTraitMethodFromCompiledHelperMethod(final PsiMethod compiledMethod, PsiClass trait) {
|
||||
public static PsiMethod createTraitMethodFromCompiledHelperMethod(final PsiMethod compiledMethod, final PsiClass trait) {
|
||||
assert compiledMethod.getParameterList().getParametersCount() > 0;
|
||||
|
||||
final GrLightMethodBuilder result = new GrLightMethodBuilder(compiledMethod.getManager(), compiledMethod.getName());
|
||||
@@ -84,59 +91,68 @@ public class GrTraitUtil {
|
||||
result.getTypeParameterList().addParameter(parameter);
|
||||
}
|
||||
|
||||
final Map<String, PsiTypeParameter> substitutionMap = ContainerUtil.newTroveMap();
|
||||
for (PsiTypeParameter parameter : trait.getTypeParameters()) {
|
||||
substitutionMap.put(parameter.getName(), parameter);
|
||||
}
|
||||
final PsiTypeVisitor<PsiType> corrector = createCorrector(compiledMethod, trait);
|
||||
|
||||
final PsiElementFactory myElementFactory = JavaPsiFacade.getInstance(compiledMethod.getProject()).getElementFactory();
|
||||
final PsiTypeVisitor<PsiType> corrector = new PsiTypeMapper() {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiType visitClassType(PsiClassType classType) {
|
||||
final PsiClass resolved = classType.resolve();
|
||||
// if resolved to method parameter -> return as is
|
||||
if (resolved instanceof PsiTypeParameter && compiledMethod.equals(((PsiTypeParameter)resolved).getOwner())) return classType;
|
||||
if (resolved == null) {
|
||||
// if not resolved -> try to get from map
|
||||
final PsiTypeParameter byName = substitutionMap.get(classType.getCanonicalText());
|
||||
return byName == null ? classType : myElementFactory.createType(byName);
|
||||
}
|
||||
else {
|
||||
// if resolved -> get from map anyways
|
||||
final PsiTypeParameter byName = substitutionMap.get(resolved.getName());
|
||||
final PsiTypeVisitor<PsiType> $this = this;
|
||||
final PsiType[] substitutes = !classType.hasParameters() ? PsiType.EMPTY_ARRAY : ContainerUtil.map2Array(
|
||||
classType.getParameters(), PsiType.class, new Function<PsiType, PsiType>() {
|
||||
@Override
|
||||
public PsiType fun(PsiType type) {
|
||||
return type.accept($this);
|
||||
}
|
||||
}
|
||||
);
|
||||
return myElementFactory.createType(byName != null ? byName : resolved, substitutes);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 1; i < compiledMethod.getParameterList().getParameters().length; i++) {
|
||||
final PsiParameter originalParameter = compiledMethod.getParameterList().getParameters()[i];
|
||||
final PsiType originalType = originalParameter.getType();
|
||||
final PsiType correctedType = trait.hasTypeParameters() ? originalType.accept(corrector) : originalType;
|
||||
final PsiParameter[] methodParameters = compiledMethod.getParameterList().getParameters();
|
||||
for (int i = 1; i < methodParameters.length; i++) {
|
||||
final PsiParameter originalParameter = methodParameters[i];
|
||||
final PsiType correctedType = originalParameter.getType().accept(corrector);
|
||||
result.addParameter(originalParameter.getName(), correctedType, false);
|
||||
}
|
||||
|
||||
for (PsiClassType type : compiledMethod.getThrowsList().getReferencedTypes()) {
|
||||
final PsiType correctedType = trait.hasTypeParameters() ? type.accept(corrector) : type;
|
||||
final PsiType correctedType = type.accept(corrector);
|
||||
result.getThrowsList().addReference(correctedType instanceof PsiClassType ? (PsiClassType)correctedType : type);
|
||||
}
|
||||
|
||||
{
|
||||
final PsiType originalType = compiledMethod.getReturnType();
|
||||
result.setReturnType(originalType != null && trait.hasTypeParameters() ? originalType.accept(corrector) : originalType);
|
||||
result.setReturnType(originalType == null ? null : originalType.accept(corrector));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiTypeMapper createCorrector(final PsiMethod compiledMethod, final PsiClass trait) {
|
||||
final PsiTypeParameter[] traitTypeParameters = trait.getTypeParameters();
|
||||
if (traitTypeParameters.length == 0) return ID_MAPPER;
|
||||
|
||||
final Map<String, PsiTypeParameter> substitutionMap = ContainerUtil.newTroveMap();
|
||||
for (PsiTypeParameter parameter : traitTypeParameters) {
|
||||
substitutionMap.put(parameter.getName(), parameter);
|
||||
}
|
||||
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(trait.getProject()).getElementFactory();
|
||||
return new PsiTypeMapper() {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiType visitClassType(PsiClassType originalType) {
|
||||
final PsiClass resolved = originalType.resolve();
|
||||
// if resolved to method parameter -> return as is
|
||||
if (resolved instanceof PsiTypeParameter && compiledMethod.equals(((PsiTypeParameter)resolved).getOwner())) return originalType;
|
||||
final PsiType[] typeParameters = originalType.getParameters();
|
||||
final PsiTypeParameter byName = substitutionMap.get(originalType.getCanonicalText());
|
||||
if (byName != null) {
|
||||
assert typeParameters.length == 0;
|
||||
return elementFactory.createType(byName);
|
||||
}
|
||||
if (resolved == null) return originalType;
|
||||
if (typeParameters.length == 0) return originalType; // do not go deeper
|
||||
|
||||
final Ref<Boolean> hasChanges = Ref.create(false);
|
||||
final PsiTypeVisitor<PsiType> $this = this;
|
||||
final PsiType[] substitutes = ContainerUtil.map2Array(typeParameters, PsiType.class, new Function<PsiType, PsiType>() {
|
||||
@Override
|
||||
public PsiType fun(PsiType type) {
|
||||
final PsiType mapped = type.accept($this);
|
||||
hasChanges.set(mapped != type);
|
||||
return mapped;
|
||||
}
|
||||
});
|
||||
return hasChanges.get() ? elementFactory.createType(resolved, substitutes) : originalType;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,7 +290,7 @@ public class PyActiveSdkConfigurable implements UnnamedConfigurable {
|
||||
PySdkService.getInstance().solidifySdk(item);
|
||||
}
|
||||
myProjectSdksModel.apply();
|
||||
newSdk = newSdk == null ? null : myProjectSdksModel.findSdk(newSdk.getName());
|
||||
newSdk = newSdk == null ? null : myProjectSdksModel.findSdk(newSdk);
|
||||
mySdkCombo.getModel().setSelectedItem(newSdk);
|
||||
|
||||
final Sdk prevSdk = getSdk();
|
||||
|
||||
@@ -406,7 +406,7 @@ public class PythonSdkDetailsDialog extends DialogWrapper {
|
||||
}
|
||||
|
||||
private void reloadSdk(Sdk currentSdk) {
|
||||
PythonSdkType.setupSdkPaths(myProject, null, currentSdk, myModificators.get(currentSdk)); // or must it be a RunWriteAction?
|
||||
PythonSdkType.setupSdkPaths(currentSdk, myProject, null, myModificators.get(currentSdk)); // or must it be a RunWriteAction?
|
||||
}
|
||||
|
||||
private class ToggleVirtualEnvFilterButton extends ToggleActionButton implements DumbAware {
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.SdkModificator;
|
||||
import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.vfs.StandardFileSystems;
|
||||
@@ -39,6 +38,7 @@ import com.jetbrains.python.psi.resolve.*;
|
||||
import com.jetbrains.python.psi.types.PyClassLikeType;
|
||||
import com.jetbrains.python.psi.types.PyType;
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext;
|
||||
import com.jetbrains.python.sdk.PySdkUpdater;
|
||||
import com.jetbrains.python.sdk.PythonSdkType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -137,10 +137,10 @@ public class PyUserSkeletonsUtil {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void addUserSkeletonsRoot(@NotNull SdkModificator sdkModificator) {
|
||||
public static void addUserSkeletonsRoot(@NotNull PySdkUpdater sdkUpdater) {
|
||||
final VirtualFile root = getUserSkeletonsDirectory();
|
||||
if (root != null) {
|
||||
sdkModificator.addRoot(root, OrderRootType.CLASSES);
|
||||
sdkUpdater.addRoot(root, OrderRootType.CLASSES);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.jetbrains.python.sdk;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.SdkModificator;
|
||||
import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl;
|
||||
import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* This sdk updater class is a facade to Sdk to make changes in it in a reliable way.
|
||||
* Working with sdk instance instead of this class can be wrong, because an instance can become
|
||||
* obsolete being substituted in sdk table by a new one. Or already created sdk modificator can be committed,
|
||||
* discarding the changes that we doing with the sdk.
|
||||
*
|
||||
*
|
||||
* There are two ways of creation of the facade:
|
||||
* 1) by sdk path - in this case we'll get the current actual sdk instance
|
||||
* from sdk table by that path, creating and committing SdkModificator on every change
|
||||
* 2) by sdkModificator - in that case we'll make changes to that modificator, but it is not committed,
|
||||
* because it has been created outside of the updater.
|
||||
*
|
||||
*
|
||||
* @author traff
|
||||
*/
|
||||
public abstract class PySdkUpdater {
|
||||
@NotNull
|
||||
public abstract Sdk getSdk();
|
||||
|
||||
public abstract void modifySdk(@NotNull SdkModificationProcessor processor);
|
||||
|
||||
public void addRoot(@NotNull final VirtualFile root, @NotNull final OrderRootType rootType) {
|
||||
modifySdk(new SdkModificationProcessor() {
|
||||
@Override
|
||||
public void process(@NotNull Sdk sdk, @NotNull SdkModificator sdkModificator) {
|
||||
sdkModificator.addRoot(root, rootType);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void removeRoots(@NotNull final OrderRootType rootType) {
|
||||
modifySdk(new PySdkUpdater.SdkModificationProcessor() {
|
||||
@Override
|
||||
public void process(@NotNull Sdk sdk, @NotNull SdkModificator sdkModificator) {
|
||||
sdkModificator.removeRoots(rootType);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static PySdkUpdater fromSdkPath(@Nullable String sdkPath) {
|
||||
return new JdkTableUpdater(sdkPath);
|
||||
}
|
||||
|
||||
public static PySdkUpdater fromSdkModificator(@NotNull Sdk sdk, @NotNull SdkModificator sdkModificator) {
|
||||
return new SdkModificatorUpdater(sdk, sdkModificator);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public abstract String getHomePath();
|
||||
|
||||
private static class JdkTableUpdater extends PySdkUpdater {
|
||||
private final String mySdkPath;
|
||||
|
||||
private JdkTableUpdater(@Nullable String path) {
|
||||
mySdkPath = path;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Sdk getSdk() {
|
||||
Sdk sdk = PythonSdkType.findSdkByPath(mySdkPath);
|
||||
if (sdk != null) {
|
||||
return sdk;
|
||||
}
|
||||
else {
|
||||
return new ProjectJdkImpl(getHomePath(), PythonSdkType.getInstance());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getHomePath() {
|
||||
return mySdkPath;
|
||||
}
|
||||
|
||||
public void modifySdk(@NotNull SdkModificationProcessor processor) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
|
||||
Sdk sdk = PythonSdkType.findSdkByPath(mySdkPath);
|
||||
|
||||
if (sdk != null) {
|
||||
SdkModificator modificator = getSdk().getSdkModificator();
|
||||
processor.process(sdk, modificator);
|
||||
modificator.commitChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class SdkModificatorUpdater extends PySdkUpdater {
|
||||
private SdkModificator myModificator;
|
||||
private Sdk mySdk;
|
||||
|
||||
public SdkModificatorUpdater(@NotNull Sdk sdk, @NotNull SdkModificator modificator) {
|
||||
mySdk = sdk;
|
||||
myModificator = modificator;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Sdk getSdk() {
|
||||
return mySdk;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getHomePath() {
|
||||
return mySdk.getHomePath();
|
||||
}
|
||||
|
||||
public void modifySdk(@NotNull SdkModificationProcessor processor) {
|
||||
processor.process(getSdk(), myModificator);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface SdkModificationProcessor {
|
||||
void process(@NotNull Sdk sdk, @NotNull SdkModificator sdkModificator);
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import com.intellij.notification.Notifications;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
@@ -45,10 +46,7 @@ import com.intellij.openapi.projectRoots.*;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.io.FileSystemUtil;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.CharFilter;
|
||||
@@ -63,6 +61,7 @@ import com.intellij.remote.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.NullableConsumer;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.PyNames;
|
||||
import com.jetbrains.python.PythonFileType;
|
||||
@@ -242,7 +241,7 @@ public class PythonSdkType extends SdkType {
|
||||
|
||||
public static boolean isVagrant(@Nullable Sdk sdk) {
|
||||
if (sdk != null && sdk.getSdkAdditionalData() instanceof PyRemoteSdkAdditionalDataBase) {
|
||||
PyRemoteSdkAdditionalDataBase data = (PyRemoteSdkAdditionalDataBase) sdk.getSdkAdditionalData();
|
||||
PyRemoteSdkAdditionalDataBase data = (PyRemoteSdkAdditionalDataBase)sdk.getSdkAdditionalData();
|
||||
|
||||
return data.getRemoteConnectionType() == CredentialsType.VAGRANT;
|
||||
}
|
||||
@@ -519,45 +518,63 @@ public class PythonSdkType extends SdkType {
|
||||
return true; // run setupSdkPaths only once (from PythonSdkDetailsStep). Skip this from showCustomCreateUI
|
||||
}
|
||||
|
||||
public static void setupSdkPaths(Sdk sdk, @Nullable Project project, @Nullable Component ownerComponent) {
|
||||
final SdkModificator sdkModificator = sdk.getSdkModificator();
|
||||
final boolean success = setupSdkPaths(project, ownerComponent, sdk, sdkModificator);
|
||||
if (success) {
|
||||
sdkModificator.commitChanges();
|
||||
}
|
||||
else {
|
||||
Messages.showErrorDialog(
|
||||
project,
|
||||
PyBundle.message("MSG.cant.setup.sdk.$0", FileUtil.toSystemDependentName(sdk.getSdkModificator().getHomePath())),
|
||||
PyBundle.message("MSG.title.bad.sdk")
|
||||
);
|
||||
}
|
||||
public static void setupSdkPaths(@NotNull final Sdk sdk,
|
||||
@Nullable final Project project,
|
||||
@Nullable final Component ownerComponent,
|
||||
@NotNull final SdkModificator sdkModificator) {
|
||||
doSetupSdkPaths(project, ownerComponent, PySdkUpdater.fromSdkModificator(sdk, sdkModificator));
|
||||
}
|
||||
|
||||
public static boolean setupSdkPaths(@Nullable final Project project,
|
||||
@Nullable final Component ownerComponent,
|
||||
@NotNull final Sdk sdk,
|
||||
@NotNull final SdkModificator sdkModificator) {
|
||||
if (isRemote(sdk) && project == null && ownerComponent == null) {
|
||||
|
||||
public static void setupSdkPaths(final Sdk sdk, @Nullable final Project project, @Nullable final Component ownerComponent) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final boolean success = doSetupSdkPaths(project, ownerComponent, PySdkUpdater.fromSdkPath(sdk.getHomePath()));
|
||||
|
||||
if (!success) {
|
||||
Messages.showErrorDialog(
|
||||
project,
|
||||
PyBundle.message("MSG.cant.setup.sdk.$0", FileUtil.toSystemDependentName(sdk.getSdkModificator().getHomePath())),
|
||||
PyBundle.message("MSG.title.bad.sdk")
|
||||
);
|
||||
}
|
||||
}
|
||||
}, ModalityState.NON_MODAL);
|
||||
}
|
||||
|
||||
private static boolean doSetupSdkPaths(@Nullable final Project project,
|
||||
@Nullable final Component ownerComponent,
|
||||
@NotNull final PySdkUpdater sdkUpdater) {
|
||||
if (isRemote(sdkUpdater.getSdk()) && project == null && ownerComponent == null) {
|
||||
LOG.error("For refreshing skeletons of remote SDK, either project or owner component must be specified");
|
||||
}
|
||||
final ProgressManager progressManager = ProgressManager.getInstance();
|
||||
final Ref<Boolean> sdkPathsUpdatedRef = new Ref<Boolean>(false);
|
||||
final Task.Modal setupTask = new Task.Modal(project, "Setting up library files for " + sdk.getName(), false) {
|
||||
public void run(@NotNull final ProgressIndicator indicator) {
|
||||
sdkModificator.removeAllRoots();
|
||||
try {
|
||||
updateSdkRootsFromSysPath(sdk, sdkModificator, indicator);
|
||||
updateUserAddedPaths(sdk, sdkModificator, indicator);
|
||||
PythonSdkUpdater.getInstance().markAlreadyUpdated(sdk.getHomePath());
|
||||
sdkPathsUpdatedRef.set(true);
|
||||
}
|
||||
catch (InvalidSdkException ignored) {
|
||||
boolean sdkPathsUpdated = UIUtil.<Boolean>invokeAndWaitIfNeeded(
|
||||
new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
sdkUpdater.modifySdk(new PySdkUpdater.SdkModificationProcessor() {
|
||||
@Override
|
||||
public void process(@NotNull Sdk sdk,
|
||||
@NotNull SdkModificator sdkModificator) {
|
||||
sdkModificator.removeAllRoots();
|
||||
}
|
||||
});
|
||||
try {
|
||||
updateSdkRootsFromSysPath(sdkUpdater);
|
||||
updateUserAddedPaths(sdkUpdater);
|
||||
PythonSdkUpdater.getInstance()
|
||||
.markAlreadyUpdated(sdkUpdater.getHomePath());
|
||||
return true;
|
||||
}
|
||||
catch (InvalidSdkException ignored) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
progressManager.run(setupTask);
|
||||
final Boolean sdkPathsUpdated = sdkPathsUpdatedRef.get();
|
||||
);
|
||||
|
||||
final Application application = ApplicationManager.getApplication();
|
||||
if (sdkPathsUpdated && !application.isUnitTestMode()) {
|
||||
application.invokeLater(new Runnable() {
|
||||
@@ -567,20 +584,20 @@ public class PythonSdkType extends SdkType {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
try {
|
||||
final String skeletonsPath = getSkeletonsPath(PathManager.getSystemPath(), sdk.getHomePath());
|
||||
PythonSdkUpdater.updateSdk(project, ownerComponent, sdk, skeletonsPath);
|
||||
final String skeletonsPath = getSkeletonsPath(PathManager.getSystemPath(), sdkUpdater.getHomePath());
|
||||
PythonSdkUpdater.updateSdk(project, ownerComponent, sdkUpdater, skeletonsPath);
|
||||
}
|
||||
catch (InvalidSdkException e) {
|
||||
// If the SDK is invalid, the user should worry about the SDK itself, not about skeletons generation errors
|
||||
if (isVagrant(sdk)) {
|
||||
if (isVagrant(sdkUpdater.getSdk())) {
|
||||
notifyRemoteSdkSkeletonsFail(e, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setupSdkPaths(project, ownerComponent, sdk, sdkModificator);
|
||||
setupSdkPaths(sdkUpdater.getSdk(), project, ownerComponent);
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (!isInvalid(sdk)) {
|
||||
else if (!isInvalid(sdkUpdater.getSdk())) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
@@ -622,7 +639,8 @@ public class PythonSdkType extends SdkType {
|
||||
|
||||
Notifications.Bus.notify(
|
||||
new Notification(
|
||||
SKELETONS_TOPIC, "Couldn't refresh skeletons for remote interpreter", e.getMessage() + "\n<a href=\"#\">Launch vagrant and refresh skeletons</a>",
|
||||
SKELETONS_TOPIC, "Couldn't refresh skeletons for remote interpreter",
|
||||
e.getMessage() + "\n<a href=\"#\">Launch vagrant and refresh skeletons</a>",
|
||||
NotificationType.WARNING,
|
||||
notificationListener
|
||||
)
|
||||
@@ -636,35 +654,28 @@ public class PythonSdkType extends SdkType {
|
||||
|
||||
private final static Pattern PYTHON_NN_RE = Pattern.compile("python\\d\\.\\d.*");
|
||||
|
||||
public static void updateSdkRootsFromSysPath(Sdk sdk, SdkModificator sdkModificator, ProgressIndicator indicator)
|
||||
public static void updateSdkRootsFromSysPath(PySdkUpdater sdkUpdater)
|
||||
throws InvalidSdkException {
|
||||
Application application = ApplicationManager.getApplication();
|
||||
boolean not_in_unit_test_mode = (application != null && !application.isUnitTestMode());
|
||||
|
||||
String sdkHome = sdkModificator.getHomePath();
|
||||
String sdkHome = sdkUpdater.getHomePath();
|
||||
assert sdkHome != null;
|
||||
final String sep = File.separator;
|
||||
// we have a number of lib dirs, those listed in python's sys.path
|
||||
if (indicator != null) {
|
||||
indicator.setText("Adding library roots");
|
||||
}
|
||||
// Add folders from sys.path
|
||||
if (!PySdkUtil.isRemote(sdk)) { //no sense to add roots of remote sdk
|
||||
if (!PySdkUtil.isRemote(sdkUpdater.getSdk())) { //no sense to add roots of remote sdk
|
||||
final List<String> paths = getSysPath(sdkHome);
|
||||
if (paths.size() > 0) {
|
||||
// add every path as root.
|
||||
for (String path : paths) {
|
||||
if (!path.contains(sep)) continue; // TODO: interpret possible 'special' paths reasonably
|
||||
if (indicator != null) {
|
||||
indicator.setText2(path);
|
||||
}
|
||||
addSdkRoot(sdkModificator, path);
|
||||
addSdkRoot(sdkUpdater, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PyUserSkeletonsUtil.addUserSkeletonsRoot(sdkModificator);
|
||||
addSkeletonsRoot(sdkModificator, sdkHome);
|
||||
PyUserSkeletonsUtil.addUserSkeletonsRoot(sdkUpdater);
|
||||
addSkeletonsRoot(sdkUpdater, sdkHome);
|
||||
|
||||
if (not_in_unit_test_mode) {
|
||||
File venv_root = getVirtualEnvRoot(sdkHome);
|
||||
@@ -680,57 +691,54 @@ public class PythonSdkType extends SdkType {
|
||||
}
|
||||
}
|
||||
}
|
||||
addHardcodedPaths(sdkModificator);
|
||||
addHardcodedPaths(sdkUpdater);
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateUserAddedPaths(Sdk sdk, SdkModificator sdkModificator, ProgressIndicator indicator)
|
||||
public static void updateUserAddedPaths(PySdkUpdater sdkUpdater)
|
||||
throws InvalidSdkException {
|
||||
if (indicator != null) {
|
||||
indicator.setText("Adding user-added roots");
|
||||
}
|
||||
SdkAdditionalData data = sdk.getSdkAdditionalData();
|
||||
SdkAdditionalData data = sdkUpdater.getSdk().getSdkAdditionalData();
|
||||
if (data instanceof PythonSdkAdditionalData) {
|
||||
for (VirtualFile file : ((PythonSdkAdditionalData)data).getAddedPathFiles()) {
|
||||
addSdkRoot(sdkModificator, file);
|
||||
addSdkRoot(sdkUpdater, file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void addSkeletonsRoot(@NotNull SdkModificator sdkModificator, String sdkHome) {
|
||||
private static void addSkeletonsRoot(@NotNull PySdkUpdater sdkUpdater, String sdkHome) {
|
||||
@NonNls final String skeletonsPath = getSkeletonsPath(PathManager.getSystemPath(), sdkHome);
|
||||
new File(skeletonsPath).mkdirs();
|
||||
final VirtualFile builtins_root = LocalFileSystem.getInstance().refreshAndFindFileByPath(skeletonsPath);
|
||||
assert builtins_root != null : "Cannot find skeletons path " + skeletonsPath + " in VFS";
|
||||
sdkModificator.addRoot(builtins_root, BUILTIN_ROOT_TYPE);
|
||||
sdkUpdater.addRoot(builtins_root, BUILTIN_ROOT_TYPE);
|
||||
}
|
||||
|
||||
protected static void addHardcodedPaths(SdkModificator sdkModificator) {
|
||||
protected static void addHardcodedPaths(PySdkUpdater sdkUpdater) {
|
||||
// Add python-django installed as package in Linux
|
||||
// NOTE: fragile and arbitrary
|
||||
if (SystemInfo.isLinux) {
|
||||
final VirtualFile file = LocalFileSystem.getInstance().findFileByPath("/usr/lib/python-django");
|
||||
if (file != null) {
|
||||
sdkModificator.addRoot(file, OrderRootType.CLASSES);
|
||||
sdkUpdater.addRoot(file, OrderRootType.CLASSES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void addSdkRoot(SdkModificator sdkModificator, String path) {
|
||||
public static void addSdkRoot(PySdkUpdater sdkUpdater, String path) {
|
||||
final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(path);
|
||||
if (file != null) {
|
||||
addSdkRoot(sdkModificator, file);
|
||||
addSdkRoot(sdkUpdater, file);
|
||||
}
|
||||
else {
|
||||
LOG.info("Bogus sys.path entry " + path);
|
||||
}
|
||||
}
|
||||
|
||||
private static void addSdkRoot(@NotNull SdkModificator sdkModificator, @NotNull VirtualFile child) {
|
||||
private static void addSdkRoot(@NotNull PySdkUpdater sdkUpdater, final @NotNull VirtualFile child) {
|
||||
// NOTE: Files marked as library sources are not considered part of project source. Since the directory of the project the
|
||||
// user is working on is included in PYTHONPATH with many configurations (e.g. virtualenv), we must not mark SDK paths as
|
||||
// library sources, only as classes.
|
||||
sdkModificator.addRoot(getSdkRootVirtualFile(child), OrderRootType.CLASSES);
|
||||
sdkUpdater.addRoot(getSdkRootVirtualFile(child), OrderRootType.CLASSES);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -29,7 +29,6 @@ import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.SdkModificator;
|
||||
import com.intellij.openapi.projectRoots.SdkTypeId;
|
||||
import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.startup.StartupActivity;
|
||||
@@ -124,7 +123,7 @@ public class PythonSdkUpdater implements StartupActivity {
|
||||
for (final Sdk sdk : sdksToUpdate) {
|
||||
try {
|
||||
LOG.info("Performing background update of skeletons for SDK " + sdk.getHomePath());
|
||||
updateSdk(project, null, sdk, PythonSdkType.findSkeletonsPath(sdk));
|
||||
updateSdk(project, null, PySdkUpdater.fromSdkPath(sdk.getHomePath()), PythonSdkType.findSkeletonsPath(sdk));
|
||||
}
|
||||
catch (InvalidSdkException e) {
|
||||
if (PythonSdkType.isVagrant(sdk)) {
|
||||
@@ -149,13 +148,14 @@ public class PythonSdkUpdater implements StartupActivity {
|
||||
});
|
||||
}
|
||||
|
||||
public static void updateSdk(@Nullable Project project, @Nullable Component ownerComponent, @NotNull final Sdk sdk, String skeletonsPath) throws InvalidSdkException {
|
||||
PySkeletonRefresher.refreshSkeletonsOfSdk(project, ownerComponent, skeletonsPath, sdk); // NOTE: whole thing would need a rename
|
||||
if (!PySdkUtil.isRemote(sdk)) {
|
||||
updateSysPath(sdk);
|
||||
public static void updateSdk(@Nullable Project project, @Nullable Component ownerComponent, @NotNull final PySdkUpdater sdkUpdater, String skeletonsPath)
|
||||
throws InvalidSdkException {
|
||||
PySkeletonRefresher.refreshSkeletonsOfSdk(project, ownerComponent, skeletonsPath, sdkUpdater); // NOTE: whole thing would need a rename
|
||||
if (!PySdkUtil.isRemote(sdkUpdater.getSdk())) {
|
||||
updateSysPath(sdkUpdater);
|
||||
}
|
||||
else {
|
||||
PyRemoteSdkAdditionalDataBase remoteSdkData = (PyRemoteSdkAdditionalDataBase)sdk.getSdkAdditionalData();
|
||||
PyRemoteSdkAdditionalDataBase remoteSdkData = (PyRemoteSdkAdditionalDataBase)sdkUpdater.getSdk().getSdkAdditionalData();
|
||||
assert remoteSdkData != null;
|
||||
final List<String> paths = Lists.newArrayList();
|
||||
for (PathMappingSettings.PathMapping mapping : remoteSdkData.getPathMappings().getPathMappings()) {
|
||||
@@ -165,15 +165,15 @@ public class PythonSdkUpdater implements StartupActivity {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateSdkPath(sdk, paths);
|
||||
updateSdkPath(sdkUpdater, paths);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void updateSysPath(@NotNull final Sdk sdk) throws InvalidSdkException {
|
||||
private static void updateSysPath(@NotNull final PySdkUpdater sdkUpdater) throws InvalidSdkException {
|
||||
long start_time = System.currentTimeMillis();
|
||||
final List<String> sysPath = PythonSdkType.getSysPath(sdk.getHomePath());
|
||||
final List<String> sysPath = PythonSdkType.getSysPath(sdkUpdater.getHomePath());
|
||||
final VirtualFile file = PyUserSkeletonsUtil.getUserSkeletonsDirectory();
|
||||
if (file != null) {
|
||||
sysPath.add(file.getPath());
|
||||
@@ -181,7 +181,7 @@ public class PythonSdkUpdater implements StartupActivity {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateSdkPath(sdk, sysPath);
|
||||
updateSdkPath(sdkUpdater, sysPath);
|
||||
}
|
||||
});
|
||||
LOG.info("Updating sys.path took " + (System.currentTimeMillis() - start_time) + " ms");
|
||||
@@ -190,29 +190,20 @@ public class PythonSdkUpdater implements StartupActivity {
|
||||
/**
|
||||
* Updates SDK based on sys.path and cleans legacy information up.
|
||||
*/
|
||||
private static void updateSdkPath(@NotNull Sdk sdk, @NotNull List<String> sysPath) {
|
||||
final SdkModificator modificator = sdk.getSdkModificator();
|
||||
boolean changed = addNewSysPathEntries(sdk, modificator, sysPath);
|
||||
changed = removeSourceRoots(sdk, modificator) || changed;
|
||||
changed = removeDuplicateClassRoots(sdk, modificator) || changed;
|
||||
changed = updateSkeletonsPath(sdk, modificator) || changed;
|
||||
if (changed) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
modificator.commitChanges();
|
||||
}
|
||||
});
|
||||
}
|
||||
private static void updateSdkPath(@NotNull PySdkUpdater sdkUpdater, @NotNull List<String> sysPath) {
|
||||
addNewSysPathEntries(sdkUpdater, sysPath);
|
||||
removeSourceRoots(sdkUpdater);
|
||||
removeDuplicateClassRoots(sdkUpdater);
|
||||
updateSkeletonsPath(sdkUpdater);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds new CLASSES entries found in sys.path.
|
||||
*/
|
||||
private static boolean addNewSysPathEntries(@NotNull Sdk sdk, @NotNull SdkModificator modificator, @NotNull List<String> sysPath) {
|
||||
final List<VirtualFile> oldRoots = Arrays.asList(sdk.getRootProvider().getFiles(OrderRootType.CLASSES));
|
||||
PythonSdkAdditionalData additionalData = sdk.getSdkAdditionalData() instanceof PythonSdkAdditionalData
|
||||
? (PythonSdkAdditionalData)sdk.getSdkAdditionalData()
|
||||
private static boolean addNewSysPathEntries(@NotNull PySdkUpdater sdkUpdater, @NotNull List<String> sysPath) {
|
||||
final List<VirtualFile> oldRoots = Arrays.asList(sdkUpdater.getSdk().getRootProvider().getFiles(OrderRootType.CLASSES));
|
||||
PythonSdkAdditionalData additionalData = sdkUpdater.getSdk().getSdkAdditionalData() instanceof PythonSdkAdditionalData
|
||||
? (PythonSdkAdditionalData)sdkUpdater.getSdk().getSdkAdditionalData()
|
||||
: null;
|
||||
List<String> newRoots = new ArrayList<String>();
|
||||
for (String root : sysPath) {
|
||||
@@ -225,7 +216,7 @@ public class PythonSdkUpdater implements StartupActivity {
|
||||
}
|
||||
if (!newRoots.isEmpty()) {
|
||||
for (String root : newRoots) {
|
||||
PythonSdkType.addSdkRoot(modificator, root);
|
||||
PythonSdkType.addSdkRoot(sdkUpdater, root);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -235,13 +226,13 @@ public class PythonSdkUpdater implements StartupActivity {
|
||||
/**
|
||||
* Removes duplicate roots that have been added as the result of a bug with *.egg handling.
|
||||
*/
|
||||
private static boolean removeDuplicateClassRoots(@NotNull Sdk sdk, @NotNull SdkModificator modificator) {
|
||||
final List<VirtualFile> sourceRoots = Arrays.asList(sdk.getRootProvider().getFiles(OrderRootType.CLASSES));
|
||||
private static boolean removeDuplicateClassRoots(@NotNull PySdkUpdater sdkUpdater) {
|
||||
final List<VirtualFile> sourceRoots = Arrays.asList(sdkUpdater.getSdk().getRootProvider().getFiles(OrderRootType.CLASSES));
|
||||
final LinkedHashSet<VirtualFile> uniqueRoots = new LinkedHashSet<VirtualFile>(sourceRoots);
|
||||
if (uniqueRoots.size() != sourceRoots.size()) {
|
||||
modificator.removeRoots(OrderRootType.CLASSES);
|
||||
sdkUpdater.removeRoots(OrderRootType.CLASSES);
|
||||
for (VirtualFile root : uniqueRoots) {
|
||||
modificator.addRoot(root, OrderRootType.CLASSES);
|
||||
sdkUpdater.addRoot(root, OrderRootType.CLASSES);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -251,10 +242,10 @@ public class PythonSdkUpdater implements StartupActivity {
|
||||
/**
|
||||
* Removes legacy SOURCES entries in Python SDK tables (PY-2891).
|
||||
*/
|
||||
private static boolean removeSourceRoots(@NotNull Sdk sdk, @NotNull SdkModificator modificator) {
|
||||
final VirtualFile[] sourceRoots = sdk.getRootProvider().getFiles(OrderRootType.SOURCES);
|
||||
private static boolean removeSourceRoots(@NotNull PySdkUpdater sdkUpdater) {
|
||||
final VirtualFile[] sourceRoots = sdkUpdater.getSdk().getRootProvider().getFiles(OrderRootType.SOURCES);
|
||||
if (sourceRoots.length > 0) {
|
||||
modificator.removeRoots(OrderRootType.SOURCES);
|
||||
sdkUpdater.removeRoots(OrderRootType.SOURCES);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -263,31 +254,27 @@ public class PythonSdkUpdater implements StartupActivity {
|
||||
/**
|
||||
* Updates binary skeletons path in the Python SDK table.
|
||||
*/
|
||||
private static boolean updateSkeletonsPath(@NotNull Sdk sdk, @NotNull SdkModificator modificator) {
|
||||
boolean changed = false;
|
||||
final String skeletonsPath = PythonSdkType.getSkeletonsPath(PathManager.getSystemPath(), sdk.getHomePath());
|
||||
private static void updateSkeletonsPath(@NotNull PySdkUpdater sdkUpdater) {
|
||||
final String skeletonsPath = PythonSdkType.getSkeletonsPath(PathManager.getSystemPath(), sdkUpdater.getHomePath());
|
||||
if (skeletonsPath != null) {
|
||||
final VirtualFile skeletonsDir = StandardFileSystems.local().refreshAndFindFileByPath(skeletonsPath);
|
||||
if (skeletonsDir != null) {
|
||||
LOG.info("Binary skeletons directory for SDK \"" + sdk.getName() + "\" (" + sdk.getHomePath() + "): " + skeletonsDir.getPath());
|
||||
final List<VirtualFile> sourceRoots = Arrays.asList(sdk.getRootProvider().getFiles(OrderRootType.CLASSES));
|
||||
LOG.info("Binary skeletons directory for SDK \"" + sdkUpdater.getSdk().getName() + "\" (" + sdkUpdater.getHomePath() + "): " + skeletonsDir.getPath());
|
||||
final List<VirtualFile> sourceRoots = Arrays.asList(sdkUpdater.getSdk().getRootProvider().getFiles(OrderRootType.CLASSES));
|
||||
boolean skeletonsDirFound = false;
|
||||
for (VirtualFile root : sourceRoots) {
|
||||
for (final VirtualFile root : sourceRoots) {
|
||||
if (root.equals(skeletonsDir)) {
|
||||
skeletonsDirFound = true;
|
||||
}
|
||||
if (PythonSdkType.isSkeletonsPath(root.getPath()) && !skeletonsDirFound) {
|
||||
modificator.removeRoot(root, OrderRootType.CLASSES);
|
||||
changed = true;
|
||||
sdkUpdater.addRoot(root, OrderRootType.CLASSES);
|
||||
}
|
||||
}
|
||||
if (!skeletonsDirFound) {
|
||||
modificator.addRoot(skeletonsDir, OrderRootType.CLASSES);
|
||||
changed = true;
|
||||
sdkUpdater.addRoot(skeletonsDir, OrderRootType.CLASSES);
|
||||
}
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
private static boolean wasOldRoot(@NotNull String root, @NotNull Collection<VirtualFile> oldRoots) {
|
||||
|
||||
@@ -47,6 +47,7 @@ import com.jetbrains.python.packaging.PyPackageManager;
|
||||
import com.jetbrains.python.psi.resolve.PythonSdkPathCache;
|
||||
import com.jetbrains.python.remote.PythonRemoteInterpreterManager;
|
||||
import com.jetbrains.python.sdk.InvalidSdkException;
|
||||
import com.jetbrains.python.sdk.PySdkUpdater;
|
||||
import com.jetbrains.python.sdk.PySdkUtil;
|
||||
import com.jetbrains.python.sdk.PythonSdkType;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -111,25 +112,25 @@ public class PySkeletonRefresher {
|
||||
public static void refreshSkeletonsOfSdk(@Nullable Project project,
|
||||
Component ownerComponent,
|
||||
String skeletonsPath,
|
||||
@NotNull Sdk sdk)
|
||||
@NotNull PySdkUpdater sdkUpdater)
|
||||
throws InvalidSdkException {
|
||||
final Map<String, List<String>> errors = new TreeMap<String, List<String>>();
|
||||
final List<String> failedSdks = new SmartList<String>();
|
||||
final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
|
||||
final String homePath = sdk.getHomePath();
|
||||
final String homePath = sdkUpdater.getHomePath();
|
||||
if (skeletonsPath == null) {
|
||||
LOG.info("Could not find skeletons path for SDK path " + homePath);
|
||||
}
|
||||
else {
|
||||
LOG.info("Refreshing skeletons for " + homePath);
|
||||
SkeletonVersionChecker checker = new SkeletonVersionChecker(0); // this default version won't be used
|
||||
final PySkeletonRefresher refresher = new PySkeletonRefresher(project, ownerComponent, sdk, skeletonsPath, indicator, null);
|
||||
final PySkeletonRefresher refresher = new PySkeletonRefresher(project, ownerComponent, sdkUpdater.getSdk(), skeletonsPath, indicator, null);
|
||||
|
||||
changeGeneratingSkeletons(1);
|
||||
try {
|
||||
List<String> sdkErrors = refresher.regenerateSkeletons(checker);
|
||||
if (sdkErrors.size() > 0) {
|
||||
String sdkName = sdk.getName();
|
||||
String sdkName = sdkUpdater.getSdk().getName();
|
||||
List<String> knownErrors = errors.get(sdkName);
|
||||
if (knownErrors == null) {
|
||||
errors.put(sdkName, sdkErrors);
|
||||
|
||||
@@ -144,10 +144,10 @@ public class PythonUnitTestingTest extends PyEnvTestCase {
|
||||
@NotNull final String stderr,
|
||||
@NotNull final String all) {
|
||||
final List<String> fileNames = runner.getHighlightedStringsInConsole().getSecond();
|
||||
Assert.assertThat(String.format("Wrong number of highlighted entries(%s) in the following output: %s",
|
||||
Assert.assertTrue(String.format("Not enough highlighted entries(%s) in the following output: %s",
|
||||
StringUtil.join(fileNames, ","),
|
||||
runner.getAllConsoleText()),
|
||||
fileNames, Matchers.hasSize(3));
|
||||
fileNames.size() >= 3);
|
||||
// UnitTest highlights file name
|
||||
Assert.assertThat("Bad line highlighted", fileNames, Matchers.everyItem(Matchers.endsWith(fileName)));
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.intellij.psi.stubs.StubUpdatingIndex;
|
||||
import com.intellij.util.indexing.FileBasedIndex;
|
||||
import com.jetbrains.python.codeInsight.userSkeletons.PyUserSkeletonsUtil;
|
||||
import com.jetbrains.python.psi.stubs.PyModuleNameIndex;
|
||||
import com.jetbrains.python.sdk.PySdkUpdater;
|
||||
import com.jetbrains.python.sdk.PythonSdkType;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
@@ -72,7 +73,7 @@ public class PythonMockSdk {
|
||||
sdkModificator.addRoot(LocalFileSystem.getInstance().refreshAndFindFileByIoFile(libPath), OrderRootType.CLASSES);
|
||||
}
|
||||
|
||||
PyUserSkeletonsUtil.addUserSkeletonsRoot(sdkModificator);
|
||||
PyUserSkeletonsUtil.addUserSkeletonsRoot(PySdkUpdater.fromSdkModificator(sdk, sdkModificator));
|
||||
|
||||
String mock_stubs_path = mock_path + PythonSdkType.SKELETON_DIR_NAME;
|
||||
sdkModificator.addRoot(LocalFileSystem.getInstance().refreshAndFindFileByPath(mock_stubs_path), PythonSdkType.BUILTIN_ROOT_TYPE);
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.UsefulTestCase;
|
||||
import com.jetbrains.python.sdk.InvalidSdkException;
|
||||
import com.jetbrains.python.sdk.PySdkUpdater;
|
||||
import com.jetbrains.python.sdk.PythonSdkType;
|
||||
import com.jetbrains.python.sdk.skeletons.PySkeletonRefresher;
|
||||
import com.jetbrains.python.sdk.skeletons.SkeletonVersionChecker;
|
||||
@@ -114,7 +115,7 @@ public final class PyTestSdkTools {
|
||||
modificator.removeRoots(OrderRootType.CLASSES);
|
||||
|
||||
for (final String path : PythonSdkType.getSysPathsFromScript(sdk.getHomePath())) {
|
||||
PythonSdkType.addSdkRoot(modificator, path);
|
||||
PythonSdkType.addSdkRoot(PySdkUpdater.fromSdkModificator(sdk, modificator), path);
|
||||
}
|
||||
if (!addSkeletons) {
|
||||
UsefulTestCase.edt(new Runnable() {
|
||||
@@ -130,7 +131,7 @@ public final class PyTestSdkTools {
|
||||
final File skeletonsDir = new File(tempDir, PythonSdkType.SKELETON_DIR_NAME);
|
||||
FileUtil.createDirectory(skeletonsDir);
|
||||
final String skeletonsPath = skeletonsDir.toString();
|
||||
PythonSdkType.addSdkRoot(modificator, skeletonsPath);
|
||||
PythonSdkType.addSdkRoot(PySdkUpdater.fromSdkModificator(sdk, modificator), skeletonsPath);
|
||||
|
||||
UsefulTestCase.edt(new Runnable() {
|
||||
@Override
|
||||
|
||||
@@ -77,10 +77,58 @@ public class MapExternalResourceDialog extends DialogWrapper {
|
||||
private final FileSystemTreeImpl myExplorer;
|
||||
private String myLocation;
|
||||
|
||||
public MapExternalResourceDialog(String uri, @NotNull Project project, @Nullable PsiFile file, @Nullable String location) {
|
||||
public MapExternalResourceDialog(String uri, @Nullable Project project, @Nullable PsiFile file, @Nullable String location) {
|
||||
super(project);
|
||||
setTitle("Map External Resource");
|
||||
myUri.setText(uri);
|
||||
myUri.getDocument().addDocumentListener(new DocumentAdapter() {
|
||||
@Override
|
||||
protected void textChanged(DocumentEvent e) {
|
||||
validateInput();
|
||||
}
|
||||
});
|
||||
|
||||
myExplorer = new FileSystemTreeImpl(project, new FileChooserDescriptor(true, false, false, false, true, false));
|
||||
Disposer.register(getDisposable(), myExplorer);
|
||||
|
||||
myExplorer.addListener(new FileSystemTree.Listener() {
|
||||
@Override
|
||||
public void selectionChanged(List<VirtualFile> selection) {
|
||||
validateInput();
|
||||
}
|
||||
}, myExplorer);
|
||||
|
||||
MouseAdapter mouseAdapter = new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (e.getClickCount() > 1 && isOKActionEnabled()) {
|
||||
doOKAction();
|
||||
}
|
||||
}
|
||||
};
|
||||
myExplorer.getTree().addMouseListener(mouseAdapter);
|
||||
|
||||
myExplorerPanel.add(ScrollPaneFactory.createScrollPane(myExplorer.getTree()), BorderLayout.CENTER);
|
||||
|
||||
AnAction actionGroup = ActionManager.getInstance().getAction("FileChooserToolbar");
|
||||
ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, (ActionGroup)actionGroup, true);
|
||||
toolbar.setTargetComponent(myExplorerPanel);
|
||||
myExplorerPanel.add(toolbar.getComponent(), BorderLayout.NORTH);
|
||||
|
||||
if (project != null) {
|
||||
setupSchemasTab(uri, project, file, location, mouseAdapter);
|
||||
}
|
||||
else {
|
||||
myTabs.removeTabAt(0);
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
private void setupSchemasTab(String uri,
|
||||
@NotNull Project project,
|
||||
@Nullable PsiFile file,
|
||||
@Nullable String location,
|
||||
MouseAdapter mouseAdapter) {
|
||||
|
||||
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
|
||||
mySchemasTree.setModel(new DefaultTreeModel(root));
|
||||
@@ -120,22 +168,7 @@ public class MapExternalResourceDialog extends DialogWrapper {
|
||||
renderer.setFont(EditorColorsManager.getInstance().getGlobalScheme().getFont(EditorFontType.PLAIN));
|
||||
|
||||
mySchemasTree.setCellRenderer(renderer);
|
||||
MouseAdapter mouseAdapter = new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (e.getClickCount() > 1 && isOKActionEnabled()) {
|
||||
doOKAction();
|
||||
}
|
||||
}
|
||||
};
|
||||
mySchemasTree.addMouseListener(mouseAdapter);
|
||||
|
||||
myUri.getDocument().addDocumentListener(new DocumentAdapter() {
|
||||
@Override
|
||||
protected void textChanged(DocumentEvent e) {
|
||||
validateInput();
|
||||
}
|
||||
});
|
||||
mySchemasTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
|
||||
@Override
|
||||
public void valueChanged(TreeSelectionEvent e) {
|
||||
@@ -143,24 +176,6 @@ public class MapExternalResourceDialog extends DialogWrapper {
|
||||
}
|
||||
});
|
||||
|
||||
myExplorer = new FileSystemTreeImpl(project, new FileChooserDescriptor(true, false, false, false, true, false));
|
||||
Disposer.register(getDisposable(), myExplorer);
|
||||
|
||||
myExplorer.addListener(new FileSystemTree.Listener() {
|
||||
@Override
|
||||
public void selectionChanged(List<VirtualFile> selection) {
|
||||
validateInput();
|
||||
}
|
||||
}, myExplorer);
|
||||
myExplorer.getTree().addMouseListener(mouseAdapter);
|
||||
|
||||
myExplorerPanel.add(ScrollPaneFactory.createScrollPane(myExplorer.getTree()), BorderLayout.CENTER);
|
||||
|
||||
AnAction actionGroup = ActionManager.getInstance().getAction("FileChooserToolbar");
|
||||
ActionToolbar toolbar = ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, (ActionGroup)actionGroup, true);
|
||||
toolbar.setTargetComponent(myExplorerPanel);
|
||||
myExplorerPanel.add(toolbar.getComponent(), BorderLayout.NORTH);
|
||||
|
||||
PsiFile schema = null;
|
||||
if (file != null) {
|
||||
schema = XmlUtil.findNamespaceByLocation(file, uri);
|
||||
@@ -188,7 +203,6 @@ public class MapExternalResourceDialog extends DialogWrapper {
|
||||
PropertiesComponent.getInstance().setValue(MAP_EXTERNAL_RESOURCE_SELECTED_TAB, Integer.toString(myTabs.getSelectedIndex()));
|
||||
}
|
||||
});
|
||||
init();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -220,7 +234,7 @@ public class MapExternalResourceDialog extends DialogWrapper {
|
||||
public String getResourceLocation() {
|
||||
if (myLocation != null) return myLocation;
|
||||
|
||||
if (myTabs.getSelectedIndex() == 0) {
|
||||
if (myTabs.getTabCount() > 1 && myTabs.getSelectedIndex() == 0) {
|
||||
TreePath path = mySchemasTree.getSelectionPath();
|
||||
if (path == null) return null;
|
||||
Object object = ((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
|
||||
|
||||
Reference in New Issue
Block a user