Quellcode durchsuchen

#37 javadoc: reflection

Ranides Atterwim vor 3 Jahren
Ursprung
Commit
0b423c866c

+ 4 - 0
assira.core/src/main/java/net/ranides/assira/collection/IntCollection.java

@@ -8,6 +8,8 @@ package net.ranides.assira.collection;
 
 import java.util.Collection;
 import java.util.stream.IntStream;
+
+import net.ranides.assira.annotations.Meta;
 import net.ranides.assira.collection.arrays.IntArrays;
 import net.ranides.assira.collection.iterators.IntIterator;
 
@@ -77,6 +79,7 @@ public interface IntCollection extends Collection<Integer> {
      * @param value value
      * @return bool
      */
+    @Meta.Alias("remove")
     boolean rem(Object value);
 
     /**
@@ -98,6 +101,7 @@ public interface IntCollection extends Collection<Integer> {
      * @param a a
      * @return array
      */
+    @Meta.Alias("toIntArray")
     int[] toArray(int[] a);
 
     /**

+ 5 - 2
assira.core/src/main/java/net/ranides/assira/reflection/IAttribute.java

@@ -152,9 +152,12 @@ public enum IAttribute {
      * it means that IElement is declared or inherited.
      * 
      * Allowed for inner classes, methods and fields.
-     * Used by IHints to include inherited members.
+     *
+     * USAGE:
+     * Can be used by IHints and IElements. If marked as required, it enables deep scan
+     * which returns both public and non-public members, including inherited ones.
      */
-    ANY             (0x0020_0000, 0),   // special: used only by AHints for deep scan of declared fields/methods/classes
+    ANY             (0x0020_0000, 0),
 
     /**
      * This is type trait: it means that IClass is array

+ 5 - 4
assira.core/src/main/java/net/ranides/assira/reflection/IAttributes.java

@@ -1,5 +1,6 @@
 package net.ranides.assira.reflection;
 
+import net.ranides.assira.annotations.Meta;
 import net.ranides.assira.collection.sets.MaskFactory;
 import net.ranides.assira.collection.sets.MaskSet;
 import net.ranides.assira.reflection.util.ClassTraits;
@@ -81,6 +82,7 @@ public class IAttributes {
      * @param attr attr
      * @return boolean
      */
+    @Meta.Alias("has")
     public boolean contains(IAttribute attr) {
         return values.contains(attr);
     }
@@ -91,6 +93,7 @@ public class IAttributes {
      * @param attrs attrs
      * @return boolean
      */
+    @Meta.Alias("has")
     public boolean containsAll(IAttributes attrs) {
         return values.containsAll(attrs.values);
     }
@@ -98,11 +101,10 @@ public class IAttributes {
     /**
      * Returns true if collection contains specified attribute
      *
-     * It is alias for "contains".
-     *
      * @param attr attr
      * @return boolean
      */
+    @Meta.Alias("contains")
     public boolean has(IAttribute attr) {
         return values.contains(attr);
     }
@@ -110,11 +112,10 @@ public class IAttributes {
     /**
      * Returns true if collection contains all specified attributes
      *
-     * It is alias for "containsAll".
-     *
      * @param attrs attrs
      * @return boolean
      */
+    @Meta.Alias("containsAll")
     public boolean has(IAttributes attrs) {
         return values.containsAll(attrs.values);
     }

+ 412 - 36
assira.core/src/main/java/net/ranides/assira/reflection/IClass.java

@@ -11,127 +11,389 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
 
+import net.ranides.assira.annotations.Meta;
 import net.ranides.assira.reflection.impl.FClass;
 import net.ranides.assira.reflection.impl.NClass;
 import net.ranides.assira.reflection.impl.SClass;
 import net.ranides.assira.reflection.util.ClassUtils;
 
 /**
- * 
+ * This interface is extension of standard "Class" interface.
+ * It allows inspection in a bit more fluent way and it supports generics.
+ *
+ * It can represent:
+ *  - ordinary raw "Class"
+ *  - generic class with resolved parameters
+ *  - TypeToken
+ *  - wildcard type
+ *  - symbolic class
+ *
  * @author Ranides Atterwim {@literal <ranides@gmail.com>}
+ * @param <T> T
  */
 @SuppressWarnings("PMD.TooManyDifferentMethods")
 public interface IClass<T> extends IElement, Comparable<IClass<?>> {
 
+    /**
+     * Constant representing "empty value"
+     */
     @SuppressWarnings("rawtypes")
     IClass NULL = NClass.getInstance();
 
-    IClass<Object>    OBJECT = typeinfo(Object.class);
-    IClass<Void>      VOID   = typeinfo(void.class);
-    IClass<Byte>      BYTE   = typeinfo(byte.class);
-    IClass<Short>     SHORT  = typeinfo(short.class);
-    IClass<Integer>   INT    = typeinfo(int.class);
-    IClass<Long>      LONG   = typeinfo(long.class);
-    IClass<Float>     FLOAT  = typeinfo(float.class);
-    IClass<Double>    DOUBLE = typeinfo(double.class);
-    IClass<Character> CHAR   = typeinfo(char.class);
-    IClass<Boolean>   BOOL   = typeinfo(boolean.class);
-    IClass<String>    STRING = typeinfo(String.class);
-    IClass<Number>    NUMBER = typeinfo(Number.class);
-
-    /**
-     * Collect information using java.reflection API
+    /**
+     * Constant representing Object.class
+     */
+    IClass<Object> OBJECT = typeinfo(Object.class);
+
+    /**
+     * Constant representing primitive void.class
+     */
+    IClass<Void> VOID = typeinfo(void.class);
+
+    /**
+     * Constant representing primitive byte.class
+     */
+    IClass<Byte> BYTE = typeinfo(byte.class);
+
+    /**
+     * Constant representing primitive short.class
+     */
+    IClass<Short> SHORT = typeinfo(short.class);
+
+    /**
+     * Constant representing primitive int.class
+     */
+    IClass<Integer> INT = typeinfo(int.class);
+
+    /**
+     * Constant representing primitive long.class
+     */
+    IClass<Long> LONG = typeinfo(long.class);
+
+    /**
+     * Constant representing primitive float.class
+     */
+    IClass<Float> FLOAT = typeinfo(float.class);
+
+    /**
+     * Constant representing primitive double.class
+     */
+    IClass<Double> DOUBLE = typeinfo(double.class);
+
+    /**
+     * Constant representing primitive char.class
+     */
+    IClass<Character> CHAR = typeinfo(char.class);
+
+    /**
+     * Constant representing primitive boolean.class
+     */
+    IClass<Boolean> BOOL = typeinfo(boolean.class);
+
+    /**
+     * Constant representing String.class
+     */
+    IClass<String> STRING = typeinfo(String.class);
+
+    /**
+     * Constant representing Number.class
+     */
+    IClass<Number> NUMBER = typeinfo(Number.class);
+
+    /**
+     * Factory: creates IClass from java.reflection type
+     *
      * @param type type
      * @return IClass
      */
     static IClass<?> typeinfo(Type type) {
         return IContext.getDefault().typeinfo(type);
     }
-    
+
+    /**
+     * Factory: creates IClass from java.reflection class
+     *
+     * @param type type
+     * @param <R> R
+     * @return IClass
+     */
     static <R> IClass<R> typeinfo(Class<R> type) {
         return IContext.getDefault().typeinfo(type);
     }
 
+    /**
+     * Factory: creates IClass for class stored in provided StackTraceElement
+     *
+     * @param frame frame
+     * @return IClass
+     */
     static IClass<?> typeinfo(StackTraceElement frame) {
         return typeinfo(frame.getClassName());
     }
 
+    /**
+     * Factory: creates IClass for class with provided fully qualified name
+     *
+     * TODO: #92 support syntax for generics
+     *
+     * @param type type
+     * @return IClass
+     */
     static IClass<?> typeinfo(String type) {
         return ClassUtils.forName(type)
             .map(IContext.getDefault()::typeinfo)
             .orElseThrow(() -> new IReflectiveException("Unknown class name: " + type));
     }
 
+    /**
+     * Factory: creates IClass for provided object.
+     *
+     * Please remember about type-erasure, this method has almost no way to deduce generic parameters.
+     *
+     * @param object object
+     * @param <R> R
+     * @return IClass
+     */
+    @Meta.Alias("typefor")
     static <R> IClass<R> typeof(R object) {
         return IContext.getDefault().typefor(object);
     }
-    
+
+    /**
+     * Factory: creates IClass for provided object.
+     *
+     * Please remember about type-erasure, this method has almost no way to deduce generic parameters.
+     *
+     * @param object object
+     * @param <R> R
+     * @return IClass
+     */
+    @Meta.Alias("typeof")
     static <R> IClass<R> typefor(R object) {
         return IContext.getDefault().typefor(object);
     }
-    
+
+    /**
+     * Factory: creates generic IClass from provided types and parameters
+     *
+     * @param type type
+     * @param params params
+     * @param <R> R
+     * @return IClass
+     */
     static <R> IClass<R> generic(Class<R> type, IClass<?>... params) {
         return FClass.newClass(type, params);
     }
-    
+
+    /**
+     * Factory: creates generic IClass from provided types and parameters
+     *
+     * @param type type
+     * @param params params
+     * @param <R> R
+     * @return IClass
+     */
     static <R> IClass<R> generic(Class<R> type, Class<?>... params) {
         return FClass.newClass(type, Arrays.stream(params).map(IClass::typeinfo).toArray(IClass<?>[]::new));
     }
 
+    /**
+     * Factory: creates symbolic IClass representing type with provided name
+     *
+     * Symbolic types could be used for example, in bytecode generators,
+     * where you don't need more that fully qualified name.
+     *
+     * It does not give information about inheritance, but tries to resolve information
+     * about outer classes by parsing name (JDK uses $ character inside inner class names)
+     *
+     * It throws exception if you try to get some materialized reflective data.
+     *
+     * @param name name
+     * @return IClass
+     */
     static IClass<?> symbolic(String name) {
         return new SClass(name);
     }
     
     @Override
     IClasses collect();
-    
+
+    /**
+     * Returns list of generic parameters.
+     *
+     * If it is impossible to resolve parameters, returned list contains wildcard types
+     * with at least type bounds defined as in generic class declaration.
+     *
+     * @return List
+     */
     List<IClass<?>> params();
-    
+
+    /**
+     * Returns all fields inside class
+     *
+     * Strategy for members scan:
+     *   - by default returns all public fields (including inherited)
+     *   - if you use non-public hints, inherited members are still included
+     *   - if you add DECLARED hint, inherited members will be discarded.
+     *
+     * @return IFields
+     */
     IFields fields();
 
+    /**
+     * Returns first field with specified name.
+     *
+     * It searches for private and inherited fields too.
+     *
+     * @param name name
+     * @return Optional
+     */
     Optional<IField> field(String name);
-    
+
+    /**
+     * Returns all constructors
+     *
+     * By default returns only public constructors.
+     *
+     * @return IConstructors
+     */
     IConstructors<T> constructors();
-    
+
+    /**
+     * Returns all methods of class.
+     *
+     * Strategy for members scan:
+     *   - by default returns all public methods (including inherited)
+     *   - if you use non-public hints, inherited members are still included
+     *   - if you add DECLARED hint, inherited members will be discarded.
+     *
+     * @return IMethods
+     */
     IMethods methods();
 
+    /**
+     * Returns first method with specified name.
+     *
+     * It searches for private and inherited methods too.
+     *
+     * @param name name
+     * @return Optional
+     */
     Optional<IMethod> method(String name);
     
     /**
-     * only parent class
+     * Returns base class
+     * If there is not base class, returns {@link #NULL} constant.
+     *
+     * For wildcard types deduces base class from upper bound.
+     * For symbolic types returns {@link #OBJECT}
+     *
      * @return IClass
      */
     @Override
     IClass<?> parent();
     
     /**
-     * 
-     * @return only parent classes
+     * Returns all classes from inheritance chain
+     *
+     * @return IClasses
      */
     IClasses parents();
-    
+
+    /**
+     * Returns all implemented interfaces
+     *
+     * Strategy for members scan:
+     *   - by default all implemented interfaces
+     *   - if you use DECLARED hint, inherited interfaces will be discarded
+     *
+     * @return IClasses
+     */
     IClasses interfaces();
-    
+
+    /**
+     * Returns outer class, if this class is inner class.
+     * Returns {@link #NULL} otherwise.
+     *
+     * @return IClass
+     */
     IClass<?> outer();
-    
+
+    /**
+     * Returns all inner classes inside this class.
+     *
+     * Strategy for members scan:
+     *   - by default returns all declared, public and non-public classes
+     *   - inherited inner classes are not returned
+     *
+     * @return IClasses
+     */
     IClasses inner();
-    
+
+    /**
+     * Returns raw class (type erasured generic).
+     *
+     * For wildcard types it returns {@code Object.class}
+     *
+     * It throws exception for non-reflective types (e.g. symbolic).
+     *
+     * @return Class
+     */
     Class<T> raw();
-    
+
+    /**
+     * Returns short name, which means class name without package name or outer class
+     *
+     * @return String
+     */
     String shortName();
 
+    /**
+     * Returns package name for this class
+     *
+     * @return String
+     */
     String packageName();
 
+    /**
+     * Returns component type if type is an array.
+     * Throws IReflectiveException otherwise
+     *
+     * @return IClass
+     */
     IClass<?> component();
-    
+
+    /**
+     * Returns reflective type assocciated with this type.
+     * Some type are not reflective and will throw IReflectiveException
+     *
+     * @return Type
+     */
     Type reflective();
-    
+
+    /**
+     * Creates new object of this type.
+     *
+     * It uses constructor even if it is non-public.
+     *
+     * @return object
+     */
     T construct();
-    
+
+    /**
+     * Creates new object of this type.
+     *
+     * It searches for constructor matching arguments.
+     * It uses matched constructor even if it is non-public.
+     *
+     * @param arguments arguments
+     * @return object
+     */
     T construct(Object... arguments);
 
     /**
      * Checks if {@code this} is superclass of {@code type} (or equals)
+     *
      * @param type type
      * @return bool
      */
@@ -139,6 +401,7 @@ public interface IClass<T> extends IElement, Comparable<IClass<?>> {
 
 	/**
 	 * Checks if {@code this} is superclass of {@code type} (or equals)
+     *
 	 * @param type type
      * @return bool
 	 */
@@ -146,6 +409,7 @@ public interface IClass<T> extends IElement, Comparable<IClass<?>> {
 
     /**
      * Checks if {@code this} is a subclass of {@code type} (or equals)
+     *
      * @param type type
      * @return bool
      */
@@ -153,43 +417,155 @@ public interface IClass<T> extends IElement, Comparable<IClass<?>> {
 
 	/**
 	 * Checks if {@code this} is a subclass of {@code type} (or equals)
+     *
 	 * @param type type
 	 * @return bool
 	 */
 	boolean isSubclass(IClass<?> type);
 
+    /**
+     * Returns true if (this is instance of type) and (type is instance of this)
+     *
+     * It uses autoboxing
+     *
+     * @param type type
+     * @return boolean
+     */
     boolean isEquivalent(Class<?> type);
 
+    /**
+     * Returns true if (this is instance of type) and (type is instance of this)
+     *
+     * It uses autoboxing
+     * It uses generic parameters.
+     *
+     * @param type
+     * @return boolean
+     */
     boolean isEquivalent(IClass<?> type);
 
+    /**
+     * Returns true if value is instance of this type.
+     *
+     * @param value value
+     * @return boolean
+     */
     boolean isInstance(Object value);
-    
+
+    /**
+     * Casts provided value to this type.
+     * Throws ClassCastException if impossible
+     *
+     * If you prefer using optional instead of try/catch, lets look at
+     * {@link ClassUtils#cast(IClass, Object)}.
+     *
+     * @param value value
+     * @return value
+     */
     T cast(Object value);
 
+    /**
+     * Alias for {@code attribute(IAttribute.INTERFACE)}.
+     *
+     * @return boolean
+     */
+    @Meta.Alias("attribute(INTERFACE)")
     boolean isInterface();
 
+    /**
+     * Alias for {@code attribute(IAttribute.ABSTRACT)}.
+     *
+     * @return boolean
+     */
+    @Meta.Alias("attribute(ABSTRACT)")
     boolean isAbstract();
 
+    /**
+     * Alias for {@code attribute(IAttribute.ANNOTATION)}.
+     *
+     * @return boolean
+     */
+    @Meta.Alias("attribute(ANNOTATION)")
     boolean isAnnotation();
 
+    /**
+     * Alias for {@code attribute(IAttribute.ENUM)}.
+     *
+     * @return boolean
+     */
+    @Meta.Alias("attribute(ENUM)")
     boolean isEnum();
 
+    /**
+     * Alias for {@code attribute(IAttribute.PARAMETERIZED)}.
+     *
+     * @return boolean
+     */
+    @Meta.Alias("attribute(PARAMETERIZED)")
     boolean isParameterized();
 
+    /**
+     * Alias for {@code attribute(IAttribute.ARRAY)}.
+     *
+     * @return boolean
+     */
+    @Meta.Alias("attribute(ARRAY)")
     boolean isArray();
 
+    /**
+     * Alias for {@code isArray() && component().isPrimitive()}.
+     *
+     * @return boolean
+     */
+    @Meta.Alias("isArray() && component().isPrimitive()")
     boolean isPrimitiveArray();
 
+    /**
+     * Alias for {@code attribute(IAttribute.PRIMITIVE)}.
+     *
+     * @return boolean
+     */
+    @Meta.Alias("attribute(PRIMITIVE)")
     boolean isPrimitive();
 
+    /**
+     * Alias for {@code attribute(IAttribute.NUMBER)}.
+     *
+     * @return boolean
+     */
+    @Meta.Alias("attribute(NUMBER)")
     boolean isNumber();
 
+    /**
+     * Alias for {@code attribute(IAttribute.INTEGER)}.
+     *
+     * @return boolean
+     */
+    @Meta.Alias("attribute(INTEGER)")
     boolean isInteger();
 
+    /**
+     * Alias for {@code attribute(IAttribute.BOXED)}.
+     *
+     * @return boolean
+     */
+    @Meta.Alias("attribute(BOXED)")
     boolean isBoxed();
 
+    /**
+     * Alias for {@code attribute(IAttribute.VOID)}.
+     *
+     * @return boolean
+     */
+    @Meta.Alias("attribute(VOID)")
     boolean isVoid();
 
+    /**
+     * Alias for {@code attribute(IAttribute.BOOLEAN)}.
+     *
+     * @return boolean
+     */
+    @Meta.Alias("attribute(BOOLEAN)")
     boolean isBoolean();
 
 }

+ 2 - 0
assira.core/src/main/java/net/ranides/assira/reflection/IMethod.java

@@ -25,6 +25,8 @@ public interface IMethod extends IExecutable {
         return FMethod.newMethod(method);
     }
 
+    // TODO: typeinfo(StackTraceElement)
+
     static IMethod symbolic(String name, IArguments args, IClass<?> rets) {
         return new SMethod(name, args, rets);
     }

+ 1 - 0
assira.core/src/main/java/net/ranides/assira/reflection/impl/RWClass.java

@@ -114,6 +114,7 @@ public class RWClass<T> extends AClass<T> implements Serializable {
 
     @Override
     public String name() {
+        // @todo #94 wilcard name
         return type.getTypeName();
     }
     

+ 1 - 1
assira.core/src/main/java/net/ranides/assira/text/ASCII.java

@@ -7,7 +7,7 @@ package net.ranides.assira.text;
 /**
  * Utility class that implements the standard C ctype functionality.
  *
- * TODO license problem, it can't be licensed under WTFPL
+ * TODO #93 license problem, it can't be licensed under WTFPL
  *
  * @author Hong Zhang
  */

+ 12 - 2
assira.core/src/test/java/net/ranides/assira/reflection/IClassTest.java

@@ -11,8 +11,7 @@ import java.io.IOException;
 import java.util.List;
 import java.util.Map;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.*;
 
 public class IClassTest {
 
@@ -60,6 +59,17 @@ public class IClassTest {
         assertEquals("net.ranides.assira.collection.maps", new TypeToken<OpenMap<String, Float>>() {}.packageName());
     }
 
+    @Test
+    public void noResolveParameters() {
+        List<IClass<?>> params1 = IClass.typeinfo(Map.class).params();
+
+        assertEquals(Object.class, params1.get(0).raw());
+        assertEquals(Object.class, params1.get(1).raw());
+
+        assertNotEquals(Object.class, params1.get(0).reflective());
+        assertNotEquals(Object.class, params1.get(1).reflective());
+    }
+
     private static final class Lister {
 
         public List<Float> list;