diff --git a/community-resources/src/idea/IdeaApplicationInfo.xml b/community-resources/src/idea/IdeaApplicationInfo.xml
index c72056508335..f37ae2c10a0e 100644
--- a/community-resources/src/idea/IdeaApplicationInfo.xml
+++ b/community-resources/src/idea/IdeaApplicationInfo.xml
@@ -4,7 +4,7 @@
-
+
diff --git a/community-resources/src/idea_community_about.png b/community-resources/src/idea_community_about.png
index d70f9e0bb45e..3d15b0a762f9 100644
Binary files a/community-resources/src/idea_community_about.png and b/community-resources/src/idea_community_about.png differ
diff --git a/community-resources/src/idea_community_about@2x.png b/community-resources/src/idea_community_about@2x.png
index 6d33c8779f35..cb3a2035f09a 100644
Binary files a/community-resources/src/idea_community_about@2x.png and b/community-resources/src/idea_community_about@2x.png differ
diff --git a/community-resources/src/idea_community_logo.png b/community-resources/src/idea_community_logo.png
index 4802436fdf5b..ce56a20d19e1 100644
Binary files a/community-resources/src/idea_community_logo.png and b/community-resources/src/idea_community_logo.png differ
diff --git a/community-resources/src/idea_community_logo@2x.png b/community-resources/src/idea_community_logo@2x.png
index 623e731b8506..73eb6056501c 100644
Binary files a/community-resources/src/idea_community_logo@2x.png and b/community-resources/src/idea_community_logo@2x.png differ
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java
index 69de5260feb6..cfa3e6624735 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java
@@ -21,6 +21,7 @@ import com.intellij.codeInspection.dataFlow.inliner.*;
import com.intellij.codeInspection.dataFlow.instructions.*;
import com.intellij.codeInspection.dataFlow.value.*;
import com.intellij.codeInspection.dataFlow.value.DfaRelationValue.RelationType;
+import com.intellij.lang.jvm.JvmModifier;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.registry.Registry;
@@ -77,11 +78,31 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
myAssertionError = createClassType(scope, JAVA_LANG_ASSERTION_ERROR);
}
+ private void buildClassInitializerFlow(PsiClass psiClass, boolean isStatic) {
+ pushUnknown();
+ ConditionalGotoInstruction conditionalGoto = new ConditionalGotoInstruction(null, false, null);
+ addInstruction(conditionalGoto);
+ for (PsiElement element : psiClass.getChildren()) {
+ if ((element instanceof PsiField || element instanceof PsiClassInitializer) &&
+ ((PsiModifierListOwner)element).hasModifier(JvmModifier.STATIC) == isStatic) {
+ element.accept(this);
+ }
+ }
+ addInstruction(new FlushVariableInstruction(null));
+ conditionalGoto.setOffset(getInstructionCount());
+ }
+
@Nullable
public ControlFlow buildControlFlow() {
myCurrentFlow = new ControlFlow(myFactory);
try {
- myCodeFragment.accept(this);
+ if(myCodeFragment instanceof PsiClass) {
+ // if(unknown) { staticInitializer(); } if(unknown) { instanceInitializer(); }
+ buildClassInitializerFlow((PsiClass)myCodeFragment, true);
+ buildClassInitializerFlow((PsiClass)myCodeFragment, false);
+ } else {
+ myCodeFragment.accept(this);
+ }
}
catch (CannotAnalyzeException e) {
return null;
@@ -271,6 +292,20 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
if (initializer != null) {
initializeVariable(field, initializer);
}
+ else if (!field.hasModifier(JvmModifier.FINAL)) {
+ // initialize with default value
+ DfaVariableValue dfaVariable = myFactory.getVarFactory().createVariableValue(field, false);
+ addInstruction(new PushInstruction(dfaVariable, null, true));
+ addInstruction(new PushInstruction(
+ myFactory.getConstFactory().createFromValue(PsiTypesUtil.getDefaultValue(field.getType()), field.getType(), null), null));
+ addInstruction(new AssignInstruction(null, dfaVariable));
+ addInstruction(new PopInstruction());
+ }
+ }
+
+ @Override
+ public void visitClassInitializer(PsiClassInitializer initializer) {
+ visitCodeBlock(initializer.getBody());
}
private void initializeVariable(PsiVariable variable, PsiExpression initializer) {
@@ -1029,7 +1064,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
if (componentType != null) {
generateBoxingUnboxingInstructionFor(initializer, componentType);
if (componentNullability == Nullness.NOT_NULL) {
- addInstruction(new CheckNotNullInstruction(initializer, NullabilityProblem.assigningToNotNull));
+ addInstruction(new CheckNotNullInstruction(initializer, NullabilityProblem.storingToNotNullArray));
}
}
addInstruction(new PopInstruction());
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java
index 6db91af441a6..42583ee11214 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java
@@ -108,8 +108,8 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
return new JavaElementVisitor() {
@Override
- public void visitField(PsiField field) {
- analyzeCodeBlock(field, holder, isOnTheFly);
+ public void visitClass(PsiClass aClass) {
+ analyzeCodeBlock(aClass, holder, isOnTheFly);
}
@Override
@@ -118,11 +118,6 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
analyzeNullLiteralMethodArguments(method, holder, isOnTheFly);
}
- @Override
- public void visitClassInitializer(PsiClassInitializer initializer) {
- analyzeCodeBlock(initializer.getBody(), holder, isOnTheFly);
- }
-
@Override
public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) {
super.visitMethodReferenceExpression(expression);
@@ -190,7 +185,7 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
private void analyzeCodeBlock(@Nullable final PsiElement scope, ProblemsHolder holder, final boolean onTheFly) {
if (scope == null) return;
- PsiClass containingClass = PsiTreeUtil.getParentOfType(scope, PsiClass.class);
+ PsiClass containingClass = PsiTreeUtil.getParentOfType(scope, PsiClass.class, false);
if (containingClass != null && PsiUtil.isLocalOrAnonymousClass(containingClass) && !(containingClass instanceof PsiEnumConstantInitializer)) return;
final StandardDataFlowRunner dfaRunner =
@@ -200,6 +195,7 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
private static boolean isInsideConstructorOrInitializer(PsiElement element) {
while (element != null) {
+ if (element instanceof PsiClass) return true;
element = PsiTreeUtil.getParentOfType(element, PsiMethod.class, PsiClassInitializer.class);
if (element instanceof PsiClassInitializer) return true;
if (element instanceof PsiMethod) {
@@ -249,12 +245,17 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
}
}
else if (rc == RunnerResult.TOO_COMPLEX) {
- if (scope.getParent() instanceof PsiMethod) {
- PsiMethod method = (PsiMethod)scope.getParent();
- final PsiIdentifier name = method.getNameIdentifier();
- if (name != null) { // Might be null for synthetic methods like JSP page.
- holder.registerProblem(name, InspectionsBundle.message("dataflow.too.complex"), ProblemHighlightType.WEAK_WARNING);
- }
+ PsiIdentifier name = null;
+ String message = null;
+ if(scope.getParent() instanceof PsiMethod) {
+ name = ((PsiMethod)scope.getParent()).getNameIdentifier();
+ message = InspectionsBundle.message("dataflow.too.complex");
+ } else if(scope instanceof PsiClass) {
+ name = ((PsiClass)scope).getNameIdentifier();
+ message = InspectionsBundle.message("dataflow.too.complex.class");
+ }
+ if (name != null) { // Might be null for synthetic methods like JSP page.
+ holder.registerProblem(name, message, ProblemHighlightType.WEAK_WARNING);
}
}
}
@@ -324,7 +325,7 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
reportNullableFunctions(visitor, holder, reportedAnchors);
reportNullableArguments(visitor, holder, reportedAnchors);
- reportNullableAssignments(visitor, holder, reportedAnchors);
+ reportNullableAssignments(visitor, holder, reportedAnchors, onTheFly);
reportUnboxedNullables(visitor, holder, reportedAnchors);
reportNullableReturns(visitor, holder, reportedAnchors, scope);
if (SUGGEST_NULLABLE_ANNOTATIONS) {
@@ -681,14 +682,29 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool {
}
}
- private static void reportNullableAssignments(DataFlowInstructionVisitor visitor, ProblemsHolder holder, Set reportedAnchors) {
+ private void reportNullableAssignments(DataFlowInstructionVisitor visitor,
+ ProblemsHolder holder,
+ Set reportedAnchors,
+ boolean onTheFly) {
for (PsiElement expr : visitor.getProblems(NullabilityProblem.assigningToNotNull)) {
if (!reportedAnchors.add(expr)) continue;
+ assert expr instanceof PsiExpression;
final String text = isNullLiteralExpression(expr)
? InspectionsBundle.message("dataflow.message.assigning.null")
: InspectionsBundle.message("dataflow.message.assigning.nullable");
- holder.registerProblem(expr, text);
+ holder.registerProblem(expr, text,
+ createNPEFixes((PsiExpression)expr, (PsiExpression)expr, onTheFly).toArray(LocalQuickFix.EMPTY_ARRAY));
+ }
+ for (PsiElement expr : visitor.getProblems(NullabilityProblem.storingToNotNullArray)) {
+ if (!reportedAnchors.add(expr)) continue;
+ assert expr instanceof PsiExpression;
+
+ final String text = isNullLiteralExpression(expr)
+ ? InspectionsBundle.message("dataflow.message.storing.array.null")
+ : InspectionsBundle.message("dataflow.message.storing.array.nullable");
+ holder.registerProblem(expr, text,
+ createNPEFixes((PsiExpression)expr, (PsiExpression)expr, onTheFly).toArray(LocalQuickFix.EMPTY_ARRAY));
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java
index bc16cb37b09b..dfb0a88628d7 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java
@@ -26,7 +26,10 @@ import com.intellij.psi.*;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.tree.IElementType;
-import com.intellij.psi.util.*;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.util.CachedValuesManager;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.FList;
@@ -195,24 +198,16 @@ public class DfaUtil {
}
static DfaValue getPossiblyNonInitializedValue(@NotNull DfaValueFactory factory, @NotNull PsiField target, @NotNull PsiElement context) {
- PsiMember placeMember = PsiTreeUtil.getParentOfType(context, PsiMember.class, false, PsiClass.class, PsiLambdaExpression.class);
- PsiType type = target.getType();
- if (placeMember == null || type instanceof PsiPrimitiveType && !(placeMember instanceof PsiField)) return null;
+ if (target.getType() instanceof PsiPrimitiveType) return null;
+ PsiMethod placeMethod = PsiTreeUtil.getParentOfType(context, PsiMethod.class, false, PsiClass.class, PsiLambdaExpression.class);
+ if (placeMethod == null) return null;
- PsiClass placeClass = placeMember.getContainingClass();
- if (placeClass != null && placeClass == target.getContainingClass()) {
- if (!placeMember.hasModifier(JvmModifier.STATIC) && target.hasModifier(JvmModifier.STATIC)) {
- return null;
- }
+ PsiClass placeClass = placeMethod.getContainingClass();
+ if (placeClass == null || placeClass != target.getContainingClass()) return null;
+ if (!placeMethod.hasModifier(JvmModifier.STATIC) && target.hasModifier(JvmModifier.STATIC)) return null;
+ if (getAccessOffset(placeMethod) >= getWriteOffset(target)) return null;
- if(getAccessOffset(placeMember) >= getWriteOffset(target)) {
- return null;
- }
- return placeMember instanceof PsiField
- ? factory.getConstFactory().createFromValue(PsiTypesUtil.getDefaultValue(type), type, null)
- : factory.createTypeValue(type, Nullness.NULLABLE);
- }
- return null;
+ return factory.createTypeValue(target.getType(), Nullness.NULLABLE);
}
private static int getWriteOffset(PsiField target) {
@@ -256,26 +251,21 @@ public class DfaUtil {
return offset;
}
- private static int getAccessOffset(PsiMember referrer) {
- if (referrer instanceof PsiField) {
- return referrer.getTextRange().getStartOffset();
- }
+ private static int getAccessOffset(PsiMethod referrer) {
PsiClass aClass = Objects.requireNonNull(referrer.getContainingClass());
- if (referrer instanceof PsiMethod) {
- boolean isStatic = referrer.hasModifier(JvmModifier.STATIC);
- for (PsiField field : aClass.getFields()) {
- if (field.hasModifier(JvmModifier.STATIC) != isStatic) continue;
- PsiExpression initializer = field.getInitializer();
- Predicate callToMethod = (PsiExpression e) -> {
- if (!(e instanceof PsiMethodCallExpression)) return false;
- PsiMethodCallExpression call = (PsiMethodCallExpression)e;
- return call.getMethodExpression().isReferenceTo(referrer) &&
- (isStatic || DfaValueFactory.isEffectivelyUnqualified(call.getMethodExpression()));
- };
- if (ExpressionUtils.isMatchingChildAlwaysExecuted(initializer, callToMethod)) {
- // current method is definitely called from some field initialization
- return field.getTextRange().getStartOffset();
- }
+ boolean isStatic = referrer.hasModifier(JvmModifier.STATIC);
+ for (PsiField field : aClass.getFields()) {
+ if (field.hasModifier(JvmModifier.STATIC) != isStatic) continue;
+ PsiExpression initializer = field.getInitializer();
+ Predicate callToMethod = (PsiExpression e) -> {
+ if (!(e instanceof PsiMethodCallExpression)) return false;
+ PsiMethodCallExpression call = (PsiMethodCallExpression)e;
+ return call.getMethodExpression().isReferenceTo(referrer) &&
+ (isStatic || DfaValueFactory.isEffectivelyUnqualified(call.getMethodExpression()));
+ };
+ if (ExpressionUtils.isMatchingChildAlwaysExecuted(initializer, callToMethod)) {
+ // current method is definitely called from some field initialization
+ return field.getTextRange().getStartOffset();
}
}
return Integer.MAX_VALUE; // accessed after initialization or at unknown moment
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/NullabilityProblem.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/NullabilityProblem.java
index b5c62a649954..36e738d67e8d 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/NullabilityProblem.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/NullabilityProblem.java
@@ -8,6 +8,7 @@ public enum NullabilityProblem {
fieldAccessNPE,
unboxingNullable,
assigningToNotNull,
+ storingToNotNullArray,
nullableReturn,
nullableFunctionReturn,
passingNullableToNotNullParameter,
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java
index 9ee4c874c25b..bf5a01b4ffce 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java
@@ -72,13 +72,16 @@ public class StandardInstructionVisitor extends InstructionVisitor {
dfaDest = instruction.getAssignedValue();
}
+ NullabilityProblem problem = PsiUtil.skipParenthesizedExprDown(instruction.getLExpression()) instanceof PsiArrayAccessExpression ?
+ NullabilityProblem.storingToNotNullArray : NullabilityProblem.assigningToNotNull;
+
if (dfaDest instanceof DfaVariableValue) {
DfaVariableValue var = (DfaVariableValue) dfaDest;
final PsiModifierListOwner psi = var.getPsiVariable();
boolean forceDeclaredNullity = !(psi instanceof PsiParameter && psi.getParent() instanceof PsiParameterList);
if (forceDeclaredNullity && var.getInherentNullability() == Nullness.NOT_NULL) {
- checkNotNullable(memState, dfaSource, NullabilityProblem.assigningToNotNull, instruction.getRExpression());
+ checkNotNullable(memState, dfaSource, problem, instruction.getRExpression());
}
if (!(psi instanceof PsiField) || !psi.hasModifierProperty(PsiModifier.VOLATILE)) {
memState.setVarValue(var, dfaSource);
@@ -89,7 +92,7 @@ public class StandardInstructionVisitor extends InstructionVisitor {
}
} else if (dfaDest instanceof DfaTypeValue && ((DfaTypeValue)dfaDest).isNotNull()) {
- checkNotNullable(memState, dfaSource, NullabilityProblem.assigningToNotNull, instruction.getRExpression());
+ checkNotNullable(memState, dfaSource, problem, instruction.getRExpression());
}
memState.push(dfaDest);
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/AssignInstruction.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/AssignInstruction.java
index 38b7b98edf10..d6260c15d9a2 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/AssignInstruction.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/AssignInstruction.java
@@ -21,6 +21,7 @@ import com.intellij.codeInspection.dataFlow.DfaInstructionState;
import com.intellij.codeInspection.dataFlow.DfaMemoryState;
import com.intellij.codeInspection.dataFlow.InstructionVisitor;
import com.intellij.codeInspection.dataFlow.value.DfaValue;
+import com.intellij.psi.PsiAssignmentExpression;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiVariable;
import org.jetbrains.annotations.Nullable;
@@ -44,6 +45,15 @@ public class AssignInstruction extends Instruction {
return myRExpression;
}
+ @Nullable
+ public PsiExpression getLExpression() {
+ if(myRExpression == null) return null;
+ if(myRExpression.getParent() instanceof PsiAssignmentExpression) {
+ return ((PsiAssignmentExpression)myRExpression.getParent()).getLExpression();
+ }
+ return null;
+ }
+
public boolean isVariableInitializer() {
return myRExpression != null && myRExpression.getParent() instanceof PsiVariable;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GuessTypeParameters.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GuessTypeParameters.java
index bc301e221951..c83ae090624c 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GuessTypeParameters.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GuessTypeParameters.java
@@ -80,6 +80,8 @@ public class GuessTypeParameters {
return;
}
+ typeElement = (PsiTypeElement)typeElement.replace(JavaPsiFacade.getElementFactory(myProject).createTypeElement(info.getType()));
+
PsiSubstitutor rawingSubstitutor = getRawingSubstitutor(myProject, context, targetClass);
int substitionResult = hasNullSubstitutions(mySubstitutor)
? SUBSTITUTED_NONE
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/JavaCreateFieldFromUsageHelper.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/JavaCreateFieldFromUsageHelper.java
index 29219d6aa559..4ddd17376bc3 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/JavaCreateFieldFromUsageHelper.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/JavaCreateFieldFromUsageHelper.java
@@ -58,8 +58,10 @@ public class JavaCreateFieldFromUsageHelper extends CreateFieldFromUsageHelper {
builder.replaceElement(field.getInitializer(), new EmptyExpression());
PsiIdentifier identifier = field.getNameIdentifier();
builder.setEndVariableAfter(identifier);
- field = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(field);
}
+
+ field = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(field);
+
editor.getCaretModel().moveToOffset(field.getTextRange().getStartOffset());
Template template = builder.buildInlineTemplate();
if (ExpectedTypesProvider.processExpectedTypes((ExpectedTypeInfo[])expectedTypes, new PsiTypeVisitor() {
diff --git a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java
index f28fe9c2c6ea..96e1c27f8c61 100644
--- a/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/copy/CopyClassesHandler.java
@@ -84,6 +84,7 @@ public class CopyClassesHandler extends CopyHandlerDelegateBase {
final PsiFile containingFile = navigationElement.getContainingFile();
if (!(containingFile instanceof PsiClassOwner &&
JavaProjectRootsUtil.isOutsideJavaSourceRoot(containingFile))) {
+ if (PsiPackage.PACKAGE_INFO_CLS_FILE.equals(containingFile.getName())) continue;
PsiClass[] topLevelClasses = getTopLevelClasses(element);
if (topLevelClasses == null) {
if (element instanceof PsiDirectory) {
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java
index 770f67bff837..3174948bfdfd 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java
@@ -44,7 +44,7 @@ public class OverrideImplementExploreUtil {
Map finals = new LinkedHashMap<>();
Map concretes = new LinkedHashMap<>();
- if (aClass.isAnnotationType()) return Collections.emptyMap();
+ if (aClass.isAnnotationType() || aClass instanceof PsiTypeParameter) return Collections.emptyMap();
PsiUtilCore.ensureValid(aClass);
Collection allMethodSigs = aClass.getVisibleSignatures();
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiDiamondTypeUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiDiamondTypeUtil.java
index 4681764c4ff0..6a04c16d6ce0 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiDiamondTypeUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiDiamondTypeUtil.java
@@ -153,9 +153,8 @@ public class PsiDiamondTypeUtil {
typeElement = ((PsiVariable)gParent).getTypeElement();
}
else if (gParent instanceof PsiReturnStatement) {
- PsiMethod method = PsiTreeUtil.getParentOfType(gParent, PsiMethod.class);
- LOG.assertTrue(method != null);
- typeElement = method.getReturnTypeElement();
+ PsiElement method = PsiTreeUtil.getParentOfType(gParent, PsiMethod.class, PsiLambdaExpression.class);
+ typeElement = method instanceof PsiMethod ? ((PsiMethod)method).getReturnTypeElement() : null;
}
return typeElement != null && PsiAugmentProvider.getInferredType(typeElement) != null;
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/afterTypeParameterBound.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/afterTypeParameterBound.java
new file mode 100644
index 000000000000..3ecab1b9f6fa
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/afterTypeParameterBound.java
@@ -0,0 +1,10 @@
+// "Make 'T' implement 'b'" "true"
+class a> {
+ void f(b r, T t) {
+ r.g(t);
+ }
+}
+interface b {
+ void g(b t);
+}
+
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/beforeTypeParameterBound.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/beforeTypeParameterBound.java
new file mode 100644
index 000000000000..f84b4c1ef641
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/beforeTypeParameterBound.java
@@ -0,0 +1,10 @@
+// "Make 'T' implement 'b'" "true"
+class a {
+ void f(b r, T t) {
+ r.g(t);
+ }
+}
+interface b {
+ void g(b t);
+}
+
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/afterInnerGeneric.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/afterInnerGeneric.java
new file mode 100644
index 000000000000..d92d3daeafda
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/afterInnerGeneric.java
@@ -0,0 +1,12 @@
+// "Create field 'foo'" "true"
+class Usage {
+
+ void usage(Generic g, List p) {
+ g.foo = p;
+ }
+}
+
+class Generic {
+
+ public List foo;
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/afterInnerGenericArray.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/afterInnerGenericArray.java
new file mode 100644
index 000000000000..7f974cd5c2e5
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/afterInnerGenericArray.java
@@ -0,0 +1,12 @@
+// "Create field 'foo'" "true"
+class Usage {
+
+ void usage(Generic g, List[] p) {
+ g.foo = p;
+ }
+}
+
+class Generic {
+
+ public List[] foo;
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/beforeInnerGeneric.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/beforeInnerGeneric.java
new file mode 100644
index 000000000000..5bc4ca00a7c6
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/beforeInnerGeneric.java
@@ -0,0 +1,11 @@
+// "Create field 'foo'" "true"
+class Usage {
+
+ void usage(Generic g, List p) {
+ g.foo = p;
+ }
+}
+
+class Generic {
+
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/beforeInnerGenericArray.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/beforeInnerGenericArray.java
new file mode 100644
index 000000000000..ccb038f44716
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createFieldFromUsage/beforeInnerGenericArray.java
@@ -0,0 +1,11 @@
+// "Create field 'foo'" "true"
+class Usage {
+
+ void usage(Generic g, List[] p) {
+ g.foo = p;
+ }
+}
+
+class Generic {
+
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after6.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after6.java
new file mode 100644
index 000000000000..883b188ee1e7
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/after6.java
@@ -0,0 +1,11 @@
+// "Create method 'foo'" "true"
+interface Generic {
+ List> foo();
+}
+
+class Usage {
+
+ List> usage(Generic g) {
+ return g.foo();
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/before6.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/before6.java
new file mode 100644
index 000000000000..265fafb3fbae
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage/before6.java
@@ -0,0 +1,10 @@
+// "Create method 'foo'" "true"
+interface Generic {
+}
+
+class Usage {
+
+ List> usage(Generic g) {
+ return g.foo();
+ }
+}
diff --git a/java/java-tests/testData/inspection/dataFlow/SCR39950/src/Test.java b/java/java-tests/testData/inspection/dataFlow/SCR39950/src/Test.java
index c31d7cff7cc9..a672e8ac0f47 100644
--- a/java/java-tests/testData/inspection/dataFlow/SCR39950/src/Test.java
+++ b/java/java-tests/testData/inspection/dataFlow/SCR39950/src/Test.java
@@ -6,7 +6,7 @@ class TestGenericsInstanceof
{
I member;
- {
+ void test() {
boolean test = member instanceof Impl;
}
}
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ArrayComponentAndMethodAnnotationConflict.java b/java/java-tests/testData/inspection/dataFlow/fixture/ArrayComponentAndMethodAnnotationConflict.java
index b1874526dad1..2b58f950ec77 100644
--- a/java/java-tests/testData/inspection/dataFlow/fixture/ArrayComponentAndMethodAnnotationConflict.java
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/ArrayComponentAndMethodAnnotationConflict.java
@@ -19,10 +19,17 @@ class FooImpl implements Foo {
return null;
}
else if (Math.random() > 0.5) {
- @NotNull Object @Nullable [] arr1 = new Object[]{null, new Object(), Math.random() > 0.5 ? new Object() : null};
- @NotNull Object @Nullable [] arr2 = {null, new Object(), Math.random() > 0.5 ? new Object() : null};
- return new Object[]{null, new Object(), Math.random() > 0.5 ? new Object() : null};
+ @NotNull Object @Nullable [] arr1 = new Object[]{null, new Object(), Math.random() > 0.5 ? new Object() : null};
+ @NotNull Object @Nullable [] arr2 = {null, new Object(), Math.random() > 0.5 ? new Object() : null};
+ return new Object[]{null, new Object(), Math.random() > 0.5 ? new Object() : null};
}
- return new @NotNull Object @Nullable []{null, new Object(), Math.random() > 0.5 ? new Object() : null};
+ return new @NotNull Object @Nullable []{null, new Object(), Math.random() > 0.5 ? new Object() : null};
+ }
+
+ void test() {
+ @NotNull Object @Nullable [] array = getNullableArrayOfNotNullObjects();
+ assert array != null;
+ array[0] = null;
+ array[1] = Math.random() > 0.5 ? null : "foo";
}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ComplexInitializer.java b/java/java-tests/testData/inspection/dataFlow/fixture/ComplexInitializer.java
new file mode 100644
index 000000000000..952fbfbab8e9
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/ComplexInitializer.java
@@ -0,0 +1,87 @@
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+class InitializerTest {
+ int x = Math.random() > 0.5 ? 0 : 1;
+ int y = x < 2 ? 5 : 6;
+ String z;
+
+ {
+ if(y == 6) {
+ System.out.println("oops");
+ }
+ z = "foo";
+ }
+
+ boolean b = z.startsWith("bar");
+
+ static final String ABC;
+ static {
+ if(Math.random() > 0.5) {
+ ABC = null;
+ } else {
+ ABC = "foo";
+ }
+ }
+
+ static final String XYZ = ABC.toLowerCase();
+
+ static {
+ new InitializerTest(); // INITIALIZED is not initialized yet here
+ }
+
+ static final String INITIALIZED = "xyz".trim();
+
+ {
+ if(INITIALIZED == null) {
+ System.out.println("Class is not initialized yet");
+ }
+ }
+
+ static {
+ if(INITIALIZED == null) {
+ System.out.println("Class is not initialized yet");
+ }
+ }
+}
+
+class Constants {
+ static final Object C1 = get();
+ static final Object C2 = get();
+ static final Object C3 = get();
+ static final Object C4 = get();
+ static final Object C5 = get();
+ static final Object C6 = get();
+ static final Object C7 = get();
+ static final Object C8 = get();
+ static final Object C9 = get();
+ static final Object C10 = get();
+ static final Object C11 = get();
+
+ static Object get() {return new Object();}
+}
+
+class TooComplexInitializer {
+ // This test just checks that "too complex" warning is placed correctly on class name,
+ // not that this particular code always must be considered as "too complex".
+ // If in future this code will become not too complex, that's fine, just update test to make it even more complex
+ static {
+ int i = 1;
+ for(Object obj = Constants.get(); obj != Constants.C5; obj = Constants.get()) {
+ if (obj == Constants.C1) i = 2;
+ if (obj == Constants.C2) i = 3;
+ if (obj == Constants.C3) i = 4;
+ if (obj == Constants.C4) i = 5;
+ if (obj == Constants.C5) i = 6;
+ if (obj == Constants.C6) i = 7;
+ if (obj == Constants.C7) i = 8;
+ if (obj == Constants.C8) i = 9;
+ if (obj == Constants.C9) i = 10;
+ if (obj == Constants.C10) i = 11;
+ if (obj == Constants.C11) i = 12;
+ if (i > 5 && obj == Constants.C3) {
+ System.out.println("Never?");
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/FieldUsedBeforeInitialization.java b/java/java-tests/testData/inspection/dataFlow/fixture/FieldUsedBeforeInitialization.java
index f9ddb5c1a88b..bb5539b072d0 100644
--- a/java/java-tests/testData/inspection/dataFlow/fixture/FieldUsedBeforeInitialization.java
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/FieldUsedBeforeInitialization.java
@@ -87,8 +87,7 @@ class NonFinalInitialized {
class NonFinalAssignedInside {
String x;
- // Should warn on the first trim
- String y = x.trim()+(x = " foo ").trim();
+ String y = x.trim()+(x = " foo ").trim();
String z = x.trim();
}
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/HonorGetterAnnotation.java b/java/java-tests/testData/inspection/dataFlow/fixture/HonorGetterAnnotation.java
index 0b3d76b5f59c..255f598d504f 100644
--- a/java/java-tests/testData/inspection/dataFlow/fixture/HonorGetterAnnotation.java
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/HonorGetterAnnotation.java
@@ -3,7 +3,7 @@ import org.jetbrains.annotations.Nullable;
class Goo {
Permission permission;
- {
+ void test() {
Object category = permission.getCategory();
System.out.println(category.hashCode());
}
diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/CreateFieldFromUsageTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/CreateFieldFromUsageTest.java
index b6d38eb8cd40..7d6d8d04fb55 100644
--- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/CreateFieldFromUsageTest.java
+++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/quickFix/CreateFieldFromUsageTest.java
@@ -84,6 +84,10 @@ public class CreateFieldFromUsageTest extends LightQuickFixTestCase {
doSingleTest();
}
+ public void testInnerGeneric() { doSingleTest(); }
+
+ public void testInnerGenericArray() { doSingleTest(); }
+
protected void doSingleTest() {
doSingleTest(getTestName(false) + ".java");
}
diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionHeavyTest.groovy b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionHeavyTest.groovy
index f7c920d98418..de6082e4915e 100644
--- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionHeavyTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionHeavyTest.groovy
@@ -50,7 +50,7 @@ class DataFlowInspectionHeavyTest extends JavaCodeInsightFixtureTestCase {
def testFile = myFixture.addFileToProject 'test.java', '''
class Zoo {
@annos.Nullable String a = null;
- @annos.NotNull String f = foo.ObjectUtils.notNull(a);
+ @annos.NotNull String f = foo.ObjectUtils.notNull(a);
void bar(@annos.NotNull String param) { }
void goo(@annos.Nullable String param) {
diff --git a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java
index 622faa144912..bc00b4e7b5ba 100644
--- a/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java
+++ b/java/java-tests/testSrc/com/intellij/java/codeInspection/DataFlowInspectionTest.java
@@ -536,4 +536,5 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase {
public void testEmptySingletonMap() {doTest();}
public void testStaticFieldsWithNewObjects() { doTest(); }
+ public void testComplexInitializer() { doTest(); }
}
diff --git a/platform/core-impl/src/com/intellij/psi/DummyHolderViewProvider.java b/platform/core-impl/src/com/intellij/psi/DummyHolderViewProvider.java
index 44e09b559978..32bc8e76c8ff 100644
--- a/platform/core-impl/src/com/intellij/psi/DummyHolderViewProvider.java
+++ b/platform/core-impl/src/com/intellij/psi/DummyHolderViewProvider.java
@@ -16,15 +16,11 @@
package com.intellij.psi;
import com.intellij.lang.Language;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.fileEditor.FileDocumentManager;
-import com.intellij.openapi.fileTypes.FileType;
-import com.intellij.openapi.util.UserDataHolderBase;
+import com.intellij.openapi.fileTypes.UnknownFileType;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.impl.SharedPsiElementImplUtil;
import com.intellij.psi.impl.source.DummyHolder;
-import com.intellij.psi.impl.source.PsiFileImpl;
+import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.psi.impl.source.tree.LeafElement;
import com.intellij.testFramework.LightVirtualFile;
import com.intellij.util.LocalTimeCounter;
@@ -35,41 +31,21 @@ import java.util.Collections;
import java.util.List;
import java.util.Set;
-public class DummyHolderViewProvider extends UserDataHolderBase implements FileViewProvider{
+public class DummyHolderViewProvider extends AbstractFileViewProvider {
private DummyHolder myHolder;
- private final PsiManager myManager;
private final long myModificationStamp;
- private final LightVirtualFile myLightVirtualFile = new LightVirtualFile("DummyHolder");
public DummyHolderViewProvider(@NotNull PsiManager manager) {
- myManager = manager;
+ super(manager, new LightVirtualFile("DummyHolder"), false, UnknownFileType.INSTANCE);
myModificationStamp = LocalTimeCounter.currentTime();
}
- @Override
- @NotNull
- public PsiManager getManager() {
- return myManager;
- }
-
- @Override
- @Nullable
- public Document getDocument() {
- return FileDocumentManager.getInstance().getDocument(getVirtualFile());
- }
-
@Override
@NotNull
public CharSequence getContents() {
return myHolder != null ? myHolder.getNode().getText() : "";
}
- @Override
- @NotNull
- public VirtualFile getVirtualFile() {
- return myLightVirtualFile;
- }
-
@Override
@NotNull
public Language getBaseLanguage() {
@@ -82,32 +58,33 @@ public class DummyHolderViewProvider extends UserDataHolderBase implements FileV
return Collections.singleton(getBaseLanguage());
}
+ @Nullable
@Override
- public PsiFile getPsi(@NotNull Language target) {
- ((PsiManagerEx)myManager).getFileManager().setViewProvider(getVirtualFile(), this);
+ protected PsiFile getPsiInner(Language target) {
+ return getCachedPsi(target);
+ }
+
+ @Override
+ public PsiFile getCachedPsi(@NotNull Language target) {
+ getManager().getFileManager().setViewProvider(getVirtualFile(), this);
return target == getBaseLanguage() ? myHolder : null;
}
+ @Override
+ public List getCachedPsiFiles() {
+ return Collections.singletonList(myHolder);
+ }
+
+ @NotNull
+ @Override
+ public List getKnownTreeRoots() {
+ return Collections.singletonList(myHolder.getTreeElement());
+ }
+
@Override
@NotNull
public List getAllFiles() {
- return Collections.singletonList(getPsi(getBaseLanguage()));
- }
-
- @Override
- public void beforeContentsSynchronized() {}
-
- @Override
- public void contentsSynchronized() {}
-
- @Override
- public boolean isEventSystemEnabled() {
- return false;
- }
-
- @Override
- public boolean isPhysical() {
- return false;
+ return getCachedPsiFiles();
}
@Override
@@ -115,23 +92,9 @@ public class DummyHolderViewProvider extends UserDataHolderBase implements FileV
return myModificationStamp;
}
- @Override
- public boolean supportsIncrementalReparse(@NotNull final Language rootLanguage) {
- return true;
- }
-
- @Override
- public void rootChanged(@NotNull PsiFile psiFile) {
- }
-
public void setDummyHolder(@NotNull DummyHolder dummyHolder) {
myHolder = dummyHolder;
- myLightVirtualFile.setFileType(dummyHolder.getFileType());
- }
-
- @Override
- public FileViewProvider clone(){
- throw new RuntimeException("Clone is not supported for DummyHolderProviders. Use DummyHolder clone directly.");
+ ((LightVirtualFile)getVirtualFile()).setFileType(dummyHolder.getFileType());
}
@Override
@@ -139,45 +102,21 @@ public class DummyHolderViewProvider extends UserDataHolderBase implements FileV
return SharedPsiElementImplUtil.findReferenceAt(getPsi(getBaseLanguage()), offset);
}
- @Override
- @Nullable
- public PsiElement findElementAt(final int offset, @NotNull final Language language) {
- return language == getBaseLanguage() ? findElementAt(offset) : null;
- }
-
-
@Override
public PsiElement findElementAt(int offset, @NotNull Class extends Language> lang) {
if (!lang.isAssignableFrom(getBaseLanguage().getClass())) return null;
return findElementAt(offset);
}
- @Override
- public PsiReference findReferenceAt(final int offsetInElement, @NotNull final Language language) {
- return language == getBaseLanguage() ? findReferenceAt(offsetInElement) : null;
- }
-
@NotNull
@Override
public FileViewProvider createCopy(@NotNull final VirtualFile copy) {
throw new RuntimeException("Clone is not supported for DummyHolderProviders. Use DummyHolder clone directly.");
}
- @NotNull
- @Override
- public PsiFile getStubBindingRoot() {
- return getPsi(getBaseLanguage());
- }
-
- @NotNull
- @Override
- public FileType getFileType() {
- return myLightVirtualFile.getFileType();
- }
-
@Override
public PsiElement findElementAt(final int offset) {
- final LeafElement element = ((PsiFileImpl)getPsi(getBaseLanguage())).calcTreeElement().findLeafElementAt(offset);
+ final LeafElement element = myHolder.calcTreeElement().findLeafElementAt(offset);
return element != null ? element.getPsi() : null;
}
}
diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java
index ca070a4cd889..f025b73abd88 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java
@@ -427,7 +427,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
}
void forceReload(VirtualFile virtualFile, @Nullable FileViewProvider viewProvider) {
- if (viewProvider instanceof AbstractFileViewProvider) {
+ if (viewProvider != null) {
((AbstractFileViewProvider)viewProvider).markInvalidated();
}
if (virtualFile != null) {
@@ -900,12 +900,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
ApplicationManager.getApplication().runWriteAction(new ExternalChangeAction() {
@Override
public void run() {
- FileViewProvider viewProvider = psiFile.getViewProvider();
- if (viewProvider instanceof AbstractFileViewProvider) {
- ((AbstractFileViewProvider)viewProvider).onContentReload();
- } else {
- LOG.error("Invalid view provider: " + viewProvider + " of " + viewProvider.getClass());
- }
+ ((AbstractFileViewProvider)psiFile.getViewProvider()).onContentReload();
}
});
}
diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiManagerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/PsiManagerImpl.java
index 414522e8bae9..67b2938d42c6 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/PsiManagerImpl.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/PsiManagerImpl.java
@@ -366,7 +366,7 @@ public class PsiManagerImpl extends PsiManagerEx {
for (PsiTreeChangePreprocessor preprocessor : myTreeChangePreprocessors) {
preprocessor.treeChanged(event);
}
- boolean enableOutOfCodeBlockTracking = myModificationTracker.getOutOfCodeBlockModificationTracker() != myModificationTracker;
+ boolean enableOutOfCodeBlockTracking = ((PsiModificationTrackerImpl)myModificationTracker).isEnableCodeBlockTracker();
for (PsiTreeChangePreprocessor preprocessor : Extensions.getExtensions(PsiTreeChangePreprocessor.EP_NAME, myProject)) {
if (!enableOutOfCodeBlockTracking && preprocessor instanceof PsiTreeChangePreprocessorBase) continue;
preprocessor.treeChanged(event);
diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiModificationTrackerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/PsiModificationTrackerImpl.java
index b9653843f218..021edf8be5f4 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/PsiModificationTrackerImpl.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/PsiModificationTrackerImpl.java
@@ -25,6 +25,7 @@ import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.util.SimpleModificationTracker;
import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.util.registry.RegistryValue;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiModificationTracker;
@@ -36,7 +37,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
-import java.util.concurrent.atomic.AtomicLong;
import static com.intellij.psi.impl.PsiTreeChangeEventImpl.PsiEventType.CHILD_MOVED;
import static com.intellij.psi.impl.PsiTreeChangeEventImpl.PsiEventType.PROPERTY_CHANGED;
@@ -46,16 +46,15 @@ import static com.intellij.psi.impl.PsiTreeChangeEventImpl.PsiEventType.PROPERTY
* Date: Jul 18, 2002
*/
public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTreeChangePreprocessor {
- private final boolean myEnableCodeBlockTracker = Registry.is("psi.modification.tracker.code-block");
- private final boolean myEnableJavaStructureTracker = Registry.is("psi.modification.tracker.java-structure");
- private final boolean myEnableLanguageTracker = Registry.is("psi.modification.tracker.per-language");
+ private static final RegistryValue ourEnableCodeBlockTracker = Registry.get("psi.modification.tracker.code-block");
+ private static final RegistryValue ourEnableJavaStructureTracker = Registry.get("psi.modification.tracker.java-structure");
+ private static final RegistryValue ourEnableLanguageTracker = Registry.get("psi.modification.tracker.per-language");
- private final AtomicLong myModificationCount = new AtomicLong(0);
- private final AtomicLong myOutOfCodeBlockModificationCount = myEnableCodeBlockTracker ? new AtomicLong(0) : myModificationCount;
- private final AtomicLong myJavaStructureModificationCount = myEnableJavaStructureTracker ? new AtomicLong(0) : myModificationCount;
+ private final boolean myTestMode = ApplicationManager.getApplication().isUnitTestMode();
- private final ModificationTracker myOutOfCodeBlockModificationTracker = myEnableCodeBlockTracker ? () -> getOutOfCodeBlockModificationCount() : this;
- private final ModificationTracker myJavaStructureModificationTracker = myEnableJavaStructureTracker ? () -> getJavaStructureModificationCount() : this;
+ private final SimpleModificationTracker myModificationCount = new SimpleModificationTracker();
+ private final SimpleModificationTracker myOutOfCodeBlockModificationTracker = wrapped(ourEnableCodeBlockTracker, myModificationCount, myTestMode);
+ private final SimpleModificationTracker myJavaStructureModificationTracker = wrapped(ourEnableJavaStructureTracker, myModificationCount, myTestMode);
private final Map myLanguageTrackers =
ConcurrentFactoryMap.createMap(language -> new SimpleModificationTracker());
@@ -63,7 +62,7 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr
private final Listener myPublisher;
public PsiModificationTrackerImpl(Project project) {
- final MessageBus bus = project.getMessageBus();
+ MessageBus bus = project.getMessageBus();
myPublisher = bus.syncPublisher(TOPIC);
bus.connect().subscribe(DumbService.DUMB_MODE, new DumbService.DumbModeListener() {
private void doIncCounter() {
@@ -83,10 +82,11 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr
}
public void incCounter() {
- myModificationCount.getAndIncrement();
- myJavaStructureModificationCount.getAndIncrement();
- myOutOfCodeBlockModificationCount.getAndIncrement();
- fireEvent();
+ incCountersInner(7);
+ }
+
+ public void incOutOfCodeBlockModificationCounter() {
+ incCountersInner(3);
}
private void fireEvent() {
@@ -94,9 +94,10 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr
myPublisher.modificationCountChanged();
}
- public void incOutOfCodeBlockModificationCounter() {
- myModificationCount.getAndIncrement();
- myOutOfCodeBlockModificationCount.getAndIncrement();
+ private void incCountersInner(int bits) {
+ if ((bits & 0x1) != 0) myModificationCount.incModificationCount();
+ if ((bits & 0x2) != 0) myOutOfCodeBlockModificationTracker.incModificationCount();
+ if ((bits & 0x4) != 0) myJavaStructureModificationTracker.incModificationCount();
fireEvent();
}
@@ -114,12 +115,7 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr
code == CHILD_MOVED ? event.getOldParent() instanceof PsiDirectory || event.getNewParent() instanceof PsiDirectory :
event.getParent() instanceof PsiDirectory;
- myModificationCount.getAndIncrement();
- if (outOfCodeBlock) {
- myJavaStructureModificationCount.getAndIncrement();
- myOutOfCodeBlockModificationCount.getAndIncrement();
- }
- fireEvent();
+ incCountersInner(outOfCodeBlock ? 7 : 1);
}
public static boolean canAffectPsi(@NotNull PsiTreeChangeEventImpl event) {
@@ -127,7 +123,7 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr
}
protected void incLanguageTrackers(@NotNull PsiTreeChangeEventImpl event) {
- if (!myEnableLanguageTracker) return;
+ if (!ourEnableLanguageTracker.asBoolean()) return;
incLanguageModificationCount(Language.ANY);
for (PsiElement o : new PsiElement[]{
event.getFile(), event.getParent(), event.getOldParent(), event.getNewParent(),
@@ -154,12 +150,17 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr
@Override
public long getModificationCount() {
- return myModificationCount.get();
+ return myModificationCount.getModificationCount();
}
@Override
public long getOutOfCodeBlockModificationCount() {
- return myOutOfCodeBlockModificationCount.get();
+ return myOutOfCodeBlockModificationTracker.getModificationCount();
+ }
+
+ @Override
+ public long getJavaStructureModificationCount() {
+ return myJavaStructureModificationTracker.getModificationCount();
}
@NotNull
@@ -168,17 +169,24 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr
return myOutOfCodeBlockModificationTracker;
}
- @Override
- public long getJavaStructureModificationCount() {
- return myJavaStructureModificationCount.get();
- }
-
@NotNull
@Override
public ModificationTracker getJavaStructureModificationTracker() {
return myJavaStructureModificationTracker;
}
+
+ @ApiStatus.Experimental
+ public boolean isEnableCodeBlockTracker() {
+ if (myTestMode) return true;
+ return ourEnableCodeBlockTracker.asBoolean();
+ }
+
+ @ApiStatus.Experimental
+ public boolean isEnableLanguageTracker() {
+ return ourEnableLanguageTracker.asBoolean();
+ }
+
@ApiStatus.Experimental
public void incLanguageModificationCount(@Nullable Language language) {
if (language == null) return;
@@ -188,14 +196,14 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr
@ApiStatus.Experimental
@NotNull
public ModificationTracker forLanguage(@NotNull Language language) {
- if (!myEnableLanguageTracker) return this;
+ if (!ourEnableLanguageTracker.asBoolean()) return this;
return myLanguageTrackers.get(language);
}
@ApiStatus.Experimental
@NotNull
public ModificationTracker forLanguages(@NotNull Condition condition) {
- if (!myEnableLanguageTracker) return this;
+ if (!ourEnableLanguageTracker.asBoolean()) return this;
return () -> {
long result = 0;
for (Language l : myLanguageTrackers.keySet()) {
@@ -205,4 +213,24 @@ public class PsiModificationTrackerImpl implements PsiModificationTracker, PsiTr
return result;
};
}
+
+ @NotNull
+ private static SimpleModificationTracker wrapped(RegistryValue value, SimpleModificationTracker fallback, boolean testMode) {
+ if (testMode) {
+ return new SimpleModificationTracker();
+ }
+ return new SimpleModificationTracker() {
+ @Override
+ public long getModificationCount() {
+ return value.asBoolean() ? super.getModificationCount() :
+ fallback.getModificationCount();
+ }
+
+ @Override
+ public void incModificationCount() {
+ if (value.asBoolean()) super.incModificationCount();
+ //else fallback.incModificationCount();
+ }
+ };
+ }
}
diff --git a/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java
index ca615bf74b62..c5c495daad3d 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/file/impl/FileManagerImpl.java
@@ -91,9 +91,7 @@ public class FileManagerImpl implements FileManager {
}
public static void clearPsiCaches(@NotNull FileViewProvider provider) {
- List psiFiles = provider instanceof AbstractFileViewProvider? ((AbstractFileViewProvider)provider).getCachedPsiFiles()
- : provider.getAllFiles();
- psiFiles.forEach(PsiFile::clearCaches);
+ ((AbstractFileViewProvider)provider).getCachedPsiFiles().forEach(PsiFile::clearCaches);
}
public void forceReload(@NotNull VirtualFile vFile) {
@@ -438,9 +436,7 @@ public class FileManagerImpl implements FileManager {
}
private void markInvalidated(@NotNull FileViewProvider viewProvider) {
- if (viewProvider instanceof AbstractFileViewProvider) {
- ((AbstractFileViewProvider)viewProvider).markInvalidated();
- }
+ ((AbstractFileViewProvider)viewProvider).markInvalidated();
VirtualFile virtualFile = viewProvider.getVirtualFile();
Document document = FileDocumentManager.getInstance().getCachedDocument(virtualFile);
if (document != null) {
@@ -453,8 +449,7 @@ public class FileManagerImpl implements FileManager {
PsiFile getCachedPsiFileInner(@NotNull VirtualFile file) {
FileViewProvider fileViewProvider = myVFileToViewProviderMap.get(file);
if (fileViewProvider == null) fileViewProvider = file.getUserData(myPsiHardRefKey);
- return fileViewProvider instanceof AbstractFileViewProvider
- ? ((AbstractFileViewProvider)fileViewProvider).getCachedPsi(fileViewProvider.getBaseLanguage()) : null;
+ return fileViewProvider != null ? ((AbstractFileViewProvider)fileViewProvider).getCachedPsi(fileViewProvider.getBaseLanguage()) : null;
}
@NotNull
@@ -462,9 +457,7 @@ public class FileManagerImpl implements FileManager {
public List getAllCachedFiles() {
List files = new ArrayList<>();
for (FileViewProvider provider : myVFileToViewProviderMap.values()) {
- if (provider instanceof AbstractFileViewProvider) {
- ContainerUtil.addIfNotNull(files, ((AbstractFileViewProvider)provider).getCachedPsi(provider.getBaseLanguage()));
- }
+ ContainerUtil.addIfNotNull(files, ((AbstractFileViewProvider)provider).getCachedPsi(provider.getBaseLanguage()));
}
return files;
}
@@ -588,11 +581,6 @@ public class FileManagerImpl implements FileManager {
return;
}
- FileViewProvider viewProvider = file.getViewProvider();
- if (viewProvider instanceof AbstractFileViewProvider) {
- ((AbstractFileViewProvider)viewProvider).onContentReload();
- } else {
- LOG.error("Invalid view provider: " + viewProvider + " of " + viewProvider.getClass());
- }
+ ((AbstractFileViewProvider)file.getViewProvider()).onContentReload();
}
}
diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java
index d8e3cda6163b..cdb0f5218fcf 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java
@@ -545,9 +545,7 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
myOriginalFile = originalFile.getOriginalFile();
FileViewProvider original = myOriginalFile.getViewProvider();
- if (myViewProvider instanceof AbstractFileViewProvider && original instanceof AbstractFileViewProvider) {
- ((AbstractFileViewProvider)original).registerAsCopy((AbstractFileViewProvider)myViewProvider);
- }
+ ((AbstractFileViewProvider)original).registerAsCopy((AbstractFileViewProvider)myViewProvider);
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/execution/console/IdeConsoleRootType.java b/platform/lang-impl/src/com/intellij/execution/console/IdeConsoleRootType.java
index 64fb30582fe4..4f494be7f13b 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/IdeConsoleRootType.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/IdeConsoleRootType.java
@@ -16,6 +16,7 @@
package com.intellij.execution.console;
import com.intellij.icons.AllIcons;
+import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
@@ -36,7 +37,7 @@ import javax.swing.*;
*/
public class IdeConsoleRootType extends ConsoleRootType {
IdeConsoleRootType() {
- super("ide", "IDE Scripting");
+ super("ide", ApplicationNamesInfo.getInstance().getProductName() + " Consoles");
}
@NotNull
diff --git a/platform/lang-impl/src/com/intellij/internal/psiView/stubtree/StubViewerPsiBasedTree.java b/platform/lang-impl/src/com/intellij/internal/psiView/stubtree/StubViewerPsiBasedTree.java
index a2ebac4e0066..a8ec4122a8e4 100644
--- a/platform/lang-impl/src/com/intellij/internal/psiView/stubtree/StubViewerPsiBasedTree.java
+++ b/platform/lang-impl/src/com/intellij/internal/psiView/stubtree/StubViewerPsiBasedTree.java
@@ -18,6 +18,7 @@ package com.intellij.internal.psiView.stubtree;
import com.intellij.ide.util.treeView.TreeVisitor;
import com.intellij.internal.psiView.ViewerPsiBasedTree;
import com.intellij.lang.ASTNode;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
@@ -25,6 +26,7 @@ import com.intellij.openapi.util.Ref;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
+import com.intellij.psi.StubBuilder;
import com.intellij.psi.impl.source.PsiFileImpl;
import com.intellij.psi.impl.source.PsiFileWithStubSupport;
import com.intellij.psi.stubs.*;
@@ -53,11 +55,12 @@ import java.util.Iterator;
import java.util.Map;
import java.util.Set;
-import static com.intellij.internal.psiView.PsiViewerDialog.LOG;
import static com.intellij.internal.psiView.PsiViewerDialog.initTree;
public class StubViewerPsiBasedTree implements ViewerPsiBasedTree {
+ public static final Logger LOG = Logger.getInstance("#com.intellij.internal.psiView.PsiViewerDialog");
+
private static final Key