assert that rangeInElement is inside the descriptor range to avoid surprising "index out of range" exceptions

This commit is contained in:
Alexey Kudravtsev
2017-12-18 14:52:34 +03:00
parent c0c279d60a
commit b2a8cb5f48
6 changed files with 40 additions and 35 deletions
@@ -94,13 +94,16 @@ public class Java8MapForEachInspection extends AbstractBaseJavaLocalInspectionTo
TextRange range;
PsiJavaToken rParenth = loop.getRParenth();
PsiElement firstChild = loop.getFirstChild();
PsiElement toHighlight;
if (wholeStatement && rParenth != null) {
range = new TextRange(0, rParenth.getStartOffsetInParent() + 1);
toHighlight = loop;
range = new TextRange(firstChild.getStartOffsetInParent(), rParenth.getStartOffsetInParent() + 1);
}
else {
toHighlight = firstChild;
range = new TextRange(0, firstChild.getTextLength());
}
holder.registerProblem(loop.getFirstChild(), InspectionsBundle.message("inspection.map.foreach.message"),
holder.registerProblem(toHighlight, InspectionsBundle.message("inspection.map.foreach.message"),
type, range, new ReplaceWithMapForEachFix());
}
}
@@ -118,8 +121,9 @@ public class Java8MapForEachInspection extends AbstractBaseJavaLocalInspectionTo
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PsiElement element = descriptor.getStartElement();
if (element.getParent() instanceof PsiForeachStatement) {
fixInForeach((PsiForeachStatement)element.getParent());
PsiElement foreach = element instanceof PsiForeachStatement ? element : element.getParent();
if (foreach instanceof PsiForeachStatement) {
fixInForeach((PsiForeachStatement)foreach);
return;
}
PsiMethodCallExpression call = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class);
@@ -198,7 +202,7 @@ public class Java8MapForEachInspection extends AbstractBaseJavaLocalInspectionTo
final PsiType myType;
String myName;
public ParameterCandidate(PsiType entryType, boolean isKey) {
ParameterCandidate(PsiType entryType, boolean isKey) {
myName = isKey ? "key" : "value";
myType = GenericsUtil
.getVariableTypeByExpressionType(PsiUtil.substituteTypeParameter(entryType, JAVA_UTIL_MAP_ENTRY, isKey ? 0 : 1, true));
@@ -335,7 +335,7 @@ public class UpdateHighlightersUtil {
info.setGroup(group);
int layer = getLayer(info, severityRegistrar);
RangeHighlighterEx highlighter = infosToRemove == null ? null : (RangeHighlighterEx)infosToRemove.pickupHighlighterFromGarbageBin(info.startOffset, info.endOffset, layer);
RangeHighlighterEx highlighter = infosToRemove == null ? null : (RangeHighlighterEx)infosToRemove.pickupHighlighterFromGarbageBin(infoStartOffset, infoEndOffset, layer);
final TextRange finalInfoRange = new TextRange(infoStartOffset, infoEndOffset);
final TextAttributes infoAttributes = info.getTextAttributes(psiFile, colorsScheme);
@@ -69,7 +69,17 @@ public class ProblemDescriptorBase extends CommonProblemDescriptorImpl implement
&& endElementRange != null
&& startElementRange.getStartOffset() >= endElementRange.getEndOffset()) {
if (!(startElement instanceof PsiFile && endElement instanceof PsiFile)) {
LOG.error("Empty PSI elements should not be passed to createDescriptor. Start: " + startElement + ", end: " + endElement + ", startContainingFile: " + startContainingFile);
LOG.error("Empty PSI elements must not be passed to createDescriptor. Start: " + startElement + ", end: " + endElement + ", startContainingFile: " + startContainingFile);
}
}
if (rangeInElement != null && startElementRange != null && endElementRange != null) {
TextRange.assertProperRange(rangeInElement);
if (rangeInElement.getEndOffset() > endElementRange.getEndOffset() - startElementRange.getStartOffset()) {
LOG.error("Argument rangeInElement " + rangeInElement + " endOffset"+
" must not exceed descriptor text range " +
"(" + startElementRange.getStartOffset() +
", " + endElementRange.getEndOffset() + ")" +
" length ("+(endElementRange.getEndOffset()-startElementRange.getStartOffset())+").");
}
}
@@ -189,23 +199,20 @@ public class ProblemDescriptorBase extends CommonProblemDescriptorImpl implement
if (startRange == null) {
return null;
}
if (startElement == endElement) {
if (isAfterEndOfLine()) {
int endOffset = myTextRangeInElement != null ? startRange.getStartOffset() + myTextRangeInElement.getEndOffset()
: startRange.getEndOffset();
return new TextRange(endOffset, endOffset);
}
if (myTextRangeInElement != null) {
return new TextRange(startRange.getStartOffset() + myTextRangeInElement.getStartOffset(),
startRange.getStartOffset() + myTextRangeInElement.getEndOffset());
}
return startRange;
if (startElement != endElement) {
TextRange endRange = getAnnotationRange(endElement);
if (endRange == null) return null;
startRange = startRange.union(endRange);
}
TextRange endRange = getAnnotationRange(endElement);
if (endRange == null) {
return null;
else if (myTextRangeInElement != null) {
startRange = startRange.cutOut(myTextRangeInElement);
}
return new TextRange(startRange.getStartOffset(), endRange.getEndOffset());
if (isAfterEndOfLine()) {
int endOffset = startRange.getEndOffset();
return new TextRange(endOffset, endOffset);
}
return startRange;
}
public Navigatable getNavigatable() {
@@ -120,8 +120,8 @@ public class TextRange implements Segment, Serializable {
@NotNull
public TextRange cutOut(@NotNull TextRange subRange) {
assert subRange.getStartOffset() <= getLength() : subRange + "; this="+this;
assert subRange.getEndOffset() <= getLength() : subRange + "; this="+this;
assert subRange.getStartOffset() <= getLength() : "SubRange: " + subRange + "; this=" + this;
assert subRange.getEndOffset() <= getLength() : "SubRange: " + subRange + "; this=" + this;
assertProperRange(subRange);
return new TextRange(myStartOffset + subRange.getStartOffset(),
Math.min(myEndOffset, myStartOffset + subRange.getEndOffset()));
@@ -77,7 +77,7 @@ public class UnsupportedFeatures extends CompatibilityVisitor {
@NotNull
private static IntentionAction createIntention(@NotNull PsiElement node, @NotNull String message, @NotNull LocalQuickFix localQuickFix) {
return createIntention(node, node.getTextRange(), message, localQuickFix);
return createIntention(node, null, message, localQuickFix);
}
@NotNull
@@ -21,7 +21,6 @@ import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.UnfairTextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference;
@@ -35,7 +34,9 @@ import org.jetbrains.annotations.NotNull;
class DomElementResolveProblemDescriptorImpl extends DomElementProblemDescriptorImpl implements DomElementResolveProblemDescriptor {
@NotNull private final PsiReference myReference;
public DomElementResolveProblemDescriptorImpl(@NotNull final GenericDomValue domElement, @NotNull final PsiReference reference, LocalQuickFix... quickFixes) {
DomElementResolveProblemDescriptorImpl(@NotNull final GenericDomValue domElement,
@NotNull final PsiReference reference,
LocalQuickFix... quickFixes) {
super(domElement, reference instanceof FileReference ? ProblemsHolder.unresolvedReferenceMessage(reference) : XmlHighlightVisitor.getErrorDescription(reference), HighlightSeverity.ERROR, quickFixes);
myReference = reference;
}
@@ -58,14 +59,7 @@ class DomElementResolveProblemDescriptorImpl extends DomElementProblemDescriptor
final PsiReference reference = myReference;
PsiElement element = reference.getElement();
if (element instanceof XmlAttributeValue && element.getTextLength() == 0) return NO_PROBLEM;
final TextRange referenceRange = reference.getRangeInElement();
if (referenceRange.isEmpty()) {
int startOffset = referenceRange.getStartOffset();
return element instanceof XmlAttributeValue
? Pair.create((TextRange)new UnfairTextRange(startOffset - 1, startOffset + 1), element)
: Pair.create(TextRange.from(startOffset, 1), element);
}
TextRange referenceRange = reference.getRangeInElement();
return Pair.create(referenceRange, element);
}
}