KT-1175 Mark unused literals
This commit is contained in:
@@ -82,7 +82,7 @@ public class JetControlFlowProcessor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitWhenConditionExpression(JetWhenConditionWithExpression condition) {
|
||||
public void visitWhenConditionWithExpression(JetWhenConditionWithExpression condition) {
|
||||
JetExpressionPattern pattern = condition.getPattern();
|
||||
if (pattern != null) {
|
||||
pattern.accept(patternVisitor);
|
||||
|
||||
@@ -641,6 +641,39 @@ public class JetFlowInformationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// "Unused literals" in block
|
||||
|
||||
public void markUnusedLiteralsInBlock(@NotNull JetElement subroutine) {
|
||||
Pseudocode pseudocode = pseudocodeMap.get(subroutine);
|
||||
assert pseudocode != null;
|
||||
JetControlFlowGraphTraverser<Void> traverser = JetControlFlowGraphTraverser.create(pseudocode, true, true);
|
||||
traverser.traverseAndAnalyzeInstructionGraph(new JetControlFlowGraphTraverser.InstructionDataAnalyzeStrategy<Void>() {
|
||||
@Override
|
||||
public void execute(@NotNull Instruction instruction, @Nullable Void enterData, @Nullable Void exitData) {
|
||||
if (!(instruction instanceof ReadValueInstruction)) return;
|
||||
JetElement element = ((ReadValueInstruction) instruction).getElement();
|
||||
if (!(element instanceof JetFunctionLiteralExpression
|
||||
|| element instanceof JetConstantExpression
|
||||
|| element instanceof JetStringTemplateExpression
|
||||
|| element instanceof JetSimpleNameExpression)) {
|
||||
return;
|
||||
}
|
||||
PsiElement parent = element.getParent();
|
||||
if (parent instanceof JetBlockExpression) {
|
||||
if (!JetPsiUtil.isImplicitlyUsed(element)) {
|
||||
if (element instanceof JetFunctionLiteralExpression) {
|
||||
trace.report(Errors.UNUSED_FUNCTION_LITERAL.on((JetFunctionLiteralExpression) element));
|
||||
}
|
||||
else {
|
||||
trace.report(Errors.UNUSED_EXPRESSION.on(element));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Util methods 7
|
||||
|
||||
|
||||
@@ -167,6 +167,8 @@ public interface Errors {
|
||||
return argument.getText();
|
||||
}
|
||||
};
|
||||
SimpleDiagnosticFactory UNUSED_EXPRESSION = SimpleDiagnosticFactory.create(WARNING, "The expression is unused");
|
||||
SimplePsiElementOnlyDiagnosticFactory<JetFunctionLiteralExpression> UNUSED_FUNCTION_LITERAL = SimplePsiElementOnlyDiagnosticFactory.create(WARNING, "The function literal is unused. If you mean block, you can use 'run { ... }'");
|
||||
|
||||
PsiElementOnlyDiagnosticFactory1<JetExpression, DeclarationDescriptor> VAL_REASSIGNMENT = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Val can not be reassigned", NAME);
|
||||
PsiElementOnlyDiagnosticFactory1<JetExpression, DeclarationDescriptor> INITIALIZATION_BEFORE_DECLARATION = PsiElementOnlyDiagnosticFactory1.create(ERROR, "Variable cannot be initialized before declaration", NAME);
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -85,11 +87,12 @@ public class JetPsiUtil {
|
||||
|
||||
if (quoted.startsWith("`") && quoted.endsWith("`") && quoted.length() >= 2) {
|
||||
return quoted.substring(1, quoted.length() - 1);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return quoted;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
public static String unquoteIdentifierOrFieldReference(@NotNull String quoted) {
|
||||
if (quoted.indexOf('`') < 0) {
|
||||
@@ -98,7 +101,8 @@ public class JetPsiUtil {
|
||||
|
||||
if (quoted.startsWith("$")) {
|
||||
return "$" + unquoteIdentifier(quoted.substring(1));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return unquoteIdentifier(quoted);
|
||||
}
|
||||
}
|
||||
@@ -167,4 +171,51 @@ public class JetPsiUtil {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static <T extends PsiElement> T getDirectParentOfTypeForBlock(@NotNull JetBlockExpression block, @NotNull Class<T> aClass) {
|
||||
T parent = PsiTreeUtil.getParentOfType(block, aClass);
|
||||
if (parent instanceof JetIfExpression) {
|
||||
JetIfExpression ifExpression = (JetIfExpression) parent;
|
||||
if (ifExpression.getElse() == block || ifExpression.getThen() == block) {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
if (parent instanceof JetWhenExpression) {
|
||||
JetWhenExpression whenExpression = (JetWhenExpression) parent;
|
||||
for (JetWhenEntry whenEntry : whenExpression.getEntries()) {
|
||||
if (whenEntry.getExpression() == block) {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (parent instanceof JetFunctionLiteral) {
|
||||
JetFunctionLiteral functionLiteral = (JetFunctionLiteral) parent;
|
||||
if (functionLiteral.getBodyExpression() == block) {
|
||||
return parent;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean isImplicitlyUsed(@NotNull JetElement element) {
|
||||
PsiElement parent = element.getParent();
|
||||
if (!(parent instanceof JetBlockExpression)) return true;
|
||||
JetBlockExpression block = (JetBlockExpression) parent;
|
||||
List<JetElement> statements = block.getStatements();
|
||||
if (statements.get(statements.size() - 1) == element) {
|
||||
JetExpression expression = getDirectParentOfTypeForBlock(block, JetIfExpression.class);
|
||||
if (expression == null) {
|
||||
expression = getDirectParentOfTypeForBlock(block, JetWhenExpression.class);
|
||||
}
|
||||
if (expression == null) {
|
||||
expression = getDirectParentOfTypeForBlock(block, JetFunctionLiteral.class);
|
||||
}
|
||||
if (expression != null) {
|
||||
return isImplicitlyUsed(expression);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -358,7 +358,7 @@ public class JetVisitorVoid extends PsiElementVisitor {
|
||||
visitJetElement(condition);
|
||||
}
|
||||
|
||||
public void visitWhenConditionExpression(JetWhenConditionWithExpression condition) {
|
||||
public void visitWhenConditionWithExpression(JetWhenConditionWithExpression condition) {
|
||||
visitJetElement(condition);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ public class JetWhenConditionWithExpression extends JetWhenCondition {
|
||||
|
||||
@Override
|
||||
public void accept(@NotNull JetVisitorVoid visitor) {
|
||||
visitor.visitWhenConditionExpression(this);
|
||||
visitor.visitWhenConditionWithExpression(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -81,5 +81,7 @@ public class ControlFlowAnalyzer {
|
||||
flowInformationProvider.markUninitializedVariables(function.asElement(), context.isDeclaredLocally());
|
||||
|
||||
flowInformationProvider.markUnusedVariables(function.asElement());
|
||||
|
||||
flowInformationProvider.markUnusedLiteralsInBlock(function.asElement());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -143,7 +143,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitWhenConditionExpression(JetWhenConditionWithExpression condition) {
|
||||
public void visitWhenConditionWithExpression(JetWhenConditionWithExpression condition) {
|
||||
JetPattern pattern = condition.getPattern();
|
||||
if (pattern != null) {
|
||||
newDataFlowInfo[0] = checkPatternType(pattern, subjectType, subjectExpression == null, scopeToExtend, context, subjectVariables);
|
||||
|
||||
Reference in New Issue
Block a user