mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-184920 Create external annotation for integral ranges and annotate some JDK methods
This commit is contained in:
+10
-17
@@ -4,10 +4,11 @@ package com.intellij.codeInspection.dataFlow.rangeSet;
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInspection.dataFlow.DfaFactType;
|
||||
import com.intellij.codeInspection.dataFlow.value.*;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.PsiAnnotation;
|
||||
import com.intellij.psi.PsiModifierListOwner;
|
||||
import com.intellij.psi.PsiPrimitiveType;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.util.ThreeState;
|
||||
import com.siyeh.ig.callMatcher.CallMapper;
|
||||
import com.siyeh.ig.callMatcher.CallMatcher;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -24,16 +25,6 @@ import static com.intellij.codeInsight.AnnotationUtil.CHECK_TYPE;
|
||||
* @author Tagir Valeev
|
||||
*/
|
||||
public abstract class LongRangeSet {
|
||||
// TODO: create an external annotation and use it
|
||||
private static final CallMapper<LongRangeSet> KNOWN_METHOD_RANGES = new CallMapper<LongRangeSet>()
|
||||
.register(CallMatcher.instanceCall("java.time.LocalDateTime", "getHour"), range(0, 23))
|
||||
.register(CallMatcher.instanceCall("java.time.LocalDateTime", "getMinute", "getSecond"), range(0, 59))
|
||||
.register(CallMatcher.staticCall(CommonClassNames.JAVA_LANG_LONG, "numberOfLeadingZeros", "numberOfTrailingZeros", "bitCount"),
|
||||
range(0, Long.SIZE))
|
||||
.register(CallMatcher.staticCall(CommonClassNames.JAVA_LANG_INTEGER, "numberOfLeadingZeros", "numberOfTrailingZeros", "bitCount"),
|
||||
range(0, Integer.SIZE))
|
||||
.register(CallMatcher.instanceCall(CommonClassNames.JAVA_LANG_ENUM, "ordinal").parameterCount(0), indexRange());
|
||||
|
||||
LongRangeSet() {}
|
||||
|
||||
/**
|
||||
@@ -446,10 +437,12 @@ public abstract class LongRangeSet {
|
||||
@NotNull
|
||||
public static LongRangeSet fromPsiElement(PsiModifierListOwner owner) {
|
||||
if (owner == null) return all();
|
||||
if (owner instanceof PsiMethod) {
|
||||
LongRangeSet rangeSet = KNOWN_METHOD_RANGES.mapFirst((PsiMethod)owner);
|
||||
if (rangeSet != null) {
|
||||
return rangeSet;
|
||||
PsiAnnotation rangeAnnotation = AnnotationUtil.findAnnotation(owner, "org.jetbrains.annotations.Range");
|
||||
if(rangeAnnotation != null) {
|
||||
Long from = AnnotationUtil.getLongAttributeValue(rangeAnnotation, "from");
|
||||
Long to = AnnotationUtil.getLongAttributeValue(rangeAnnotation, "to");
|
||||
if(from != null && to != null && to >= from) {
|
||||
return range(from, to);
|
||||
}
|
||||
}
|
||||
if (AnnotationUtil.isAnnotated(owner, "javax.annotation.Nonnegative", CHECK_TYPE)) {
|
||||
|
||||
@@ -7,7 +7,10 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.Processors;
|
||||
import com.intellij.util.containers.ConcurrentFactoryMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.THashMap;
|
||||
@@ -487,6 +490,13 @@ public class AnnotationUtil {
|
||||
return constValue instanceof Boolean ? (Boolean)constValue : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Long getLongAttributeValue(@NotNull PsiAnnotation anno, @Nullable final String attributeName) {
|
||||
PsiAnnotationMemberValue attrValue = anno.findAttributeValue(attributeName);
|
||||
Object constValue = JavaPsiFacade.getInstance(anno.getProject()).getConstantEvaluationHelper().computeConstantExpression(attrValue);
|
||||
return constValue instanceof Number ? ((Number)constValue).longValue() : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getDeclaredStringAttributeValue(@NotNull PsiAnnotation anno, @Nullable final String attributeName) {
|
||||
PsiAnnotationMemberValue attrValue = anno.findDeclaredAttributeValue(attributeName);
|
||||
|
||||
@@ -61,6 +61,12 @@
|
||||
<item name="java.lang.Comparable int compareTo(T) 0">
|
||||
<annotation name="org.jetbrains.annotations.NotNull" />
|
||||
</item>
|
||||
<item name='java.lang.Enum int ordinal()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="0"/>
|
||||
<val name="to" val="java.lang.Integer.MAX_VALUE"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.lang.Enum T valueOf(java.lang.Class<T>, java.lang.String)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
@@ -70,6 +76,24 @@
|
||||
<item name='java.lang.Enum T valueOf(java.lang.Class<T>, java.lang.String) 1'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='java.lang.Integer int numberOfLeadingZeros(int)'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="0"/>
|
||||
<val name="to" val="32"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.lang.Integer int numberOfTrailingZeros(int)'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="0"/>
|
||||
<val name="to" val="32"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.lang.Integer int bitCount(int)'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="0"/>
|
||||
<val name="to" val="32"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.lang.Integer java.lang.Integer valueOf(java.lang.String)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
@@ -91,6 +115,24 @@
|
||||
<item name='java.lang.Long java.lang.Long valueOf(long)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='java.lang.Long int numberOfLeadingZeros(long)'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="0"/>
|
||||
<val name="to" val="64"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.lang.Long int numberOfTrailingZeros(long)'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="0"/>
|
||||
<val name="to" val="64"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.lang.Long int bitCount(long)'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="0"/>
|
||||
<val name="to" val="64"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.lang.Object java.lang.Class<?> getClass()'>
|
||||
<annotation name='org.jetbrains.annotations.Contract'>
|
||||
<val name="pure" val="true"/>
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
<root>
|
||||
<item name='java.time.LocalDate int getDayOfMonth()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="1"/>
|
||||
<val name="to" val="31"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalDate int getDayOfYear()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="1"/>
|
||||
<val name="to" val="366"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalDate int getMonthValue()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="1"/>
|
||||
<val name="to" val="12"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalDateTime int getDayOfMonth()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="1"/>
|
||||
<val name="to" val="31"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalDateTime int getDayOfYear()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="1"/>
|
||||
<val name="to" val="366"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalDateTime int getHour()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="0"/>
|
||||
<val name="to" val="23"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalDateTime int getMinute()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="0"/>
|
||||
<val name="to" val="59"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalDateTime int getMonthValue()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="1"/>
|
||||
<val name="to" val="12"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalDateTime int getNano()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="0"/>
|
||||
<val name="to" val="999_999_999"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalDateTime int getSecond()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="0"/>
|
||||
<val name="to" val="59"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalDateTime int getYear()'>
|
||||
<annotation name='org.jetbrains.annotations.Contract'>
|
||||
<val name="pure" val="true"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalDateTime java.time.LocalDateTime from(java.time.temporal.TemporalAccessor)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='java.time.LocalDateTime java.time.LocalDateTime of(int, int, int, int, int)'>
|
||||
<annotation name='org.jetbrains.annotations.Contract'>
|
||||
<val name="pure" val="true"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalDateTime java.time.LocalDateTime of(int, int, int, int, int, int)'>
|
||||
<annotation name='org.jetbrains.annotations.Contract'>
|
||||
<val name="pure" val="true"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalDateTime java.time.LocalDateTime of(int, int, int, int, int, int, int)'>
|
||||
<annotation name='org.jetbrains.annotations.Contract'>
|
||||
<val name="pure" val="true"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalDateTime java.time.LocalDateTime of(int, java.time.Month, int, int, int)'>
|
||||
<annotation name='org.jetbrains.annotations.Contract'>
|
||||
<val name="pure" val="true"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalDateTime java.time.LocalDateTime of(int, java.time.Month, int, int, int, int)'>
|
||||
<annotation name='org.jetbrains.annotations.Contract'>
|
||||
<val name="pure" val="true"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalDateTime java.time.LocalDateTime of(int, java.time.Month, int, int, int, int, int)'>
|
||||
<annotation name='org.jetbrains.annotations.Contract'>
|
||||
<val name="pure" val="true"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalDateTime java.time.LocalDateTime parse(java.lang.CharSequence)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='java.time.LocalDateTime java.time.LocalDateTime parse(java.lang.CharSequence, java.time.format.DateTimeFormatter)'>
|
||||
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||
</item>
|
||||
<item name='java.time.LocalTime int getHour()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="0"/>
|
||||
<val name="to" val="23"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalTime int getMinute()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="0"/>
|
||||
<val name="to" val="59"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalTime int getNano()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="0"/>
|
||||
<val name="to" val="999_999_999"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.LocalTime int getSecond()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="0"/>
|
||||
<val name="to" val="59"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.Month int getValue()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="1"/>
|
||||
<val name="to" val="12"/>
|
||||
</annotation>
|
||||
<annotation name='org.jetbrains.annotations.Contract'>
|
||||
<val name="pure" val="true"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.Month int length()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="28"/>
|
||||
<val name="to" val="31"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.Month int maxLength()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="29"/>
|
||||
<val name="to" val="31"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.Month int minLength()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="28"/>
|
||||
<val name="to" val="31"/>
|
||||
</annotation>
|
||||
</item>
|
||||
<item name='java.time.Year int length()'>
|
||||
<annotation name='org.jetbrains.annotations.Range'>
|
||||
<val name="from" val="365"/>
|
||||
<val name="to" val="366"/>
|
||||
</annotation>
|
||||
</item>
|
||||
</root>
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
package org.jetbrains.annotations;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* An annotation which allows to specify for integral type (byte, char, short, int, long) an allowed values range.
|
||||
* <p>
|
||||
* This is an experimental annotation which can be changed or removed without additional notice!
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.CLASS)
|
||||
@Target({ElementType.TYPE_USE})
|
||||
@ApiStatus.Experimental
|
||||
public @interface Range {
|
||||
/**
|
||||
* @return minimal allowed value (inclusive)
|
||||
*/
|
||||
long from();
|
||||
|
||||
/**
|
||||
* @return maximal allowed value (inclusive)
|
||||
*/
|
||||
long to();
|
||||
}
|
||||
Reference in New Issue
Block a user