|  | @@ -5,6 +5,7 @@ import org.objectweb.asm.Label;
 | 
		
	
		
			
			| 5 | 5 |  import org.objectweb.asm.Type;
 | 
		
	
		
			
			| 6 | 6 |  import org.openzen.zenscript.codemodel.FunctionParameter;
 | 
		
	
		
			
			| 7 | 7 |  import org.openzen.zenscript.codemodel.HighLevelDefinition;
 | 
		
	
		
			
			|  | 8 | +import org.openzen.zenscript.codemodel.generic.TypeParameter;
 | 
		
	
		
			
			| 8 | 9 |  import org.openzen.zenscript.codemodel.member.*;
 | 
		
	
		
			
			| 9 | 10 |  import org.openzen.zenscript.codemodel.type.StoredType;
 | 
		
	
		
			
			| 10 | 11 |  import org.openzen.zenscript.javabytecode.JavaBytecodeContext;
 | 
		
	
	
		
			
			|  | @@ -15,6 +16,9 @@ import org.openzen.zenscript.javashared.JavaCompiledModule;
 | 
		
	
		
			
			| 15 | 16 |  import org.openzen.zenscript.javashared.JavaField;
 | 
		
	
		
			
			| 16 | 17 |  import org.openzen.zenscript.javashared.JavaMethod;
 | 
		
	
		
			
			| 17 | 18 |  
 | 
		
	
		
			
			|  | 19 | +import java.util.ArrayList;
 | 
		
	
		
			
			|  | 20 | +import java.util.stream.Collectors;
 | 
		
	
		
			
			|  | 21 | +
 | 
		
	
		
			
			| 18 | 22 |  public class JavaExpansionMemberVisitor implements MemberVisitor<Void> {
 | 
		
	
		
			
			| 19 | 23 |  
 | 
		
	
		
			
			| 20 | 24 |  	private final ClassWriter writer;
 | 
		
	
	
		
			
			|  | @@ -79,38 +83,76 @@ public class JavaExpansionMemberVisitor implements MemberVisitor<Void> {
 | 
		
	
		
			
			| 79 | 83 |  		if (!method.compile)
 | 
		
	
		
			
			| 80 | 84 |  			return null;
 | 
		
	
		
			
			| 81 | 85 |  
 | 
		
	
		
			
			|  | 86 | +		final ArrayList<TypeParameter> typeParameters = new ArrayList<>();
 | 
		
	
		
			
			|  | 87 | +		expandedClass.type.extractTypeParameters(typeParameters);
 | 
		
	
		
			
			| 82 | 88 |  
 | 
		
	
		
			
			| 83 |  | -		CompilerUtils.tagMethodParameters(context, javaModule, member.header, member.isStatic());
 | 
		
	
		
			
			|  | 89 | +		CompilerUtils.tagMethodParameters(context, javaModule, member.header, member.isStatic(), typeParameters);
 | 
		
	
		
			
			| 84 | 90 |  
 | 
		
	
		
			
			| 85 | 91 |  		final String expandedClassDescriptor = context.getDescriptor(expandedClass);
 | 
		
	
		
			
			|  | 92 | +		final String expandedClassSignature = context.getSignature(expandedClass);
 | 
		
	
		
			
			| 86 | 93 |  		final Label methodStart = new Label();
 | 
		
	
		
			
			| 87 | 94 |  		final Label methodEnd = new Label();
 | 
		
	
		
			
			| 88 | 95 |  		final String methodSignature;
 | 
		
	
		
			
			|  | 96 | +		final String methodDescriptor;
 | 
		
	
		
			
			|  | 97 | +
 | 
		
	
		
			
			|  | 98 | +
 | 
		
	
		
			
			| 89 | 99 |  
 | 
		
	
		
			
			| 90 | 100 |  		if (!isStatic) {
 | 
		
	
		
			
			| 91 |  | -			methodSignature = "(" + expandedClassDescriptor + context.getMethodSignature(member.header).substring(1);
 | 
		
	
		
			
			|  | 101 | +			String methodSignature1 = context.getMethodSignature(member.header);
 | 
		
	
		
			
			|  | 102 | +
 | 
		
	
		
			
			|  | 103 | +			//Add the expanded type as first generic parameter to the list.
 | 
		
	
		
			
			|  | 104 | +			if(!typeParameters.isEmpty()){
 | 
		
	
		
			
			|  | 105 | +				final String collect = typeParameters.stream()
 | 
		
	
		
			
			|  | 106 | +						.map(t -> t.name + ":" + "Ljava/lang/Object;")
 | 
		
	
		
			
			|  | 107 | +						.collect(Collectors.joining("", "<", ""));
 | 
		
	
		
			
			|  | 108 | +				if(methodSignature1.startsWith("<")) {
 | 
		
	
		
			
			|  | 109 | +					methodSignature1 = collect + methodSignature1.substring(1);
 | 
		
	
		
			
			|  | 110 | +				} else {
 | 
		
	
		
			
			|  | 111 | +					methodSignature1 = collect + ">" + methodSignature1;
 | 
		
	
		
			
			|  | 112 | +				}
 | 
		
	
		
			
			|  | 113 | +			}
 | 
		
	
		
			
			|  | 114 | +
 | 
		
	
		
			
			|  | 115 | +			final StringBuilder typeParamSigBuilder = new StringBuilder();
 | 
		
	
		
			
			|  | 116 | +			final StringBuilder typeParamDescBuilder = new StringBuilder();
 | 
		
	
		
			
			|  | 117 | +			int i = 1;
 | 
		
	
		
			
			|  | 118 | +			for (TypeParameter typeParameter : typeParameters) {
 | 
		
	
		
			
			|  | 119 | +				typeParamSigBuilder.append("Ljava/lang/Class<T").append(typeParameter.name).append(";>;");
 | 
		
	
		
			
			|  | 120 | +				typeParamDescBuilder.append("Ljava/lang/Class;");
 | 
		
	
		
			
			|  | 121 | +			}
 | 
		
	
		
			
			|  | 122 | +
 | 
		
	
		
			
			|  | 123 | +
 | 
		
	
		
			
			|  | 124 | +			final int index = methodSignature1.lastIndexOf('(') + 1;
 | 
		
	
		
			
			|  | 125 | +			methodSignature = methodSignature1.substring(0, index) + expandedClassSignature + typeParamSigBuilder.toString() + methodSignature1.substring(index);
 | 
		
	
		
			
			|  | 126 | +			methodDescriptor = "(" + expandedClassDescriptor + typeParamDescBuilder.toString() + context.getMethodDescriptor(member.header).substring(1);
 | 
		
	
		
			
			| 92 | 127 |  		} else {
 | 
		
	
		
			
			| 93 | 128 |  			methodSignature = context.getMethodSignature(member.header);
 | 
		
	
		
			
			|  | 129 | +			methodDescriptor = context.getMethodDescriptor(member.header);
 | 
		
	
		
			
			| 94 | 130 |  		}
 | 
		
	
		
			
			| 95 | 131 |  
 | 
		
	
		
			
			| 96 | 132 |  
 | 
		
	
		
			
			| 97 |  | -		final JavaWriter methodWriter = new JavaWriter(member.position, writer, true, method, definition, true, methodSignature, methodSignature, null);
 | 
		
	
		
			
			|  | 133 | +		final JavaWriter methodWriter = new JavaWriter(member.position, writer, true, method, definition, true, methodSignature, methodDescriptor, null);
 | 
		
	
		
			
			| 98 | 134 |  		methodWriter.label(methodStart);
 | 
		
	
		
			
			| 99 | 135 |  
 | 
		
	
		
			
			| 100 | 136 |  		if (!isStatic) {
 | 
		
	
		
			
			| 101 | 137 |  			methodWriter.nameVariable(0, "expandedObj", methodStart, methodEnd, Type.getType(expandedClassDescriptor));
 | 
		
	
		
			
			| 102 | 138 |  			methodWriter.nameParameter(0, "expandedObj");
 | 
		
	
		
			
			| 103 |  | -			for (final FunctionParameter parameter : member.header.parameters) {
 | 
		
	
		
			
			| 104 |  | -				methodWriter.nameParameter(0, parameter.name);
 | 
		
	
		
			
			| 105 |  | -				methodWriter.nameVariable(javaModule.getParameterInfo(parameter).index, parameter.name, methodStart, methodEnd, context.getType(parameter.type));
 | 
		
	
		
			
			| 106 |  | -			}
 | 
		
	
		
			
			| 107 |  | -		} else {
 | 
		
	
		
			
			| 108 |  | -			for (final FunctionParameter parameter : member.header.parameters) {
 | 
		
	
		
			
			| 109 |  | -				methodWriter.nameParameter(0, parameter.name);
 | 
		
	
		
			
			| 110 |  | -				methodWriter.nameVariable(javaModule.getParameterInfo(parameter).index, parameter.name, methodStart, methodEnd, context.getType(parameter.type));
 | 
		
	
		
			
			|  | 139 | +
 | 
		
	
		
			
			|  | 140 | +			for (TypeParameter typeParameter : typeParameters) {
 | 
		
	
		
			
			|  | 141 | +				methodWriter.nameParameter(0, "typeOf" + typeParameter.name);
 | 
		
	
		
			
			|  | 142 | +				methodWriter.nameVariable(javaModule.getTypeParameterInfo(typeParameter).parameterIndex, "typeOf" + typeParameter.name, methodStart, methodEnd, Type.getType(Class.class));
 | 
		
	
		
			
			| 111 | 143 |  			}
 | 
		
	
		
			
			| 112 | 144 |  		}
 | 
		
	
		
			
			| 113 | 145 |  
 | 
		
	
		
			
			|  | 146 | +		for (TypeParameter typeParameter : member.header.typeParameters) {
 | 
		
	
		
			
			|  | 147 | +			methodWriter.nameParameter(0, "typeOf" + typeParameter.name);
 | 
		
	
		
			
			|  | 148 | +			methodWriter.nameVariable(javaModule.getTypeParameterInfo(typeParameter).parameterIndex, "typeOf" + typeParameter.name, methodStart, methodEnd, Type.getType(Class.class));
 | 
		
	
		
			
			|  | 149 | +		}
 | 
		
	
		
			
			|  | 150 | +
 | 
		
	
		
			
			|  | 151 | +		for (final FunctionParameter parameter : member.header.parameters) {
 | 
		
	
		
			
			|  | 152 | +			methodWriter.nameParameter(0, parameter.name);
 | 
		
	
		
			
			|  | 153 | +			methodWriter.nameVariable(javaModule.getParameterInfo(parameter).index, parameter.name, methodStart, methodEnd, context.getType(parameter.type));
 | 
		
	
		
			
			|  | 154 | +		}
 | 
		
	
		
			
			|  | 155 | +
 | 
		
	
		
			
			| 114 | 156 |  
 | 
		
	
		
			
			| 115 | 157 |  		{
 | 
		
	
		
			
			| 116 | 158 |  			final JavaStatementVisitor statementVisitor = new JavaStatementVisitor(context, javaModule, methodWriter);
 | 
		
	
	
		
			
			|  | @@ -126,6 +168,69 @@ public class JavaExpansionMemberVisitor implements MemberVisitor<Void> {
 | 
		
	
		
			
			| 126 | 168 |  
 | 
		
	
		
			
			| 127 | 169 |  	@Override
 | 
		
	
		
			
			| 128 | 170 |  	public Void visitGetter(GetterMember member) {
 | 
		
	
		
			
			|  | 171 | +		final boolean isStatic = member.isStatic();
 | 
		
	
		
			
			|  | 172 | +		final StoredType returnType = member.getType();
 | 
		
	
		
			
			|  | 173 | +		final String descriptor;
 | 
		
	
		
			
			|  | 174 | +		final String signature;
 | 
		
	
		
			
			|  | 175 | +
 | 
		
	
		
			
			|  | 176 | +		final ArrayList<TypeParameter> typeParameters = new ArrayList<>();
 | 
		
	
		
			
			|  | 177 | +		expandedClass.type.extractTypeParameters(typeParameters);
 | 
		
	
		
			
			|  | 178 | +
 | 
		
	
		
			
			|  | 179 | +		final String descMiddle, signatureMiddle, signatureStart;
 | 
		
	
		
			
			|  | 180 | +		if(typeParameters.isEmpty()) {
 | 
		
	
		
			
			|  | 181 | +			descMiddle = signatureMiddle = signatureStart = "";
 | 
		
	
		
			
			|  | 182 | +		} else {
 | 
		
	
		
			
			|  | 183 | +			final StringBuilder descMiddleBuilder = new StringBuilder();
 | 
		
	
		
			
			|  | 184 | +			final StringBuilder signatureMiddleBuilder = new StringBuilder();
 | 
		
	
		
			
			|  | 185 | +			final StringBuilder signatureStartBuilder = new StringBuilder("<");
 | 
		
	
		
			
			|  | 186 | +
 | 
		
	
		
			
			|  | 187 | +			for (TypeParameter typeParameter : typeParameters) {
 | 
		
	
		
			
			|  | 188 | +				descMiddleBuilder.append("Ljava/lang/Class;");
 | 
		
	
		
			
			|  | 189 | +				signatureMiddleBuilder.append("Ljava/lang/Class<T").append(typeParameter.name).append(";>;");
 | 
		
	
		
			
			|  | 190 | +				signatureStartBuilder.append(typeParameter.name).append(":Ljava/lang/Object;");
 | 
		
	
		
			
			|  | 191 | +			}
 | 
		
	
		
			
			|  | 192 | +
 | 
		
	
		
			
			|  | 193 | +			descMiddle = descMiddleBuilder.toString();
 | 
		
	
		
			
			|  | 194 | +			signatureMiddle = signatureMiddleBuilder.toString();
 | 
		
	
		
			
			|  | 195 | +			signatureStart = signatureStartBuilder.append(">").toString();
 | 
		
	
		
			
			|  | 196 | +		}
 | 
		
	
		
			
			|  | 197 | +
 | 
		
	
		
			
			|  | 198 | +		if (isStatic) {
 | 
		
	
		
			
			|  | 199 | +			descriptor = "(" + descMiddle + ")" + context.getDescriptor(returnType);
 | 
		
	
		
			
			|  | 200 | +			signature = signatureStart + "(" + signatureMiddle + ")" + context.getSignature(returnType);
 | 
		
	
		
			
			|  | 201 | +		} else {
 | 
		
	
		
			
			|  | 202 | +			descriptor = "(" + context.getDescriptor(expandedClass) + descMiddle + ")" + context.getDescriptor(returnType);
 | 
		
	
		
			
			|  | 203 | +			signature = signatureStart + "(" + context.getSignature(expandedClass) + signatureMiddle + ")" + context.getSignature(returnType);
 | 
		
	
		
			
			|  | 204 | +		}
 | 
		
	
		
			
			|  | 205 | +
 | 
		
	
		
			
			|  | 206 | +		final Label methodStart = new Label();
 | 
		
	
		
			
			|  | 207 | +		final Label methodEnd = new Label();
 | 
		
	
		
			
			|  | 208 | +
 | 
		
	
		
			
			|  | 209 | +		final JavaMethod method = context.getJavaMethod(member);
 | 
		
	
		
			
			|  | 210 | +		final JavaWriter methodWriter = new JavaWriter(member.position, this.writer, true, method, definition, true, signature, descriptor, new String[0]);
 | 
		
	
		
			
			|  | 211 | +
 | 
		
	
		
			
			|  | 212 | +		methodWriter.label(methodStart);
 | 
		
	
		
			
			|  | 213 | +
 | 
		
	
		
			
			|  | 214 | +		if (!isStatic) {
 | 
		
	
		
			
			|  | 215 | +			methodWriter.nameVariable(0, "expandedObj", methodStart, methodEnd, context.getType(this.expandedClass));
 | 
		
	
		
			
			|  | 216 | +			methodWriter.nameParameter(0, "expandedObj");
 | 
		
	
		
			
			|  | 217 | +		}
 | 
		
	
		
			
			|  | 218 | +
 | 
		
	
		
			
			|  | 219 | +		int i = isStatic ? 0 : 1;
 | 
		
	
		
			
			|  | 220 | +		for (TypeParameter typeParameter : typeParameters) {
 | 
		
	
		
			
			|  | 221 | +			final String name = "typeOf" + typeParameter.name;
 | 
		
	
		
			
			|  | 222 | +			methodWriter.nameVariable(i, name, methodStart, methodEnd, Type.getType(Class.class));
 | 
		
	
		
			
			|  | 223 | +			methodWriter.nameParameter(0, name);
 | 
		
	
		
			
			|  | 224 | +		}
 | 
		
	
		
			
			|  | 225 | +
 | 
		
	
		
			
			|  | 226 | +		{
 | 
		
	
		
			
			|  | 227 | +			final JavaStatementVisitor statementVisitor = new JavaStatementVisitor(context, javaModule, methodWriter);
 | 
		
	
		
			
			|  | 228 | +			statementVisitor.start();
 | 
		
	
		
			
			|  | 229 | +			member.body.accept(statementVisitor);
 | 
		
	
		
			
			|  | 230 | +			methodWriter.label(methodEnd);
 | 
		
	
		
			
			|  | 231 | +			statementVisitor.end();
 | 
		
	
		
			
			|  | 232 | +		}
 | 
		
	
		
			
			|  | 233 | +
 | 
		
	
		
			
			| 129 | 234 |  		return null;
 | 
		
	
		
			
			| 130 | 235 |  	}
 | 
		
	
		
			
			| 131 | 236 |  
 |