Add support for partial classes

This commit is contained in:
Volker Berlin 2020-01-19 15:15:01 +01:00
parent 7894963612
commit 4872dd137a
5 changed files with 89 additions and 9 deletions

View File

@ -19,6 +19,8 @@ package de.inetsoftware.classparser;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
@ -48,9 +50,9 @@ public class ClassFile {
private final ConstantClass[] interfaces;
private final FieldInfo[] fields;
private FieldInfo[] fields;
private final MethodInfo[] methods;
private MethodInfo[] methods;
private final Attributes attributes;
@ -136,16 +138,27 @@ public class ClassFile {
methods = classFile.methods;
attributes = classFile.attributes;
patchConstantPool( classFile.thisClass.getName(), thisClass );
}
/**
* Replace the reference to the Class in the the constant pool.
*
* @param origClassName
* the class name that should be replaced.
* @param thisClass
* the reference of the class that should be used.
*/
private void patchConstantPool( String origClassName, ConstantClass thisClass ) {
// patch constant pool
String origClassName = classFile.thisClass.getName();
for( int i = 0; i < constantPool.size(); i++ ) {
Object obj = constantPool.get( i );
if( obj instanceof ConstantClass ) {
if( ((ConstantClass)obj).getName().equals( origClassName ) ) {
constantPool.set( i, thisClass );
}
} else if( obj instanceof ConstantFieldRef ) {
ConstantFieldRef ref = (ConstantFieldRef)obj;
} else if( obj instanceof ConstantRef ) {
ConstantRef ref = (ConstantRef)obj;
if( ref.getClassName().equals( origClassName ) ) {
ConstantNameAndType nameAndType = new ConstantNameAndType( ref.getName(), ref.getType() );
constantPool.set( i, new ConstantFieldRef( thisClass, nameAndType ) );
@ -301,4 +314,31 @@ public class ClassFile {
public static enum Type {
Class, Interface, Enum;
}
/**
* Extends this class with the methods and fields of the partial class.
*
* @param partialClassFile
* extension of the class
*/
public void partial( ClassFile partialClassFile ) {
ArrayList<MethodInfo> allMethods = new ArrayList<>( Arrays.asList( methods ) );
for( MethodInfo m : partialClassFile.methods ) {
if( getMethod( m.getName(), m.getType() ) == null ) {
m.setDeclaringClassFile( this );
allMethods.add( m );
}
}
methods = allMethods.toArray( methods );
ArrayList<FieldInfo> allFields = new ArrayList<>( Arrays.asList( fields ) );
for( FieldInfo field : partialClassFile.fields ) {
if( getField( field.getName() ) == null ) {
allFields.add( field );
}
}
fields = allFields.toArray( fields );
partialClassFile.patchConstantPool( partialClassFile.thisClass.getName(), thisClass );
}
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2011 - 2019 Volker Berlin (i-net software)
Copyright 2011 - 2020 Volker Berlin (i-net software)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -21,6 +21,7 @@ import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import de.inetsoftware.classparser.Attributes.AttributeInfo;
@ -200,4 +201,14 @@ public class MethodInfo implements Member {
public ConstantPool getConstantPool() {
return constantPool;
}
/**
* Replace the reference to the ClassFile
*
* @param classFile
* the new value
*/
void setDeclaringClassFile( @Nonnull ClassFile classFile ) {
this.classFile = classFile;
}
}

View File

@ -88,6 +88,11 @@ public class JWebAssembly {
*/
public static final String REPLACE_ANNOTATION = "de.inetsoftware.jwebassembly.api.annotation.Replace";
/**
* The name of the annotation for partial class another class of the Java runtime.
*/
public static final String PARTIAL_ANNOTATION = "de.inetsoftware.jwebassembly.api.annotation.Partial";
/**
* If the GC feature of WASM should be use or the GC of the JavaScript host. If true use the GC instructions of WASM.
*/

View File

@ -104,15 +104,31 @@ public class ClassFileLoader {
}
/**
* Replace the class in the cache with the given instance.
* Replace the class in the cache with the given instance to the loader cache.
*
* @param className
* the name of the class to replace
* @param classFile
* the replasing ClassFile
* the replacing ClassFile
*/
public void replace( String className, ClassFile classFile ) {
void replace( String className, ClassFile classFile ) {
classFile = new ClassFile( className, classFile );
replace.put( className, classFile );
}
/**
* Add a partial class with the given instance to the loader cache.
*
* @param className
* the name of the class to replace
* @param partialClassFile
* the partial ClassFile
* @throws IOException
* If any I/O error occur
*/
void partial( String className, ClassFile partialClassFile ) throws IOException {
ClassFile classFile = get( className );
replace.put( className, classFile );
classFile.partial( partialClassFile );
}
}

View File

@ -172,6 +172,14 @@ public class ModuleGenerator {
}
}
// check if this class extends another class with partial code
if( (annotationValues = classFile.getAnnotation( JWebAssembly.PARTIAL_ANNOTATION )) != null ) {
String signatureName = (String)annotationValues.get( "value" );
if( signatureName != null ) {
classFileLoader.partial( signatureName, classFile );
}
}
iterateMethods( classFile, m -> prepareMethod( m ) );
}