Permalink
Browse files

Add mandatory TYPE parameter to all typeof classes

  • Loading branch information...
LadyCailin committed Oct 9, 2017
1 parent cd440d2 commit 15e4836f17bbab4ad98ad5219d7e54d190956dba
Showing with 2,282 additions and 1,961 deletions.
  1. +4 −3 src/main/java/com/laytonsmith/PureUtilities/ClassLoading/Annotations/CacheAnnotations.java
  2. +90 −59 src/main/java/com/laytonsmith/PureUtilities/Common/Annotations/AnnotationChecks.java
  3. +2 −2 src/main/java/com/laytonsmith/core/Procedure.java
  4. +7 −7 src/main/java/com/laytonsmith/core/Static.java
  5. +2 −1 src/main/java/com/laytonsmith/core/compiler/keywords/ClosureKeyword.java
  6. +3 −2 src/main/java/com/laytonsmith/core/compiler/keywords/IClosureKeyword.java
  7. +8 −7 src/main/java/com/laytonsmith/core/constructs/CArray.java
  8. +96 −92 src/main/java/com/laytonsmith/core/constructs/CBoolean.java
  9. +552 −523 src/main/java/com/laytonsmith/core/constructs/CByteArray.java
  10. +198 −153 src/main/java/com/laytonsmith/core/constructs/CClassType.java
  11. +6 −4 src/main/java/com/laytonsmith/core/constructs/CClosure.java
  12. +3 −3 src/main/java/com/laytonsmith/core/constructs/CDouble.java
  13. +7 −3 src/main/java/com/laytonsmith/core/constructs/CIClosure.java
  14. +3 −0 src/main/java/com/laytonsmith/core/constructs/CInt.java
  15. +135 −132 src/main/java/com/laytonsmith/core/constructs/CMutablePrimitive.java
  16. +63 −66 src/main/java/com/laytonsmith/core/constructs/CNull.java
  17. +14 −11 src/main/java/com/laytonsmith/core/constructs/CNumber.java
  18. +14 −11 src/main/java/com/laytonsmith/core/constructs/CPrimitive.java
  19. +92 −86 src/main/java/com/laytonsmith/core/constructs/CResource.java
  20. +152 −149 src/main/java/com/laytonsmith/core/constructs/CSlice.java
  21. +3 −0 src/main/java/com/laytonsmith/core/constructs/CString.java
  22. +59 −59 src/main/java/com/laytonsmith/core/constructs/CVoid.java
  23. +6 −6 src/main/java/com/laytonsmith/core/constructs/Construct.java
  24. +1 −2 src/main/java/com/laytonsmith/core/constructs/IVariable.java
  25. +2 −2 src/main/java/com/laytonsmith/core/events/BoundEvent.java
  26. +8 −8 src/main/java/com/laytonsmith/core/exceptions/CRE/AbstractCREException.java
  27. +18 −14 src/main/java/com/laytonsmith/core/exceptions/CRE/CREBadEntityException.java
  28. +20 −15 src/main/java/com/laytonsmith/core/exceptions/CRE/CREBadEntityTypeException.java
  29. +21 −16 src/main/java/com/laytonsmith/core/exceptions/CRE/CREBindException.java
  30. +22 −17 src/main/java/com/laytonsmith/core/exceptions/CRE/CRECastException.java
  31. +20 −15 src/main/java/com/laytonsmith/core/exceptions/CRE/CREEnchantmentException.java
  32. +20 −15 src/main/java/com/laytonsmith/core/exceptions/CRE/CREError.java
  33. +20 −16 src/main/java/com/laytonsmith/core/exceptions/CRE/CREEventException.java
  34. +19 −15 src/main/java/com/laytonsmith/core/exceptions/CRE/CREException.java
  35. +22 −17 src/main/java/com/laytonsmith/core/exceptions/CRE/CREFormatException.java
  36. +20 −15 src/main/java/com/laytonsmith/core/exceptions/CRE/CREIOException.java
  37. +20 −15 src/main/java/com/laytonsmith/core/exceptions/CRE/CREIllegalArgumentException.java
  38. +21 −16 src/main/java/com/laytonsmith/core/exceptions/CRE/CREIncludeException.java
  39. +21 −16 src/main/java/com/laytonsmith/core/exceptions/CRE/CREIndexOverflowException.java
  40. +21 −16 src/main/java/com/laytonsmith/core/exceptions/CRE/CREInsufficientArgumentsException.java
  41. +21 −16 src/main/java/com/laytonsmith/core/exceptions/CRE/CREInsufficientPermissionException.java
  42. +21 −16 src/main/java/com/laytonsmith/core/exceptions/CRE/CREInvalidPluginException.java
  43. +22 −17 src/main/java/com/laytonsmith/core/exceptions/CRE/CREInvalidProcedureException.java
  44. +21 −16 src/main/java/com/laytonsmith/core/exceptions/CRE/CREInvalidWorldException.java
  45. +21 −16 src/main/java/com/laytonsmith/core/exceptions/CRE/CRELengthException.java
  46. +20 −15 src/main/java/com/laytonsmith/core/exceptions/CRE/CRENotFoundException.java
  47. +21 −16 src/main/java/com/laytonsmith/core/exceptions/CRE/CRENullPointerException.java
  48. +4 −0 src/main/java/com/laytonsmith/core/exceptions/CRE/CREOAuthException.java
  49. +22 −17 src/main/java/com/laytonsmith/core/exceptions/CRE/CREPlayerOfflineException.java
  50. +21 −16 src/main/java/com/laytonsmith/core/exceptions/CRE/CREPluginChannelException.java
  51. +22 −17 src/main/java/com/laytonsmith/core/exceptions/CRE/CREPluginInternalException.java
  52. +21 −16 src/main/java/com/laytonsmith/core/exceptions/CRE/CRERangeException.java
  53. +20 −15 src/main/java/com/laytonsmith/core/exceptions/CRE/CREReadOnlyException.java
  54. +20 −15 src/main/java/com/laytonsmith/core/exceptions/CRE/CRESQLException.java
  55. +22 −17 src/main/java/com/laytonsmith/core/exceptions/CRE/CREScoreboardException.java
  56. +21 −16 src/main/java/com/laytonsmith/core/exceptions/CRE/CRESecurityException.java
  57. +20 −15 src/main/java/com/laytonsmith/core/exceptions/CRE/CREShellException.java
  58. +21 −16 src/main/java/com/laytonsmith/core/exceptions/CRE/CREStackOverflowError.java
  59. +25 −21 src/main/java/com/laytonsmith/core/exceptions/CRE/CREThrowable.java
  60. +21 −16 src/main/java/com/laytonsmith/core/exceptions/CRE/CREUnageableMobException.java
  61. +21 −16 src/main/java/com/laytonsmith/core/exceptions/CRE/CREUntameableMobException.java
  62. +7 −7 src/main/java/com/laytonsmith/core/functions/CompositeFunction.java
  63. +1 −1 src/main/java/com/laytonsmith/core/functions/DataHandling.java
  64. +8 −8 src/main/java/com/laytonsmith/core/functions/Exceptions.java
  65. +5 −1 src/main/java/com/laytonsmith/core/natives/interfaces/ArrayAccess.java
  66. +7 −4 src/main/java/com/laytonsmith/core/natives/interfaces/Mixed.java
  67. +10 −5 src/main/java/com/laytonsmith/core/natives/interfaces/Sizable.java
  68. +1 −1 src/main/java/com/laytonsmith/tools/Interpreter.java
