diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java index 9eda16b291a..2689170ed80 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetControlFlowGraphTraverser.java @@ -1,5 +1,6 @@ package org.jetbrains.jet.lang.cfg; +import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; @@ -19,31 +20,36 @@ import java.util.Map; public class JetControlFlowGraphTraverser { private final Pseudocode pseudocode; private final boolean lookInside; + private final boolean straightDirection; private final Map> dataMap = Maps.newLinkedHashMap(); - public static JetControlFlowGraphTraverser create(Pseudocode pseudocode, boolean lookInside) { - return new JetControlFlowGraphTraverser(pseudocode, lookInside); + public static JetControlFlowGraphTraverser create(Pseudocode pseudocode, boolean lookInside, boolean straightDirection) { + return new JetControlFlowGraphTraverser(pseudocode, lookInside, straightDirection); } - private JetControlFlowGraphTraverser(Pseudocode pseudocode, boolean lookInside) { + private JetControlFlowGraphTraverser(Pseudocode pseudocode, boolean lookInside, boolean straightDirection) { this.pseudocode = pseudocode; this.lookInside = lookInside; + this.straightDirection = straightDirection; + } + + private Instruction getStartInstruction(Pseudocode pseudocode) { + return straightDirection ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction(); } public void collectInformationFromInstructionGraph( InstructionDataMergeStrategy instructionDataMergeStrategy, D initialDataValue, - D initialDataValueForEnterInstruction, - boolean straightDirection) { + D initialDataValueForEnterInstruction) { initializeDataMap(pseudocode, initialDataValue); - dataMap.put(straightDirection ? pseudocode.getEnterInstruction() : pseudocode.getSinkInstruction(), + dataMap.put(getStartInstruction(pseudocode), Pair.create(initialDataValueForEnterInstruction, initialDataValueForEnterInstruction)); boolean[] changed = new boolean[1]; changed[0] = true; while (changed[0]) { changed[0] = false; - traverseSubGraph(pseudocode, instructionDataMergeStrategy, Collections.emptyList(), straightDirection, changed, false); + traverseSubGraph(pseudocode, instructionDataMergeStrategy, Collections.emptyList(), changed, false); } } @@ -64,20 +70,25 @@ public class JetControlFlowGraphTraverser { Pseudocode pseudocode, InstructionDataMergeStrategy instructionDataMergeStrategy, Collection previousSubGraphInstructions, - boolean straightDirection, boolean[] changed, boolean isLocal) { List instructions = pseudocode.getInstructions(); - SubroutineEnterInstruction enterInstruction = pseudocode.getEnterInstruction(); + Instruction startInstruction = getStartInstruction(pseudocode); + + if (!straightDirection) { + instructions = Lists.newArrayList(instructions); + Collections.reverse(instructions); + } for (Instruction instruction : instructions) { - if (!isLocal && instruction instanceof SubroutineEnterInstruction) continue; + boolean isStart = straightDirection ? instruction instanceof SubroutineEnterInstruction : instruction instanceof SubroutineSinkInstruction; + if (!isLocal && isStart) continue; Collection allPreviousInstructions; Collection previousInstructions = straightDirection ? instruction.getPreviousInstructions() : instruction.getNextInstructions(); - if (instruction == enterInstruction && !previousSubGraphInstructions.isEmpty()) { + if (instruction == startInstruction && !previousSubGraphInstructions.isEmpty()) { allPreviousInstructions = Lists.newArrayList(previousInstructions); allPreviousInstructions.addAll(previousSubGraphInstructions); } @@ -87,7 +98,15 @@ public class JetControlFlowGraphTraverser { if (lookInside && instruction instanceof LocalDeclarationInstruction) { Pseudocode subroutinePseudocode = ((LocalDeclarationInstruction) instruction).getBody(); - traverseSubGraph(subroutinePseudocode, instructionDataMergeStrategy, previousInstructions, straightDirection, changed, true); + traverseSubGraph(subroutinePseudocode, instructionDataMergeStrategy, previousInstructions, changed, true); + Instruction lastInstruction = straightDirection ? subroutinePseudocode.getSinkInstruction() : subroutinePseudocode.getEnterInstruction(); + Pair previousValue = dataMap.get(instruction); + Pair newValue = dataMap.get(lastInstruction); + if (!previousValue.equals(newValue)) { + changed[0] = true; + dataMap.put(instruction, newValue); + } + continue; } Pair previousDataValue = dataMap.get(instruction); @@ -116,12 +135,16 @@ public class JetControlFlowGraphTraverser { Pseudocode pseudocode, InstructionDataAnalyzeStrategy instructionDataAnalyzeStrategy) { List instructions = pseudocode.getInstructions(); + if (!straightDirection) { + instructions = Lists.newArrayList(instructions); + Collections.reverse(instructions); + } for (Instruction instruction : instructions) { if (instruction.isDead()) continue; - Pair pair = dataMap.get(instruction); if (lookInside && instruction instanceof LocalDeclarationInstruction) { traverseAndAnalyzeInstructionGraph(((LocalDeclarationInstruction) instruction).getBody(), instructionDataAnalyzeStrategy); } + Pair pair = dataMap.get(instruction); instructionDataAnalyzeStrategy.execute(instruction, pair != null ? pair.getFirst() : null, pair != null ? pair.getSecond() : null); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index c88b2264c5d..7b8f6fc2b0b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -194,7 +194,7 @@ public class JetFlowInformationProvider { final Pseudocode pseudocode = pseudocodeMap.get(subroutine); assert pseudocode != null; - JetControlFlowGraphTraverser> traverser = JetControlFlowGraphTraverser.create(pseudocode, false); + JetControlFlowGraphTraverser> traverser = JetControlFlowGraphTraverser.create(pseudocode, false, true); Collection usedVariables = collectUsedVariables(pseudocode); final Collection declaredVariables = collectDeclaredVariables(subroutine); @@ -213,7 +213,7 @@ public class JetFlowInformationProvider { } }; - traverser.collectInformationFromInstructionGraph(variableInitializersMergeStrategy, Collections.emptyMap(), initialMapForStartInstruction, true); + traverser.collectInformationFromInstructionGraph(variableInitializersMergeStrategy, Collections.emptyMap(), initialMapForStartInstruction); final Collection varWithUninitializedErrorGenerated = Sets.newHashSet(); final Collection varWithValReassignErrorGenerated = Sets.newHashSet(); @@ -396,7 +396,7 @@ public class JetFlowInformationProvider { Pseudocode pseudocode = pseudocodeMap.get(subroutine); assert pseudocode != null; - JetControlFlowGraphTraverser.create(pseudocode, true).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() { + JetControlFlowGraphTraverser.create(pseudocode, true, true).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() { @Override public void execute(Instruction instruction, Void enterData, Void exitData) { if (instruction instanceof ReadValueInstruction) { @@ -419,73 +419,50 @@ public class JetFlowInformationProvider { public void markUnusedVariables(@NotNull JetElement subroutine) { Pseudocode pseudocode = pseudocodeMap.get(subroutine); assert pseudocode != null; - - final Set usedVariables = Sets.newHashSet(); - JetControlFlowGraphTraverser.create(pseudocode, true).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() { - @Override - public void execute(Instruction instruction, @Nullable Void enterData, @Nullable Void exitData) { - if (instruction instanceof ReadValueInstruction) { - VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, false); - usedVariables.add(variableDescriptor); - } - } - }); - Collection declaredVariables = collectDeclaredVariables(subroutine); - for (VariableDescriptor declaredVariable : declaredVariables) { - if (!usedVariables.contains(declaredVariable)) { - PsiElement element = trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, declaredVariable); - //todo - if (element instanceof JetProperty && JetPsiUtil.isLocal((JetNamedDeclaration) element)) { - PsiElement nameIdentifier = ((JetNamedDeclaration) element).getNameIdentifier(); - PsiElement elementToMark = nameIdentifier != null ? nameIdentifier : element; - trace.report(Errors.UNUSED_VARIABLE.on((JetNamedDeclaration)element, elementToMark, declaredVariable)); - } - } + JetControlFlowGraphTraverser> traverser = JetControlFlowGraphTraverser.create(pseudocode, true, false); + final Collection declaredVariables = collectDeclaredVariables(subroutine); + Collection usedVariables = collectUsedVariables(pseudocode); + Map sinkInstructionData = Maps.newHashMap(); + for (VariableDescriptor usedVariable : usedVariables) { + sinkInstructionData.put(usedVariable, VariableStatus.UNUSED); } - - markUnusedValues(subroutine, pseudocode, declaredVariables); - } - - private void markUnusedValues(@NotNull JetElement subroutine, Pseudocode pseudocode, final Collection declaredVariables) { - JetControlFlowGraphTraverser> traverser = JetControlFlowGraphTraverser.create(pseudocode, true); - traverser.collectInformationFromInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataMergeStrategy>() { + traverser.collectInformationFromInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataMergeStrategy>() { @Override - public Pair, Set> execute(Instruction instruction, @NotNull Collection> incomingEdgesData) { - Set enterResult = Sets.newHashSet(); - for (Set edgeData : incomingEdgesData) { - enterResult.addAll(edgeData); - } - Set exitResult = Sets.newHashSet(enterResult); - if (instruction instanceof ReadValueInstruction) { - VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, true); - if (variableDescriptor != null) { - exitResult.add(variableDescriptor); + public Pair, Map> execute(Instruction instruction, @NotNull Collection> incomingEdgesData) { + Map enterResult = Maps.newHashMap(); + for (Map edgeData : incomingEdgesData) { + for (Map.Entry entry : edgeData.entrySet()) { + VariableDescriptor variableDescriptor = entry.getKey(); + VariableStatus variableStatus = entry.getValue(); + enterResult.put(variableDescriptor, variableStatus.merge(enterResult.get(variableDescriptor))); } } - else if (instruction instanceof WriteValueInstruction) { - VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, true); - if (variableDescriptor != null) { - exitResult.remove(variableDescriptor); + Map exitResult = Maps.newHashMap(enterResult); + VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, true); + if (variableDescriptor != null) { + if (instruction instanceof ReadValueInstruction) { + exitResult.put(variableDescriptor, VariableStatus.READ); + } + else if (instruction instanceof WriteValueInstruction) { + exitResult.put(variableDescriptor, VariableStatus.WRITTEN); } } - return new Pair, Set>(enterResult, exitResult); + return new Pair, Map>(enterResult, exitResult); } - }, Collections.emptySet(), Collections.emptySet(), false); - traverser.traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy>() { + }, Collections.emptyMap(), sinkInstructionData); + traverser.traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy>() { @Override - public void execute(Instruction instruction, @Nullable Set enterData, @Nullable Set exitData) { + public void execute(Instruction instruction, @Nullable Map enterData, @Nullable Map exitData) { assert enterData != null && exitData != null; - if (instruction instanceof WriteValueInstruction) { - VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, false); - if (variableDescriptor != null && declaredVariables.contains(variableDescriptor)) { - if (!enterData.contains(variableDescriptor)) { - PsiElement variableDeclarationElement = trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, variableDescriptor); -// assert variableDeclarationElement instanceof JetProperty || variableDeclarationElement instanceof JetParameter; -// boolean isLocal = !(variableDeclarationElement instanceof JetProperty) || JetPsiUtil.isLocal((JetProperty) variableDeclarationElement); - assert variableDeclarationElement instanceof JetDeclaration; - boolean isLocal = JetPsiUtil.isLocal((JetDeclaration) variableDeclarationElement); - if (isLocal) { - JetElement element = ((WriteValueInstruction) instruction).getElement(); + VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, false); + if (variableDescriptor != null && declaredVariables.contains(variableDescriptor)) { + PsiElement variableDeclarationElement = trace.get(BindingContext.DESCRIPTOR_TO_DECLARATION, variableDescriptor); + assert variableDeclarationElement instanceof JetDeclaration; + boolean isLocal = JetPsiUtil.isLocal((JetDeclaration) variableDeclarationElement); + if (isLocal) { + if (instruction instanceof WriteValueInstruction) { + JetElement element = ((WriteValueInstruction) instruction).getElement(); + if (enterData.get(variableDescriptor) == VariableStatus.WRITTEN || enterData.get(variableDescriptor) == VariableStatus.UNUSED) { if (element instanceof JetBinaryExpression && ((JetBinaryExpression) element).getOperationToken() == JetTokens.EQ) { JetExpression right = ((JetBinaryExpression) element).getRight(); if (right != null) { @@ -499,6 +476,20 @@ public class JetFlowInformationProvider { } } } + } + else if (instruction instanceof VariableDeclarationInstruction) { + JetDeclaration element = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement(); + if (element instanceof JetProperty) { + PsiElement nameIdentifier = ((JetNamedDeclaration) element).getNameIdentifier(); + PsiElement elementToMark = nameIdentifier != null ? nameIdentifier : element; + if (enterData.get(variableDescriptor) == VariableStatus.UNUSED) { + trace.report(Errors.UNUSED_VARIABLE.on((JetNamedDeclaration) element, elementToMark, variableDescriptor)); + } + else if (enterData.get(variableDescriptor) == VariableStatus.WRITTEN) { + trace.report(Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE.on((JetNamedDeclaration) element, elementToMark, variableDescriptor)); + } + } + } } } @@ -506,26 +497,44 @@ public class JetFlowInformationProvider { }); } + private static enum VariableStatus { + READ(2), + WRITTEN(1), + UNUSED(0); + + private int importance; + + private VariableStatus(int importance) { + this.importance = importance; + } + + public VariableStatus merge(@Nullable VariableStatus variableStatus) { + if (variableStatus == null || importance > variableStatus.importance) return this; + return variableStatus; + } + } + //////////////////////////////////////////////////////////////////////////////// // Util methods @Nullable private VariableDescriptor extractVariableDescriptorIfAny(Instruction instruction, boolean onlyReference) { - VariableDescriptor variableDescriptor = null; + JetElement element = null; if (instruction instanceof ReadValueInstruction) { - JetElement element = ((ReadValueInstruction) instruction).getElement(); - variableDescriptor = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), element, onlyReference); + element = ((ReadValueInstruction) instruction).getElement(); } else if (instruction instanceof WriteValueInstruction) { - JetElement lValue = ((WriteValueInstruction) instruction).getlValue(); - variableDescriptor = BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), lValue, onlyReference); + element = ((WriteValueInstruction) instruction).getlValue(); } - return variableDescriptor; + else if (instruction instanceof VariableDeclarationInstruction) { + element = ((VariableDeclarationInstruction) instruction).getVariableDeclarationElement(); + } + return BindingContextUtils.extractVariableDescriptorIfAny(trace.getBindingContext(), element, onlyReference); } private Collection collectUsedVariables(Pseudocode pseudocode) { final Set usedVariables = Sets.newHashSet(); - JetControlFlowGraphTraverser.create(pseudocode, true).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() { + JetControlFlowGraphTraverser.create(pseudocode, true, true).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() { @Override public void execute(Instruction instruction, Void enterData, Void exitData) { VariableDescriptor variableDescriptor = extractVariableDescriptorIfAny(instruction, false); @@ -542,7 +551,7 @@ public class JetFlowInformationProvider { assert pseudocode != null; final Set declaredVariables = Sets.newHashSet(); - JetControlFlowGraphTraverser.create(pseudocode, false).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() { + JetControlFlowGraphTraverser.create(pseudocode, false, true).traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy() { @Override public void execute(Instruction instruction, @Nullable Void enterData, @Nullable Void exitData) { if (instruction instanceof VariableDeclarationInstruction) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index 742245b2263..eecdfed9d7d 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -145,6 +145,7 @@ public interface Errors { PsiElementOnlyDiagnosticFactory1 UNINITIALIZED_VARIABLE = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Variable ''{0}'' must be initialized", NAME); PsiElementOnlyDiagnosticFactory1 UNUSED_VARIABLE = PsiElementOnlyDiagnosticFactory1.create(WARNING, "Variable ''{0}'' is never used", NAME); + PsiElementOnlyDiagnosticFactory1 ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE = PsiElementOnlyDiagnosticFactory1.create(WARNING, "Variable ''{0}'' is assigned but never accessed", NAME); PsiElementOnlyDiagnosticFactory2 UNUSED_VALUE = new PsiElementOnlyDiagnosticFactory2(WARNING, "The value ''{0}'' assigned to ''{1}'' is never used", NAME) { @Override protected String makeMessageForA(@NotNull JetElement element) { diff --git a/compiler/testData/checkerWithErrorTypes/full/BinaryCallsOnNullableValues.jet b/compiler/testData/checkerWithErrorTypes/full/BinaryCallsOnNullableValues.jet index 86d34c881be..5394c137aae 100644 --- a/compiler/testData/checkerWithErrorTypes/full/BinaryCallsOnNullableValues.jet +++ b/compiler/testData/checkerWithErrorTypes/full/BinaryCallsOnNullableValues.jet @@ -11,7 +11,7 @@ class C() { } fun f(): Unit { - var x: Int? = 1 + var x: Int? = 1 x = 1 x + 1 x plus 1 diff --git a/compiler/testData/checkerWithErrorTypes/full/infos/Autocasts.jet b/compiler/testData/checkerWithErrorTypes/full/infos/Autocasts.jet index de468b149b4..38a9005de0b 100644 --- a/compiler/testData/checkerWithErrorTypes/full/infos/Autocasts.jet +++ b/compiler/testData/checkerWithErrorTypes/full/infos/Autocasts.jet @@ -179,7 +179,7 @@ fun declarations(a: Any?) { } } fun vars(a: Any?) { - var b: Int = 0 + var b: Int = 0 if (a is Int) { b = a } diff --git a/compiler/testData/checkerWithErrorTypes/quick/AutocastsForStableIdentifiers.jet b/compiler/testData/checkerWithErrorTypes/quick/AutocastsForStableIdentifiers.jet index 37ff349686f..25c73139ff1 100644 --- a/compiler/testData/checkerWithErrorTypes/quick/AutocastsForStableIdentifiers.jet +++ b/compiler/testData/checkerWithErrorTypes/quick/AutocastsForStableIdentifiers.jet @@ -17,7 +17,7 @@ class AClass() { val x : Any? = 1 fun Any?.vars(a: Any?) : Int { - var b: Int = 0 + var b: Int = 0 if (ns.y is Int) { b = ns.y } @@ -74,7 +74,7 @@ trait T {} open class C { fun foo() { - var t : T? = null + var t : T? = null if (this is T) { t = this } diff --git a/compiler/testData/checkerWithErrorTypes/quick/UninitializedOrReassignedVariables.jet b/compiler/testData/checkerWithErrorTypes/quick/UninitializedOrReassignedVariables.jet index eb7807c0797..f1bbe6de43b 100644 --- a/compiler/testData/checkerWithErrorTypes/quick/UninitializedOrReassignedVariables.jet +++ b/compiler/testData/checkerWithErrorTypes/quick/UninitializedOrReassignedVariables.jet @@ -16,7 +16,7 @@ fun t1(b : Boolean) { } doSmth(u) - var r: String + var r: String if (b) { r = "s" } @@ -63,10 +63,10 @@ fun t4(a: A, val b: A, var c: A) { // reassigned vals fun t1() { - val a : Int = 1 + val a : Int = 1 a = 2 - var b : Int = 1 + var b : Int = 1 b = 3 } diff --git a/compiler/testData/checkerWithErrorTypes/quick/UnusedVariables.jet b/compiler/testData/checkerWithErrorTypes/quick/UnusedVariables.jet index c52c8e8e61d..dab85168b91 100644 --- a/compiler/testData/checkerWithErrorTypes/quick/UnusedVariables.jet +++ b/compiler/testData/checkerWithErrorTypes/quick/UnusedVariables.jet @@ -1,7 +1,7 @@ namespace unused_variables fun testSimpleCases() { - var i = 2 + var i = 2 i = 34 i = 34 doSmth(i) @@ -9,7 +9,7 @@ fun testSimpleCases() { var j = 2 j = j++ - j = j-- + j = j-- } class IncDec() { @@ -45,7 +45,7 @@ class MyTest() { fun testSimple() { a = "rro" - var i = 1; + var i = 1; i = 34; i = 456; } @@ -62,7 +62,7 @@ class MyTest() { } fun testIf() { - var a : Any + var a : Any if (1 < 2) { a = 23 } @@ -91,7 +91,7 @@ class MyTest() { } fun testInnerFunctions() { - var y = 1 + var y = 1 fun foo() { y = 1 } diff --git a/compiler/testData/checkerWithErrorTypes/quick/regressions/kt610.jet b/compiler/testData/checkerWithErrorTypes/quick/regressions/kt610.jet new file mode 100644 index 00000000000..916704e6c03 --- /dev/null +++ b/compiler/testData/checkerWithErrorTypes/quick/regressions/kt610.jet @@ -0,0 +1,10 @@ +//KT-610 Distinguish errors 'unused variable' and 'variable is assigned but never accessed' + +namespace kt610 + +fun foo() { + var j = 9 //'unused variable' error + + var i = 1 //should be an error 'variable i is assigned but never accessed' + i = 2 +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java b/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java index 09f872108fc..5dfb0bd94e4 100644 --- a/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java +++ b/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java @@ -88,7 +88,7 @@ public class JetPsiChecker implements Annotator { } else if (diagnostic.getSeverity() == Severity.WARNING) { annotation = holder.createWarningAnnotation(diagnostic.getFactory().getTextRange(diagnostic), getMessage(diagnostic)); - if (diagnostic.getFactory() == Errors.UNUSED_VARIABLE) { + if (diagnostic.getFactory() == Errors.UNUSED_VARIABLE || diagnostic.getFactory() == Errors.ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE) { annotation.setHighlightType(ProblemHighlightType.LIKE_UNUSED_SYMBOL); } } diff --git a/idea/testData/checker/BinaryCallsOnNullableValues.jet b/idea/testData/checker/BinaryCallsOnNullableValues.jet index 285605c2a42..a66c709b010 100644 --- a/idea/testData/checker/BinaryCallsOnNullableValues.jet +++ b/idea/testData/checker/BinaryCallsOnNullableValues.jet @@ -11,7 +11,7 @@ class C() { } fun f(): Unit { - var x: Int? = 1 + var x: Int? = 1 x = 1 x + 1 x plus 1