Imports are tracked when types are used

This commit is contained in:
Andrey Breslav
2013-03-05 20:21:18 +04:00
parent f7de41ea1b
commit ac981915a1
4 changed files with 134 additions and 106 deletions
@@ -16,14 +16,15 @@
package org.jetbrains.jet.di;
import com.google.common.collect.*;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.utils.Printer;
import javax.annotation.PreDestroy;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -39,14 +40,13 @@ public class DependencyInjectorGenerator {
private final Set<Field> fields = Sets.newLinkedHashSet();
private final Set<Parameter> parameters = Sets.newLinkedHashSet();
private final Set<Field> backsParameter = Sets.newHashSet();
private final Set<FactoryMethod> factoryMethods = Sets.newLinkedHashSet();
private final List<Class<?>> implementsList = Lists.newArrayList();
private final Dependencies dependencies = new Dependencies();
private final Set<Field> backsParameter = Sets.newHashSet();
private final List<Class<?>> implementsList = Lists.newArrayList();
private final Collection<Class<?>> imports = Sets.newHashSet();
private final ImportManager importManager = new ImportManager();
public DependencyInjectorGenerator() {
}
@@ -75,6 +75,7 @@ public class DependencyInjectorGenerator {
FileOutputStream fileOutputStream = new FileOutputStream(tmpfile);
System.out.println("File opened: " + tmpfile.getAbsolutePath());
PrintStream out = new PrintStream(fileOutputStream);
try {
fields.addAll(dependencies.satisfyDependencies());
@@ -129,7 +130,7 @@ public class DependencyInjectorGenerator {
if (!superInterface.isInterface()) {
throw new IllegalArgumentException("Only interfaces are supported as supertypes");
}
out.print(superInterface.getSimpleName());
out.print(type(superInterface));
if (iterator.hasNext()) {
out.print(", ");
}
@@ -230,58 +231,25 @@ public class DependencyInjectorGenerator {
for (DiType type : parameterTypes) {
parameters.add(new Parameter(type, var(type), null, false));
}
factoryMethods.add(new FactoryMethod("create" + returnType.getSimpleName(), returnType, parameters));
factoryMethods.add(new FactoryMethod("create" + type(returnType), returnType, parameters));
}
private void generateImports(PrintStream out, String injectorPackageName) {
for (Field field : fields) {
generateImportDirectives(out, field.getType(), injectorPackageName);
DiType implType = field.getInitialization().getType();
if (implType != null) {
generateImportDirectives(out, implType, injectorPackageName);
}
for (DiType typeToImport : field.getInitialization().getTypesToImport()) {
generateImportDirective(out, typeToImport.getClazz(), injectorPackageName);
for (Class<?> importedClass : importManager.getImportedClasses()) {
if (importedClass.isPrimitive()) continue;
String importedPackageName = importedClass.getPackage().getName();
if ("java.lang".equals(importedPackageName)
|| injectorPackageName.equals(importedPackageName)) {
continue;
}
out.println("import " + importedClass.getCanonicalName() + ";");
}
for (Class<?> superInterface : implementsList) {
generateImportDirective(out, superInterface, injectorPackageName);
}
for (Parameter parameter : parameters) {
generateImportDirectives(out, parameter.getType(), injectorPackageName);
}
for (Parameter parameter : parameters) {
if (parameter.isRequired()) {
generateImportDirective(out, NotNull.class, injectorPackageName);
break;
}
}
generateImportDirective(out, PreDestroy.class, injectorPackageName);
}
private void generateImportDirectives(PrintStream out, DiType type, String injectorPackageName) {
generateImportDirective(out, type.getClazz(), injectorPackageName);
for (DiType typeParameter : type.getTypeParameters()) {
generateImportDirectives(out, typeParameter, injectorPackageName);
}
}
private void generateImportDirective(PrintStream out, Class<?> type, String injectorPackageName) {
if (type.isPrimitive()) return;
String importedPackageName = type.getPackage().getName();
if ("java.lang".equals(importedPackageName)
|| injectorPackageName.equals(importedPackageName)
|| !imports.add(type)) {
return;
}
out.println("import " + type.getCanonicalName() + ";");
}
private void generateFields(PrintStream out) {
for (Field field : fields) {
String _final = backsParameter.contains(field) ? "final " : "";
out.println(" private " + _final + InjectorGeneratorUtil.getEffectiveFieldType(field).getSimpleName() + " " + field.getName() + ";");
out.println(" private " + _final + type(InjectorGeneratorUtil.getEffectiveFieldType(field)) + " " + field.getName() + ";");
}
}
@@ -302,7 +270,7 @@ public class DependencyInjectorGenerator {
if (parameter.isRequired()) {
p.printWithNoIndent("@NotNull ");
}
p.printWithNoIndent(parameter.getType().getSimpleName(), " ", parameter.getName());
p.printWithNoIndent(type(parameter.getType()), " ", parameter.getName());
if (iterator.hasNext()) {
p.printlnWithNoIndent(",");
}
@@ -314,7 +282,7 @@ public class DependencyInjectorGenerator {
p.pushIndent();
InjectionLogicGenerator.FIELDS.generate(p, fields);
InjectionLogicGenerator.generateForFields(p, fields);
p.popIndent();
p.println("}");
@@ -343,7 +311,7 @@ public class DependencyInjectorGenerator {
for (Field field : fields) {
if (!field.isPublic()) continue;
String visibility = field.isPublic() ? "public" : "private";
out.println(indent0 + visibility + " " + field.getTypeName() + " " + field.getGetterName() + "() {");
out.println(indent0 + visibility + " " + type(field.getType()) + " " + field.getGetterName() + "() {");
out.println(indent1 + "return this." + field.getName() + ";");
out.println(indent0 + "}");
@@ -393,7 +361,7 @@ public class DependencyInjectorGenerator {
p.println(") {");
p.pushIndent();
InjectionLogicGenerator.LOCAL_VARIABLES.generate(p, fields);
InjectionLogicGenerator.generateForLocalVariables(importManager, p, fields);
p.println("return ", resultField.getName(), ";");
@@ -401,7 +369,11 @@ public class DependencyInjectorGenerator {
p.println("}");
}
private String type(DiType type) {
return type.getSimpleName();
private CharSequence type(DiType type) {
return importManager.render(type);
}
private CharSequence type(Class<?> type) {
return type(DiType.fromReflectionType(type));
}
}
@@ -21,9 +21,7 @@ import org.jetbrains.annotations.NotNull;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
public class DiType {
@@ -64,25 +62,6 @@ public class DiType {
return this.typeParameters.equals(that.typeParameters);
}
@NotNull
public String getSimpleName() {
StringBuilder sb = new StringBuilder();
sb.append(clazz.getSimpleName());
Iterator<DiType> typeParameterIterator = typeParameters.iterator();
if (typeParameterIterator.hasNext()) {
sb.append("<");
if (typeParameterIterator.hasNext()) {
sb.append(typeParameterIterator.next().getSimpleName());
}
while (typeParameterIterator.hasNext()) {
sb.append(", ");
sb.append(typeParameterIterator.next().getSimpleName());
}
sb.append(">");
}
return sb.toString();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -0,0 +1,69 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.di;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.utils.Printer;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
public class ImportManager {
private final Map<String, Class<?>> classes = Maps.newLinkedHashMap();
public boolean addClass(@NotNull Class<?> classToImport) {
String simpleName = classToImport.getSimpleName();
Class<?> imported = classes.get(simpleName);
if (imported != null) return classToImport.equals(imported);
classes.put(simpleName, classToImport);
return true;
}
@NotNull
public Collection<Class<?>> getImportedClasses() {
return classes.values();
}
@NotNull
public CharSequence render(@NotNull DiType type) {
StringBuilder out = new StringBuilder();
Printer p = new Printer(out);
if (addClass(type.getClazz())) {
p.print(type.getClazz().getSimpleName());
}
else {
p.print(type.getClazz().getCanonicalName());
}
if (!type.getTypeParameters().isEmpty()) {
p.print("<");
for (Iterator<DiType> iterator = type.getTypeParameters().iterator(); iterator.hasNext(); ) {
p.print(render(iterator.next()));
if (iterator.hasNext()) {
p.print(", ");
}
}
p.print(">");
}
return out;
}
}
@@ -23,43 +23,51 @@ import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
abstract class InjectionLogicGenerator {
public abstract class InjectionLogicGenerator {
public static final InjectionLogicGenerator FIELDS = new InjectionLogicGenerator() {
@Override
public String prefixForPostConstructorCall(Field field) {
return "";
}
public static void generateForFields(@NotNull Printer p, @NotNull Collection<Field> fields) {
new InjectionLogicGenerator() {
@Override
public String prefixForPostConstructorCall(Field field) {
return "";
}
@Override
public String prefixForSetterCall(Field field) {
return field.isPublic() ? "this." : "";
}
@Override
public String prefixForSetterCall(Field field) {
return field.isPublic() ? "this." : "";
}
@Override
public String prefixForInitialization(Field field) {
return "this.";
}
};
@Override
public String prefixForInitialization(Field field) {
return "this.";
}
}.generate(p, fields);
}
public static final InjectionLogicGenerator LOCAL_VARIABLES = new InjectionLogicGenerator() {
@Override
public String prefixForPostConstructorCall(Field field) {
return "";
}
public static void generateForLocalVariables(
@NotNull final ImportManager importManager,
@NotNull Printer p,
@NotNull Collection<Field> fields
) {
new InjectionLogicGenerator() {
@Override
public String prefixForPostConstructorCall(Field field) {
return "";
}
@Override
public String prefixForSetterCall(Field field) {
return "";
}
@Override
public String prefixForSetterCall(Field field) {
return "";
}
@Override
public String prefixForInitialization(Field field) {
return field.getType() + " ";
}
};
@Override
public String prefixForInitialization(Field field) {
return importManager.render(field.getType()) + " ";
}
}.generate(p, fields);
}
public final void generate(@NotNull Printer p, @NotNull Collection<Field> fields) {
protected void generate(@NotNull Printer p, @NotNull Collection<Field> fields) {
// Initialize fields
for (Field field : fields) {
//if (!backsParameter.contains(field) || field.isPublic()) {