@@ -28,7 +28,7 @@
*
*/
public class CacheAnnotations {
public static void main(String[] args) throws Exception {
File outputDir = new File(args[0]);
File scanDir = new File(args[1]);
@@ -50,7 +50,8 @@ public static void main(String[] args) throws Exception {
ClassDiscovery.getDefaultInstance().addDiscoveryLocation(cacheFile);
StreamUtils.GetSystemOut().println("-- Checking for custom compile errors --");
AnnotationChecks.checkForceImplementation();
AnnotationChecks.checkForTypeInTypeofClasses();
Implementation.setServerType(Implementation.Type.SHELL);
List<String> uhohs = new ArrayList<>();
Set<Class> apiClasses = new HashSet<>();
@@ -91,7 +92,7 @@ public static void main(String[] args) throws Exception {
if(!m.getName().equals("getName")){
if(c.getAnnotation(typeof.class) != null && !isGetNameExempt){
uhohs.add(c.getName() + " must implement " + m.getName() + "().");
}
}
}
} catch (SecurityException ex) {
throw new Error(ex);
@@ -1,7 +1,12 @@
package com.laytonsmith.PureUtilities.Common.Annotations;
import com.laytonsmith.PureUtilities.ClassLoading.ClassDiscovery;
import com.laytonsmith.PureUtilities.ClassLoading.ClassMirror.ClassMirror;
import com.laytonsmith.PureUtilities.ClassLoading.ClassMirror.FieldMirror;
import com.laytonsmith.PureUtilities.Common.ReflectionUtils;
import com.laytonsmith.PureUtilities.Common.StringUtils;
import com.laytonsmith.annotations.typeof;
import com.laytonsmith.core.constructs.CClassType;
import java.lang.reflect.Constructor;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
@@ -14,74 +19,100 @@
import java.util.Set;
/**
* This class is run by maven at compile time, and checks to ensure that the various
* annotations referenced here are checked, and fail if any of the parameters are missing.
* This class is run by maven at compile time, and checks to ensure that the various annotations referenced here are
* checked, and fail if any of the parameters are missing.
*/
public class AnnotationChecks {
public static void checkForceImplementation() throws Exception{
Set<String> uhohs = new HashSet<>();
Set<Constructor> set = ClassDiscovery.getDefaultInstance().loadConstructorsWithAnnotation(ForceImplementation.class);
for(Constructor cons : set){
Class superClass = cons.getDeclaringClass();
Set<Class> s = ClassDiscovery.getDefaultInstance().loadClassesThatExtend(superClass);
checkImplements: for(Class c : s){
// c is the class we want to check to make sure it implements cons
for(Constructor cCons : c.getDeclaredConstructors()){
if(Arrays.equals(cons.getParameterTypes(), cCons.getParameterTypes())){
continue checkImplements;
}
}
if(c.isMemberClass() && (c.getModifiers() & Modifier.STATIC) == 0){
// Ok, so, an inner, non static class actually passes the super class's reference to the constructor as
// the first parameter, at a byte code level. So this is a different type of error, or at least, a different
// error message will be helpful.
uhohs.add(c.getName() + " must be static.");
} else {
uhohs.add(c.getName() + " must implement the constructor with signature (" + getSignature(cons) + "), but doesn't.");
}
}
public static void checkForTypeInTypeofClasses() throws Exception {
Set<ClassMirror<?>> classes = ClassDiscovery.getDefaultInstance().getClassesWithAnnotation(typeof.class);
Set<String> errors = new HashSet<>();
for (ClassMirror<?> clazz : classes) {
try {
// Make sure that TYPE has the same type as the typeof annotation
CClassType TYPE = (CClassType)ReflectionUtils.get(clazz.loadClass(), "TYPE");
if(TYPE == null) {
errors.add("TYPE is null? " + clazz.getClassName());
continue;
}
Set<Method> set2 = ClassDiscovery.getDefaultInstance().loadMethodsWithAnnotation(ForceImplementation.class);
for(Method cons : set2){
Class superClass = cons.getDeclaringClass();
Set<Class> s = ClassDiscovery.getDefaultInstance().loadClassesThatExtend(superClass);
checkImplements: for(Class c : s){
// c is the class we want to check to make sure it implements cons
for(Method cCons : c.getDeclaredMethods()){
if(cCons.getName().equals(cons.getName()) && Arrays.equals(cons.getParameterTypes(), cCons.getParameterTypes())){
continue checkImplements;
}
}
uhohs.add(c.getName() + " must implement the method with signature " + cons.getName() + "(" + getSignature(cons) + "), but doesn't.");
}
if(!TYPE.val().equals(clazz.getAnnotation(typeof.class).getValue("value"))) {
errors.add(clazz.getClassName() + "'s TYPE value is different than the typeof annotation on it");
}
if(!uhohs.isEmpty()){
List<String> uhohsList = new ArrayList<>(uhohs);
Collections.sort(uhohsList);
throw new Exception("There " + StringUtils.PluralHelper(uhohs.size(), "error") + ". The following classes need to implement various methods:\n" + StringUtils.Join(uhohs, "\n"));
} catch (ReflectionUtils.ReflectionException ex) {
errors.add(clazz.getClassName() + " needs to add the following:\n\t@SuppressWarnings(\"FieldNameHidesFieldInSuperclass\")\n" +
"\tpublic static final CClassType TYPE = CClassType.get(\"" + clazz.getAnnotation(typeof.class).getValue("value") + "\");");
}
}
if (!errors.isEmpty()) {
throw new Exception("\n" + StringUtils.Join(errors, "\n"));
}
}
public static void checkForceImplementation() throws Exception {
Set<String> uhohs = new HashSet<>();
Set<Constructor> set = ClassDiscovery.getDefaultInstance().loadConstructorsWithAnnotation(ForceImplementation.class);
for (Constructor cons : set) {
Class superClass = cons.getDeclaringClass();
Set<Class> s = ClassDiscovery.getDefaultInstance().loadClassesThatExtend(superClass);
checkImplements:
for (Class c : s) {
// c is the class we want to check to make sure it implements cons
for (Constructor cCons : c.getDeclaredConstructors()) {
if (Arrays.equals(cons.getParameterTypes(), cCons.getParameterTypes())) {
continue checkImplements;
}
}
if (c.isMemberClass() && (c.getModifiers() & Modifier.STATIC) == 0) {
// Ok, so, an inner, non static class actually passes the super class's reference to the constructor as
// the first parameter, at a byte code level. So this is a different type of error, or at least, a different
// error message will be helpful.
uhohs.add(c.getName() + " must be static.");
} else {
uhohs.add(c.getName() + " must implement the constructor with signature (" + getSignature(cons) + "), but doesn't.");
}
}
}
Set<Method> set2 = ClassDiscovery.getDefaultInstance().loadMethodsWithAnnotation(ForceImplementation.class);
for (Method cons : set2) {
Class superClass = cons.getDeclaringClass();
Set<Class> s = ClassDiscovery.getDefaultInstance().loadClassesThatExtend(superClass);
checkImplements:
for (Class c : s) {
// c is the class we want to check to make sure it implements cons
for (Method cCons : c.getDeclaredMethods()) {
if (cCons.getName().equals(cons.getName()) && Arrays.equals(cons.getParameterTypes(), cCons.getParameterTypes())) {
continue checkImplements;
}
}
uhohs.add(c.getName() + " must implement the method with signature " + cons.getName() + "(" + getSignature(cons) + "), but doesn't.");
}
}
if (!uhohs.isEmpty()) {
List<String> uhohsList = new ArrayList<>(uhohs);
Collections.sort(uhohsList);
throw new Exception("There " + StringUtils.PluralHelper(uhohs.size(), "error") + ". The following classes need to implement various methods:\n" + StringUtils.Join(uhohs, "\n"));
}
private static String getSignature(Member executable){
List<String> l = new ArrayList<>();
}
private static String getSignature(Member executable) {
List<String> l = new ArrayList<>();
// for(Class cc : executable.getParameterTypes()){
// l.add(cc.getName());
// }
if(executable instanceof Method){
for(Class cc : ((Method)executable).getParameterTypes()){
l.add(cc.getName());
}
} else if(executable instanceof Constructor){
for(Class cc : ((Constructor)executable).getParameterTypes()){
l.add(cc.getName());
}
} else {
throw new Error("Unexpected executable type");
}
return StringUtils.Join(l, ", ");
if (executable instanceof Method) {
for (Class cc : ((Method) executable).getParameterTypes()) {
l.add(cc.getName());
}
} else if (executable instanceof Constructor) {
for (Class cc : ((Constructor) executable).getParameterTypes()) {
l.add(cc.getName());
}
} else {
throw new Error("Unexpected executable type");
}
return StringUtils.Join(l, ", ");
}
}
@@ -201,7 +201,7 @@ public Construct execute(List<Construct> args, Environment env, Target t) {
}
}
}
env.getEnv(GlobalEnv.class).GetVarList().set(new IVariable(new CClassType("array", Target.UNKNOWN), "@arguments", arguments, Target.UNKNOWN));
env.getEnv(GlobalEnv.class).GetVarList().set(new IVariable(CArray.TYPE, "@arguments", arguments, Target.UNKNOWN));
StackTraceManager stManager = env.getEnv(GlobalEnv.class).GetStackTraceManager();
stManager.addStackTraceElement(new ConfigRuntimeException.StackTraceElement("proc " + name, getTarget()));
try {
@@ -251,7 +251,7 @@ public Construct execute(List<Construct> args, Environment env, Target t) {
// Normal exit, but no return.
stManager.popStackTraceElement();
// If we got here, then there was no return value. This is fine, but only for returnType void or auto.
if(!(returnType.equals(CClassType.AUTO) || returnType.equals(CClassType.VOID))){
if(!(returnType.equals(CClassType.AUTO) || returnType.equals(CVoid.TYPE))){
throw new CRECastException("Expecting procedure \"" + name + "\" to return a value of type " + returnType.val() + ","
+ " but no value was returned.", tree.getTarget());
}
@@ -249,12 +249,12 @@ public static byte getInt8(Construct c, Target t) {
public static boolean getBoolean(Construct c) {
return ArgumentValidation.getBoolean(c, Target.UNKNOWN);
}
/**
* Returns a primitive from any given construct.
* @param c
* @param t
* @return
* @return
*/
public static CPrimitive getPrimitive(Construct c, Target t){
return ArgumentValidation.getObject(c, t, CPrimitive.class);
@@ -264,7 +264,7 @@ public static CPrimitive getPrimitive(Construct c, Target t){
* Returns a CByteArray from any given construct.
* @param c
* @param t
* @return
* @return
*/
public static CByteArray getByteArray(Construct c, Target t) {
return ArgumentValidation.getByteArray(c, t);
@@ -459,7 +459,7 @@ public static Construct resolveConstruct(String val, Target t) throws ConfigRunt
return CNull.NULL;
}
if(val.equals("void")){
return CClassType.VOID;
return CVoid.TYPE;
}
if (INVALID_HEX.matcher(val).matches()) {
throw new CREFormatException("Hex numbers must only contain digits 0-9, and the letters A-F, but \"" + val + "\" was found.", t);
@@ -498,7 +498,7 @@ public static Construct resolveConstruct(String val, Target t) throws ConfigRunt
// TODO: Once compiler environments are added, we would need to check to see if the value here is a custom
// type. However, as it stands, since we only support the native types, we will just hardcode the check here.
if(NativeTypeList.getNativeTypeList().contains(val)){
return new CClassType(val, t);
return CClassType.get(val);
} else {
return new CString(val, t);
}
@@ -1069,7 +1069,7 @@ public static void QuickAppend(FileWriter f, String message) throws IOException
f.flush();
}
public static boolean hasCHPermission(String functionName, Environment env) {
//The * label completely overrides everything
@@ -1360,7 +1360,7 @@ public static boolean InCmdLine(Environment environment) {
Construct value = args[argNumber];
if (!type.isAssignableFrom(value.getClass())) {
typeof todesired = type.getAnnotation(typeof.class);
String toactual = value.typeof();
CClassType toactual = value.typeof();
if (todesired != null) {
throw new CRECastException("Argument " + (argNumber + 1) + " of " + func.getName() + " was expected to be a "
+ todesired.value() + ", but " + toactual + " \"" + value.val() + "\" was found.", t);
@@ -3,6 +3,7 @@
import com.laytonsmith.core.ParseTree;
import com.laytonsmith.core.compiler.Keyword;
import com.laytonsmith.core.constructs.CClassType;
import com.laytonsmith.core.constructs.CClosure;
import com.laytonsmith.core.constructs.CFunction;
import com.laytonsmith.core.exceptions.ConfigCompileException;
import java.util.List;
@@ -35,7 +36,7 @@ public int process(List<ParseTree> list, int keywordPosition) throws ConfigCompi
return keywordPosition;
} else {
// Else it's standalone, so this should be treated as the closure ClassType
list.set(keywordPosition, new ParseTree(new CClassType("closure", list.get(keywordPosition).getTarget()), list.get(keywordPosition).getFileOptions()));
list.set(keywordPosition, new ParseTree(CClosure.TYPE, list.get(keywordPosition).getFileOptions()));
return keywordPosition;
}
} catch(IndexOutOfBoundsException ex){
@@ -4,11 +4,12 @@
import com.laytonsmith.core.compiler.Keyword;
import com.laytonsmith.core.constructs.CClassType;
import com.laytonsmith.core.constructs.CFunction;
import com.laytonsmith.core.constructs.CIClosure;
import com.laytonsmith.core.exceptions.ConfigCompileException;
import java.util.List;
/**
*
*
*/
@Keyword.keyword("iclosure")
public class IClosureKeyword extends Keyword {
@@ -34,7 +35,7 @@ public int process(List<ParseTree> list, int keywordPosition) throws ConfigCompi
return keywordPosition;
} else {
// Else it's standalone, so this should be treated as the closure ClassType
list.set(keywordPosition, new ParseTree(new CClassType("iclosure", list.get(keywordPosition).getTarget()), list.get(keywordPosition).getFileOptions()));
list.set(keywordPosition, new ParseTree(CIClosure.TYPE, list.get(keywordPosition).getFileOptions()));
return keywordPosition;
}
} catch(IndexOutOfBoundsException ex){
@@ -42,6 +42,7 @@
@typeof("array")
public class CArray extends Construct implements ArrayAccess{
public static final CClassType TYPE = CClassType.get("array");
private boolean associative_mode = false;
private long next_index = 0;
private List<Construct> array;
@@ -234,7 +235,7 @@ public void reverse(Target t){
public final void push(Construct c, Target t){
push(c, null, t);
}
/**
* Pushes a new Construct onto the end of the array. If the index is specified, this works like
* a "insert" operation, in that all values are shifted to the right, starting with the value
@@ -573,26 +574,26 @@ public CArray clone() {
clone.regenValue();
return clone;
}
public CArray deepClone(Target t) {
CArray clone = deepClone(this, t, new ArrayList<CArray[]>());
return clone;
}
private static CArray deepClone(CArray array, Target t, ArrayList<CArray[]> cloneRefs) {
// Return the clone reference if this array has been cloned before (both clones will have the same reference).
for(CArray[] refCouple : cloneRefs) {
if(refCouple[0] == array) {
return refCouple[1];
}
}
// Create the clone to put array in and add it to the cloneRefs list.
CArray clone = new CArray(t, (int) array.size());
clone.associative_mode = array.associative_mode;
cloneRefs.add(new CArray[] {array, clone});
// Iterate over the array, recursively calling this method to perform a deep clone.
for (Construct key : array.keySet()) {
Construct value = array.get(key, t);
@@ -927,4 +928,4 @@ public void clear(){
public void ensureCapacity(int capacity) {
((ArrayList) array).ensureCapacity(capacity);
}
}
}
Oops, something went wrong.

0 comments on commit 15e4836

Please sign in to comment.