continue firefox evaluate

This commit is contained in:
Vladimir Krivosheev
2015-01-26 18:44:53 +01:00
parent 88988e758f
commit 168cb229be
9 changed files with 54 additions and 305 deletions
@@ -98,7 +98,7 @@ final class FieldProcessor<T> {
writeMethodDeclarationJava(out, method);
out.openBlock();
if (effectiveFieldName != null) {
out.append("return ").append(TypeHandler.FIELD_PREFIX).append(effectiveFieldName).semi();
out.append("return ").append(TypeWriter.FIELD_PREFIX).append(effectiveFieldName).semi();
}
out.closeBlock();
}
@@ -12,46 +12,46 @@ import java.util.Map;
public class GlobalScope {
private final State state;
public GlobalScope(Collection<TypeHandler<?>> typeHandlers, Collection<Map<Class<?>, String>> basePackages) {
state = new State(typeHandlers, basePackages);
public GlobalScope(Collection<TypeWriter<?>> typeWriters, Collection<Map<Class<?>, String>> basePackages) {
state = new State(typeWriters, basePackages);
}
public GlobalScope(GlobalScope globalScope) {
state = globalScope.state;
}
public String getTypeImplReference(TypeHandler<?> typeHandler) {
return state.getTypeImplReference(typeHandler);
public String getTypeImplReference(TypeWriter<?> typeWriter) {
return state.getTypeImplReference(typeWriter);
}
public String requireFactoryGenerationAndGetName(TypeHandler<?> typeHandler) {
return state.requireFactoryGenerationAndGetName(typeHandler);
public String requireFactoryGenerationAndGetName(TypeWriter<?> typeWriter) {
return state.requireFactoryGenerationAndGetName(typeWriter);
}
public String getTypeImplShortName(TypeHandler<?> typeHandler) {
return state.getTypeImplShortName(typeHandler);
public String getTypeImplShortName(TypeWriter<?> typeWriter) {
return state.getTypeImplShortName(typeWriter);
}
public FileScope newFileScope(StringBuilder output) {
return new FileScope(this, output);
}
public List<TypeHandler<?>> getTypeFactories() {
public List<TypeWriter<?>> getTypeFactories() {
return state.typesWithFactoriesList;
}
private static class State {
private final Map<TypeHandler<?>, String> typeToName;
private final Map<TypeWriter<?>, String> typeToName;
private final Collection<Map<Class<?>, String>> basePackages;
private final THashSet<TypeHandler<?>> typesWithFactories = new THashSet<>();
private final List<TypeHandler<?>> typesWithFactoriesList = new ArrayList<>();
private final THashSet<TypeWriter<?>> typesWithFactories = new THashSet<>();
private final List<TypeWriter<?>> typesWithFactoriesList = new ArrayList<>();
State(Collection<TypeHandler<?>> typeHandlers, Collection<Map<Class<?>, String>> basePackages) {
State(Collection<TypeWriter<?>> typeWriters, Collection<Map<Class<?>, String>> basePackages) {
this.basePackages = basePackages;
int uniqueCode = 0;
Map<TypeHandler<?>, String> result = new THashMap<>(typeHandlers.size());
for (TypeHandler<?> handler : typeHandlers) {
Map<TypeWriter<?>, String> result = new THashMap<>(typeWriters.size());
for (TypeWriter<?> handler : typeWriters) {
String conflict = result.put(handler, Util.TYPE_NAME_PREFIX + Integer.toString(uniqueCode++));
if (conflict != null) {
throw new RuntimeException();
@@ -60,14 +60,14 @@ public class GlobalScope {
typeToName = result;
}
String getTypeImplReference(TypeHandler<?> typeHandler) {
String localName = typeToName.get(typeHandler);
String getTypeImplReference(TypeWriter<?> typeWriter) {
String localName = typeToName.get(typeWriter);
if (localName != null) {
return localName;
}
for (Map<Class<?>, String> base : basePackages) {
String result = base.get(typeHandler.typeClass);
String result = base.get(typeWriter.typeClass);
if (result != null) {
return result;
}
@@ -76,17 +76,17 @@ public class GlobalScope {
throw new RuntimeException();
}
public String requireFactoryGenerationAndGetName(TypeHandler<?> typeHandler) {
String name = getTypeImplShortName(typeHandler);
if (typesWithFactories.add(typeHandler)) {
typesWithFactoriesList.add(typeHandler);
public String requireFactoryGenerationAndGetName(TypeWriter<?> typeWriter) {
String name = getTypeImplShortName(typeWriter);
if (typesWithFactories.add(typeWriter)) {
typesWithFactoriesList.add(typeWriter);
}
return name;
}
@NotNull
String getTypeImplShortName(TypeHandler<?> typeHandler) {
return typeToName.get(typeHandler);
String getTypeImplShortName(TypeWriter<?> typeWriter) {
return typeToName.get(typeWriter);
}
}
}
@@ -55,7 +55,7 @@ class InterfaceReader {
}
};
private final LinkedHashMap<Class<?>, TypeHandler<?>> typeToTypeHandler;
private final LinkedHashMap<Class<?>, TypeWriter<?>> typeToTypeHandler;
final List<TypeRef<?>> refs = new ArrayList<>();
final List<SubtypeCaster> subtypeCasters = new ArrayList<>();
@@ -67,22 +67,22 @@ class InterfaceReader {
}
}
private InterfaceReader(LinkedHashMap<Class<?>, TypeHandler<?>> typeToTypeHandler) {
private InterfaceReader(LinkedHashMap<Class<?>, TypeWriter<?>> typeToTypeHandler) {
this.typeToTypeHandler = typeToTypeHandler;
}
public static TypeHandler<?> createHandler(LinkedHashMap<Class<?>, TypeHandler<?>> typeToTypeHandler, Class<?> aClass) {
public static TypeWriter<?> createHandler(LinkedHashMap<Class<?>, TypeWriter<?>> typeToTypeHandler, Class<?> aClass) {
InterfaceReader reader = new InterfaceReader(typeToTypeHandler);
reader.processed.addAll(typeToTypeHandler.keySet());
reader.go(new Class[]{aClass});
return typeToTypeHandler.get(aClass);
}
LinkedHashMap<Class<?>, TypeHandler<?>> go() {
LinkedHashMap<Class<?>, TypeWriter<?>> go() {
return go(typeToTypeHandler.keySet().toArray(new Class[typeToTypeHandler.size()]));
}
private LinkedHashMap<Class<?>, TypeHandler<?>> go(Class<?>[] classes) {
private LinkedHashMap<Class<?>, TypeWriter<?>> go(Class<?>[] classes) {
for (Class<?> typeClass : classes) {
createIfNotExists(typeClass);
}
@@ -146,18 +146,18 @@ class InterfaceReader {
}
}
TypeHandler<?> typeHandler = new TypeHandler<>(typeClass, getSuperclassRef(typeClass),
TypeWriter<?> typeWriter = new TypeWriter<>(typeClass, getSuperclassRef(typeClass),
fields.volatileFields, fields.methodHandlerMap,
fields.fieldLoaders,
fields.lazyRead);
for (TypeRef ref : refs) {
if (ref.typeClass == typeClass) {
assert ref.type == null;
ref.type = typeHandler;
ref.type = typeWriter;
break;
}
}
typeToTypeHandler.put(typeClass, typeHandler);
typeToTypeHandler.put(typeClass, typeWriter);
}
ValueReader getFieldTypeParser(Type type, boolean isSubtyping, @Nullable Method method) {
@@ -11,13 +11,13 @@ class ReadDelegate {
private static final List<String> STATIC_METHOD_PARAM_NAME_LIST = Collections.singletonList(Util.READER_NAME);
private static final List<String> STATIC_METHOD_PARAM_NAME_LIST2 = Arrays.asList(Util.READER_NAME, "nextName");
private final TypeHandler<?> typeHandler;
private final TypeWriter<?> typeHandler;
private final boolean isList;
private final List<String> paramNames;
ReadDelegate(@NotNull TypeHandler<?> typeHandler, boolean isList, boolean hasNextNameParam) {
this.typeHandler = typeHandler;
ReadDelegate(@NotNull TypeWriter<?> typeWriter, boolean isList, boolean hasNextNameParam) {
this.typeHandler = typeWriter;
this.isList = isList;
paramNames = hasNextNameParam ? STATIC_METHOD_PARAM_NAME_LIST2 : STATIC_METHOD_PARAM_NAME_LIST;
@@ -23,7 +23,7 @@ public final class ReaderGenerator {
private final String className;
final Collection<Map<Class<?>, String>> basePackagesMap;
final LinkedHashMap<Class<?>, TypeHandler<?>> typeToTypeHandler;
final LinkedHashMap<Class<?>, TypeWriter<?>> typeToTypeHandler;
final ReaderRoot<ROOT> root;
public GenerateConfiguration(String packageName, String className, Class<ROOT> readerRootClass, Class<?>[] protocolInterfaces) {
@@ -107,8 +107,8 @@ public final class ReaderGenerator {
FileScope fileScope = generate(configuration, new StringBuilder());
Map<Class<?>, String> typeToImplClassName = new THashMap<>();
for (TypeHandler<?> typeHandler : configuration.typeToTypeHandler.values()) {
typeToImplClassName.put(typeHandler.typeClass, configuration.packageName + "." + configuration.className + "." + fileScope.getTypeImplShortName(typeHandler));
for (TypeWriter<?> typeWriter : configuration.typeToTypeHandler.values()) {
typeToImplClassName.put(typeWriter.typeClass, configuration.packageName + "." + configuration.className + "." + fileScope.getTypeImplShortName(typeWriter));
}
return typeToImplClassName;
}
@@ -129,14 +129,14 @@ public final class ReaderGenerator {
ClassScope rootClassScope = fileScope.newClassScope();
configuration.root.writeStaticMethodJava(rootClassScope);
for (TypeHandler<?> typeHandler : configuration.typeToTypeHandler.values()) {
for (TypeWriter<?> typeWriter : configuration.typeToTypeHandler.values()) {
out.newLine();
typeHandler.write(rootClassScope);
typeWriter.write(rootClassScope);
out.newLine();
}
boolean isFirst = true;
for (TypeHandler<?> typeHandler : globalScope.getTypeFactories()) {
for (TypeWriter<?> typeWriter : globalScope.getTypeFactories()) {
if (isFirst) {
isFirst = false;
}
@@ -144,13 +144,13 @@ public final class ReaderGenerator {
out.newLine();
}
String originName = typeHandler.typeClass.getCanonicalName();
out.newLine().append("private static final class ").append(globalScope.getTypeImplShortName(typeHandler)).append(Util.TYPE_FACTORY_NAME_POSTFIX).append(" extends ObjectFactory<");
String originName = typeWriter.typeClass.getCanonicalName();
out.newLine().append("private static final class ").append(globalScope.getTypeImplShortName(typeWriter)).append(Util.TYPE_FACTORY_NAME_POSTFIX).append(" extends ObjectFactory<");
out.append(originName).append('>').openBlock();
out.append("@Override").newLine().append("public ").append(originName).append(" read(").append(Util.JSON_READER_PARAMETER_DEF);
out.append(')').openBlock();
out.append("return ");
typeHandler.writeInstantiateCode(rootClassScope, out);
typeWriter.writeInstantiateCode(rootClassScope, out);
out.append('(').append(Util.READER_NAME).append(", null);").closeBlock();
out.closeBlock();
}
@@ -13,11 +13,11 @@ import java.util.*;
class ReaderRoot<R> {
private final Class<R> rootClass;
private final LinkedHashMap<Class<?>, TypeHandler<?>> typeToTypeHandler;
private final LinkedHashMap<Class<?>, TypeWriter<?>> typeToTypeHandler;
private final Set<Class<?>> visitedInterfaces = new THashSet<>(1);
final LinkedHashMap<Method, ReadDelegate> methodMap = new LinkedHashMap<>();
ReaderRoot(Class<R> rootClass, LinkedHashMap<Class<?>, TypeHandler<?>> typeToTypeHandler) {
ReaderRoot(Class<R> rootClass, LinkedHashMap<Class<?>, TypeWriter<?>> typeToTypeHandler) {
this.rootClass = rootClass;
this.typeToTypeHandler = typeToTypeHandler;
readInterfaceRecursive(rootClass);
@@ -60,10 +60,10 @@ class ReaderRoot<R> {
}
//noinspection SuspiciousMethodCalls
TypeHandler<?> typeHandler = typeToTypeHandler.get(returnType);
if (typeHandler == null) {
typeHandler = InterfaceReader.createHandler(typeToTypeHandler, m.getReturnType());
if (typeHandler == null) {
TypeWriter<?> typeWriter = typeToTypeHandler.get(returnType);
if (typeWriter == null) {
typeWriter = InterfaceReader.createHandler(typeToTypeHandler, m.getReturnType());
if (typeWriter == null) {
throw new JsonProtocolModelParseException("Unknown return type in " + m);
}
}
@@ -74,7 +74,7 @@ class ReaderRoot<R> {
}
Type argument = arguments[0];
if (argument == JsonReaderEx.class || argument == Object.class) {
methodMap.put(m, new ReadDelegate(typeHandler, isList, arguments.length != 1));
methodMap.put(m, new ReadDelegate(typeWriter, isList, arguments.length != 1));
}
else {
throw new JsonProtocolModelParseException("Unrecognized argument type in " + m);
@@ -17,7 +17,7 @@ abstract class SubtypeCaster {
abstract void writeJava(TextOutput out);
TypeHandler<?> getSubtypeHandler() {
TypeWriter<?> getSubtypeHandler() {
return subtypeRef.type;
}
}
@@ -1,251 +0,0 @@
package org.jetbrains.protocolReader;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jsonProtocol.JsonObjectBased;
import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
class TypeHandler<T> {
public static final char FIELD_PREFIX = '_';
final Class<T> typeClass;
private final List<VolatileFieldBinding> volatileFields;
private final LinkedHashMap<Method, MethodHandler> methodHandlerMap;
/** Loaders that should read values and save them in field array on parse time. */
private final List<FieldLoader> fieldLoaders;
/** Subtype aspects of the type or null */
final ExistingSubtypeAspect subtypeAspect;
private final boolean hasLazyFields;
TypeHandler(Class<T> typeClass, TypeRef<?> jsonSuperClass,
List<VolatileFieldBinding> volatileFields,
LinkedHashMap<Method, MethodHandler> methodHandlerMap,
List<FieldLoader> fieldLoaders,
boolean hasLazyFields) {
this.typeClass = typeClass;
this.volatileFields = volatileFields;
this.methodHandlerMap = methodHandlerMap;
this.fieldLoaders = fieldLoaders;
this.hasLazyFields = hasLazyFields;
subtypeAspect = jsonSuperClass == null ? null : new ExistingSubtypeAspect(jsonSuperClass);
}
public void writeInstantiateCode(@NotNull ClassScope scope, @NotNull TextOutput out) {
writeInstantiateCode(scope, false, out);
}
public void writeInstantiateCode(@NotNull ClassScope scope, boolean deferredReading, @NotNull TextOutput out) {
String className = scope.getTypeImplReference(this);
if (deferredReading || subtypeAspect == null) {
out.append("new ").append(className);
}
else {
subtypeAspect.writeInstantiateCode(className, out);
}
}
public void write(@NotNull FileScope fileScope) {
TextOutput out = fileScope.getOutput();
String valueImplClassName = fileScope.getTypeImplShortName(this);
out.append("private static final class ").append(valueImplClassName);
out.append(" implements ").append(typeClass.getCanonicalName()).openBlock();
if (hasLazyFields || JsonObjectBased.class.isAssignableFrom(typeClass)) {
out.append("private ").append(Util.JSON_READER_CLASS_NAME).space().append(Util.PENDING_INPUT_READER_NAME).semi().newLine();
}
ClassScope classScope = fileScope.newClassScope();
for (VolatileFieldBinding field : volatileFields) {
field.writeFieldDeclaration(classScope, out);
out.newLine();
}
for (FieldLoader loader : fieldLoaders) {
out.append("private").space();
loader.valueReader.appendFinishedValueTypeName(out);
out.space().append(FIELD_PREFIX).append(loader.name);
if (loader.valueReader instanceof PrimitiveValueReader) {
String defaultValue = ((PrimitiveValueReader)loader.valueReader).defaultValue;
if (defaultValue != null) {
out.append(" = ").append(defaultValue);
}
}
out.semi();
out.newLine();
}
if (subtypeAspect != null) {
subtypeAspect.writeSuperFieldJava(out);
}
writeConstructorMethod(valueImplClassName, classScope, out);
out.newLine();
if (subtypeAspect != null) {
subtypeAspect.writeParseMethod(valueImplClassName, classScope, out);
}
for (Map.Entry<Method, MethodHandler> entry : methodHandlerMap.entrySet()) {
out.newLine();
entry.getValue().writeMethodImplementationJava(classScope, entry.getKey(), out);
out.newLine();
}
writeBaseMethods(out);
if (subtypeAspect != null) {
subtypeAspect.writeGetSuperMethodJava(out);
}
out.indentOut().append('}');
}
/**
* Generates Java implementation of standard methods of JSON type class (if needed):
* {@link org.jetbrains.jsonProtocol.JsonObjectBased#getDeferredReader()}
*/
private void writeBaseMethods(TextOutput out) {
Class<?> typeClass = this.typeClass;
Method method;
try {
method = typeClass.getMethod("getDeferredReader");
}
catch (SecurityException e) {
throw new RuntimeException(e);
}
catch (NoSuchMethodException ignored) {
// Method not found, skip.
return;
}
out.newLine();
MethodHandler.writeMethodDeclarationJava(out, method);
out.openBlock();
out.append("return ").append(Util.PENDING_INPUT_READER_NAME).semi();
out.closeBlock();
}
private void writeConstructorMethod(@NotNull String valueImplClassName, @NotNull ClassScope classScope, @NotNull TextOutput out) {
out.newLine().append(valueImplClassName).append('(').append(Util.JSON_READER_PARAMETER_DEF).comma().append("String name");
if (subtypeAspect != null) {
subtypeAspect.writeSuperConstructorParamJava(out);
}
out.append(')').openBlock();
if (subtypeAspect != null) {
subtypeAspect.writeSuperConstructorInitialization(out);
}
if (JsonObjectBased.class.isAssignableFrom(typeClass) || hasLazyFields) {
out.append(Util.PENDING_INPUT_READER_NAME).append(" = ").append(Util.READER_NAME).append(".subReader()").semi().newLine();
}
if (fieldLoaders.isEmpty()) {
out.append(Util.READER_NAME).append(".skipValue()").semi();
}
else {
out.append("if (name == null)").openBlock();
{
out.append("if (reader.beginObject().hasNext())").openBlock();
{
out.append("name = reader.nextName()").semi();
}
out.closeBlock();
out.newLine().append("else").openBlock();
{
out.append("return").semi();
}
out.closeBlock();
}
out.closeBlock();
out.newLine();
writeReadFields(out, classScope);
// we don't read all data if we have lazy fields, so, we should not check end of stream
//if (!hasLazyFields) {
out.newLine().newLine().append(Util.READER_NAME).append(".endObject()").semi();
//}
}
out.closeBlock();
}
private void writeReadFields(TextOutput out, ClassScope classScope) {
boolean stopIfAllFieldsWereRead = hasLazyFields;
boolean hasOnlyOneFieldLoader = fieldLoaders.size() == 1;
boolean isTracedStop = stopIfAllFieldsWereRead && !hasOnlyOneFieldLoader;
if (isTracedStop) {
out.newLine().append("int i = 0").semi();
}
out.newLine().append("do").openBlock();
boolean isFirst = true;
String operator = "if";
for (FieldLoader fieldLoader : fieldLoaders) {
if (!isFirst) {
out.newLine();
}
out.append(operator).append(" (name");
out.append(".equals(\"").append(fieldLoader.jsonName).append("\"))").openBlock();
{
String primitiveValueName = fieldLoader.valueReader instanceof ObjectValueReader ? ((ObjectValueReader)fieldLoader.valueReader).primitiveValueName : null;
if (primitiveValueName != null) {
out.append("if (reader.peek() == com.google.gson.stream.JsonToken.BEGIN_OBJECT)").openBlock();
}
assignField(out, fieldLoader.name);
fieldLoader.valueReader.writeReadCode(classScope, false, out);
out.semi();
if (primitiveValueName != null) {
out.closeBlock();
out.newLine().append("else").openBlock();
assignField(out, primitiveValueName + "Type");
out.append("reader.peek()").semi().newLine();
assignField(out, primitiveValueName);
out.append("reader.nextString(true)").semi();
out.closeBlock();
}
if (stopIfAllFieldsWereRead && !isTracedStop) {
out.newLine().append(Util.READER_NAME).append(".skipValues()").semi().newLine().append("break").semi();
}
}
out.closeBlock();
if (isFirst) {
isFirst = false;
operator = "else if";
}
}
out.newLine().append("else").openBlock().append("reader.skipValue();");
if (isTracedStop) {
out.newLine().append("continue").semi();
}
out.closeBlock();
if (isTracedStop) {
out.newLine().newLine().append("if (i == ").append(fieldLoaders.size() - 1).append(")").openBlock();
out.append(Util.READER_NAME).append(".skipValues()").semi().newLine().append("break").semi().closeBlock();
out.newLine().append("else").openBlock().append("i++").semi().closeBlock();
}
out.closeBlock();
out.newLine().append("while ((name = reader.nextNameOrNull()) != null)").semi();
}
@NotNull
private static TextOutput assignField(TextOutput out, String fieldName) {
return out.append(FIELD_PREFIX).append(fieldName).append(" = ");
}
}
@@ -2,7 +2,7 @@ package org.jetbrains.protocolReader;
class TypeRef<T> {
final Class<T> typeClass;
TypeHandler<T> type;
TypeWriter<T> type;
TypeRef(Class<T> typeClass) {
this.typeClass = typeClass;