Move injector-generator under generators
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.
|
||||
*/
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="frontend" />
|
||||
<orderEntry type="library" name="intellij-core" level="project" />
|
||||
<orderEntry type="library" name="javax.inject" level="project" />
|
||||
<orderEntry type="module" module-name="backend" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.Lists;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class ConstructorCall implements Expression {
|
||||
private final Constructor<?> constructor;
|
||||
private final List<Field> constructorArguments = Lists.newArrayList();
|
||||
|
||||
ConstructorCall(Constructor<?> constructor) {
|
||||
this.constructor = constructor;
|
||||
}
|
||||
|
||||
public List<Field> getConstructorArguments() {
|
||||
return constructorArguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return constructor.toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String renderAsCode() {
|
||||
StringBuilder builder = new StringBuilder("new " + constructor.getDeclaringClass().getSimpleName() + "(");
|
||||
for (Iterator<Field> iterator = constructorArguments.iterator(); iterator.hasNext(); ) {
|
||||
Field argument = iterator.next();
|
||||
if (argument.isPublic()) {
|
||||
builder.append(argument.getGetterName()).append("()");
|
||||
}
|
||||
else {
|
||||
builder.append(argument.getName());
|
||||
}
|
||||
if (iterator.hasNext()) {
|
||||
builder.append(", ");
|
||||
}
|
||||
}
|
||||
builder.append(")");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<DiType> getTypesToImport() {
|
||||
return Collections.singletonList(new DiType(constructor.getDeclaringClass()));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DiType getType() {
|
||||
return new DiType(constructor.getDeclaringClass());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* 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.HashMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.di.InjectorGeneratorUtil.var;
|
||||
|
||||
public class Dependencies {
|
||||
|
||||
private final Set<Field> allFields = Sets.newLinkedHashSet();
|
||||
private final Set<Field> satisfied = Sets.newHashSet();
|
||||
private final Set<Field> used = Sets.newHashSet();
|
||||
private final Multimap<DiType, Field> typeToFields = HashMultimap.create();
|
||||
|
||||
private final Set<Field> newFields = Sets.newLinkedHashSet();
|
||||
|
||||
public void addField(@NotNull Field field) {
|
||||
allFields.add(field);
|
||||
typeToFields.put(field.getType(), field);
|
||||
}
|
||||
|
||||
public void addSatisfiedField(@NotNull Field field) {
|
||||
addField(field);
|
||||
satisfied.add(field);
|
||||
}
|
||||
|
||||
private Field addNewField(@NotNull DiType type) {
|
||||
Field field = Field.create(false, type, var(type), null);
|
||||
addField(field);
|
||||
newFields.add(field);
|
||||
return field;
|
||||
}
|
||||
|
||||
private void satisfyDependenciesFor(Field field, ImmutableStack<Field> neededFor) {
|
||||
if (!satisfied.add(field)) return;
|
||||
|
||||
Expression initialization = field.getInitialization();
|
||||
if (initialization instanceof InstantiateType) {
|
||||
initializeByConstructorCall(field, neededFor);
|
||||
}
|
||||
DiType typeToInitialize = InjectorGeneratorUtil.getEffectiveFieldType(field);
|
||||
|
||||
// Sort setters in order to get deterministic behavior
|
||||
List<Method> declaredMethods = Lists.newArrayList(typeToInitialize.getClazz().getDeclaredMethods());
|
||||
Collections.sort(declaredMethods, new Comparator<Method>() {
|
||||
@Override
|
||||
public int compare(Method o1, Method o2) {
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
}
|
||||
});
|
||||
for (Method method : declaredMethods) {
|
||||
if (method.getAnnotation(javax.inject.Inject.class) == null
|
||||
|| !method.getName().startsWith("set")
|
||||
|| method.getParameterTypes().length != 1) continue;
|
||||
|
||||
Type parameterType = method.getGenericParameterTypes()[0];
|
||||
|
||||
|
||||
Field dependency = findDependencyOfType(
|
||||
DiType.fromReflectionType(parameterType),
|
||||
field + ": " + method + ": " + allFields,
|
||||
neededFor.prepend(field)
|
||||
);
|
||||
used.add(dependency);
|
||||
|
||||
field.getDependencies().add(new SetterDependency(field, method.getName(), dependency));
|
||||
}
|
||||
}
|
||||
|
||||
private Field findDependencyOfType(DiType parameterType, String errorMessage, ImmutableStack<Field> neededFor) {
|
||||
List<Field> fields = Lists.newArrayList();
|
||||
for (Map.Entry<DiType, Field> entry : typeToFields.entries()) {
|
||||
if (parameterType.isAssignableFrom(entry.getKey())) {
|
||||
fields.add(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
if (fields.isEmpty()) {
|
||||
|
||||
if (parameterType.getClazz().isPrimitive() || parameterType.getClazz().getPackage().getName().equals("java.lang")) {
|
||||
throw new IllegalArgumentException(
|
||||
"cannot declare magic field of type " + parameterType + ": " + errorMessage);
|
||||
}
|
||||
|
||||
Field dependency = addNewField(parameterType);
|
||||
satisfyDependenciesFor(dependency, neededFor);
|
||||
return dependency;
|
||||
}
|
||||
else if (fields.size() == 1) {
|
||||
return fields.iterator().next();
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Ambiguous dependency: \n"
|
||||
+ errorMessage
|
||||
+ "\nneeded for " + neededFor
|
||||
+ "\navailable: " + fields);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeByConstructorCall(Field field, ImmutableStack<Field> neededFor) {
|
||||
//noinspection RedundantCast
|
||||
DiType type = ((InstantiateType) field.getInitialization()).getType();
|
||||
|
||||
Class<?> clazz = type.getClazz();
|
||||
if (clazz.isInterface()) {
|
||||
if (initializeAsSingleton(field, type)) return;
|
||||
throw new IllegalArgumentException("cannot instantiate interface: " + clazz.getName() + " needed for " + neededFor);
|
||||
}
|
||||
if (Modifier.isAbstract(clazz.getModifiers())) {
|
||||
if (initializeAsSingleton(field, type)) return;
|
||||
throw new IllegalArgumentException("cannot instantiate abstract class: " + clazz.getName() + " needed for " + neededFor);
|
||||
}
|
||||
|
||||
// Note: projections are not computed here
|
||||
|
||||
// Look for constructor
|
||||
List<Constructor<?>> publicConstructors = findPublicConstructors(clazz.getConstructors());
|
||||
if (publicConstructors.size() != 1) {
|
||||
if (initializeAsSingleton(field, type)) return;
|
||||
if (publicConstructors.size() == 0) {
|
||||
throw new IllegalArgumentException("No public constructor: " + clazz.getName() + " needed for " + neededFor);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Too many public constructors in " + clazz.getName() + " needed for " + neededFor);
|
||||
}
|
||||
}
|
||||
|
||||
Constructor<?> publicConstructor = publicConstructors.get(0);
|
||||
|
||||
// Find arguments
|
||||
ConstructorCall dependency = new ConstructorCall(publicConstructor);
|
||||
Type[] parameterTypes = publicConstructor.getGenericParameterTypes();
|
||||
for (Type parameterType : parameterTypes) {
|
||||
Field fieldForParameter = findDependencyOfType(
|
||||
DiType.fromReflectionType(parameterType),
|
||||
"constructor: " + publicConstructor + ", parameter: " + parameterType,
|
||||
neededFor.prepend(field)
|
||||
);
|
||||
used.add(fieldForParameter);
|
||||
dependency.getConstructorArguments().add(fieldForParameter);
|
||||
}
|
||||
|
||||
field.setInitialization(dependency);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<Constructor<?>> findPublicConstructors(Constructor<?>[] constructors) {
|
||||
List<Constructor<?>> result = new ArrayList<Constructor<?>>();
|
||||
for (Constructor<?> constructor : constructors) {
|
||||
if (Modifier.isPublic(constructor.getModifiers())) {
|
||||
result.add(constructor);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static boolean initializeAsSingleton(Field field, DiType type) {
|
||||
Class<?> clazz = type.getClazz();
|
||||
|
||||
return initializeBySingletonMethod(field, clazz, "getInstance")
|
||||
|| initializeBySingletonField(field, clazz, "INSTANCE")
|
||||
|| initializeBySingletonField(field, clazz, "INSTANCE$");
|
||||
}
|
||||
|
||||
private static boolean initializeBySingletonMethod(Field field, Class<?> clazz, String name) {
|
||||
try {
|
||||
clazz.getMethod(name);
|
||||
field.setInitialization(GetSingleton.byMethod(clazz, name));
|
||||
return true;
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
// Ignored
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean initializeBySingletonField(Field field, Class<?> clazz, String name) {
|
||||
try {
|
||||
clazz.getField(name);
|
||||
field.setInitialization(GetSingleton.byField(clazz, name));
|
||||
return true;
|
||||
}
|
||||
catch (NoSuchFieldException e) {
|
||||
// Ignored
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public Collection<Field> satisfyDependencies() {
|
||||
for (Field field : Lists.newArrayList(allFields)) {
|
||||
satisfyDependenciesFor(field, LinkedImmutableStack.<Field>empty());
|
||||
}
|
||||
return newFields;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<Field> getUsedFields() {
|
||||
return used;
|
||||
}
|
||||
|
||||
private interface ImmutableStack<T> {
|
||||
@NotNull
|
||||
ImmutableStack<T> prepend(T t);
|
||||
}
|
||||
|
||||
private static class LinkedImmutableStack<T> implements ImmutableStack<T> {
|
||||
|
||||
private static final ImmutableStack EMPTY = new ImmutableStack() {
|
||||
@NotNull
|
||||
@Override
|
||||
public ImmutableStack prepend(Object o) {
|
||||
return create(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "<itself>";
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
public static <T> ImmutableStack<T> empty() {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static <T> LinkedImmutableStack<T> create(@NotNull T t) {
|
||||
return new LinkedImmutableStack<T>(t, LinkedImmutableStack.<T>empty());
|
||||
}
|
||||
|
||||
private final T head;
|
||||
private final ImmutableStack<T> tail;
|
||||
|
||||
private LinkedImmutableStack(@NotNull T head, @NotNull ImmutableStack<T> tail) {
|
||||
this.head = head;
|
||||
this.tail = tail;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public LinkedImmutableStack<T> prepend(@NotNull T t) {
|
||||
return new LinkedImmutableStack<T>(t, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return doToString(this, new StringBuilder()).toString();
|
||||
}
|
||||
|
||||
private static <T> CharSequence doToString(@NotNull ImmutableStack<T> stack, StringBuilder builder) {
|
||||
if (stack == empty()) {
|
||||
builder.append("|");
|
||||
return builder;
|
||||
}
|
||||
|
||||
LinkedImmutableStack<T> list = (LinkedImmutableStack<T>) stack;
|
||||
builder.append("\n\t").append(list.head).append(" -> ");
|
||||
return doToString(list.tail, builder);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+361
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
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.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.jet.di.InjectorGeneratorUtil.var;
|
||||
|
||||
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 ImportManager importManager = new ImportManager();
|
||||
|
||||
private String targetSourceRoot;
|
||||
private String injectorPackageName;
|
||||
private String injectorClassName;
|
||||
private String generatedBy;
|
||||
|
||||
public DependencyInjectorGenerator() {
|
||||
}
|
||||
|
||||
public String getInjectorClassName() {
|
||||
return injectorClassName;
|
||||
}
|
||||
|
||||
public DependencyInjectorGenerator configure(String targetSourceRoot, String injectorPackageName, String injectorClassName, String generatedBy) {
|
||||
this.targetSourceRoot = targetSourceRoot;
|
||||
this.injectorPackageName = injectorPackageName;
|
||||
this.injectorClassName = injectorClassName;
|
||||
this.generatedBy = generatedBy;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void generate() throws IOException {
|
||||
assert targetSourceRoot != null : "Don't forget to call configure()";
|
||||
|
||||
GeneratorsFileUtil.writeFileIfContentChanged(getOutputFile(), generateText().toString());
|
||||
}
|
||||
|
||||
public File getOutputFile() {
|
||||
String outputFileName = targetSourceRoot + "/" + injectorPackageName.replace(".", "/") + "/" + injectorClassName + ".java";
|
||||
return new File(outputFileName);
|
||||
}
|
||||
|
||||
public CharSequence generateText() throws IOException {
|
||||
assert generatedBy != null : "Don't forget to call configure()";
|
||||
|
||||
fields.addAll(dependencies.satisfyDependencies());
|
||||
reportUnusedParameters(injectorPackageName, injectorClassName);
|
||||
|
||||
StringBuilder preamble = new StringBuilder();
|
||||
generatePreamble(injectorPackageName, new Printer(preamble));
|
||||
|
||||
StringBuilder body = new StringBuilder();
|
||||
Printer p = new Printer(body);
|
||||
|
||||
p.println();
|
||||
|
||||
p.println("/* This file is generated by " + generatedBy + ". DO NOT EDIT! */");
|
||||
p.println("@SuppressWarnings(\"all\")");
|
||||
p.print("public class " + injectorClassName);
|
||||
generateImplementsList(p);
|
||||
p.println(" {");
|
||||
p.pushIndent();
|
||||
p.println();
|
||||
generateFields(p);
|
||||
p.println();
|
||||
generateConstructor(injectorClassName, p);
|
||||
p.println();
|
||||
generateDestroy(injectorClassName, p);
|
||||
p.println();
|
||||
generateGetters(p);
|
||||
generateFactoryMethods(p);
|
||||
p.popIndent();
|
||||
p.println("}"); // class
|
||||
|
||||
importManager.addClass(NotNull.class);
|
||||
importManager.addClass(PreDestroy.class);
|
||||
StringBuilder imports = new StringBuilder();
|
||||
generateImports(new Printer(imports), injectorPackageName);
|
||||
|
||||
StringBuilder text = new StringBuilder(preamble);
|
||||
text.append(imports);
|
||||
text.append(body);
|
||||
return text;
|
||||
}
|
||||
|
||||
private void reportUnusedParameters(String injectorPackageName, String injectorClassName) {
|
||||
Sets.SetView<Field> unusedParameters = Sets.difference(backsParameter, dependencies.getUsedFields());
|
||||
for (Field parameter : unusedParameters) {
|
||||
if (!parameter.isPublic()) {
|
||||
System.err.println("Unused parameter: " + parameter + " for " + injectorPackageName + "." + injectorClassName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void generatePreamble(String injectorPackageName, Printer p) throws IOException {
|
||||
String copyright = "generators/injector-generator/copyright.txt";
|
||||
p.println(FileUtil.loadFile(new File(copyright)));
|
||||
|
||||
p.println("package " + injectorPackageName + ";");
|
||||
p.println();
|
||||
}
|
||||
|
||||
private void generateImplementsList(Printer out) {
|
||||
if (!implementsList.isEmpty()) {
|
||||
out.print(" implements ");
|
||||
for (Iterator<Class<?>> iterator = implementsList.iterator(); iterator.hasNext(); ) {
|
||||
Class<?> superInterface = iterator.next();
|
||||
if (!superInterface.isInterface()) {
|
||||
throw new IllegalArgumentException("Only interfaces are supported as supertypes");
|
||||
}
|
||||
out.print(type(superInterface));
|
||||
if (iterator.hasNext()) {
|
||||
out.print(", ");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void implementInterface(Class<?> superInterface) {
|
||||
implementsList.add(superInterface);
|
||||
}
|
||||
|
||||
public void addParameter(boolean reexport, @NotNull DiType type, @Nullable String name, boolean required, boolean useAsContext) {
|
||||
Field field = addField(reexport, type, name, null, useAsContext);
|
||||
Parameter parameter = new Parameter(type, name, field, required);
|
||||
parameters.add(parameter);
|
||||
field.setInitialization(new ParameterExpression(parameter));
|
||||
backsParameter.add(field);
|
||||
dependencies.addSatisfiedField(field);
|
||||
}
|
||||
|
||||
public Field addField(boolean isPublic, DiType type, @Nullable String name, @Nullable Expression init, boolean useAsContext) {
|
||||
Field field = Field.create(isPublic, type, name == null ? var(type) : name, init);
|
||||
addField(field);
|
||||
if (useAsContext) {
|
||||
for (Field accessibleViaGetter : field.getFieldsAccessibleViaGetters()) {
|
||||
addField(accessibleViaGetter);
|
||||
}
|
||||
}
|
||||
return field;
|
||||
}
|
||||
|
||||
private void addField(@NotNull Field field) {
|
||||
fields.add(field);
|
||||
dependencies.addField(field);
|
||||
}
|
||||
|
||||
public void addFactoryMethod(@NotNull Class<?> returnType, Class<?>... parameterTypes) {
|
||||
List<DiType> types = Lists.newArrayList();
|
||||
for (Class<?> type : parameterTypes) {
|
||||
types.add(new DiType(type));
|
||||
}
|
||||
addFactoryMethod(new DiType(returnType), types);
|
||||
}
|
||||
|
||||
public void addFactoryMethod(@NotNull DiType returnType, DiType... parameterTypes) {
|
||||
addFactoryMethod(returnType, Arrays.asList(parameterTypes));
|
||||
}
|
||||
|
||||
public void addFactoryMethod(@NotNull DiType returnType, @NotNull Collection<DiType> parameterTypes) {
|
||||
List<Parameter> parameters = Lists.newArrayList();
|
||||
for (DiType type : parameterTypes) {
|
||||
parameters.add(new Parameter(type, var(type), null, false));
|
||||
}
|
||||
factoryMethods.add(new FactoryMethod("create" + type(returnType), returnType, parameters));
|
||||
}
|
||||
|
||||
private void generateImports(Printer out, String 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() + ";");
|
||||
}
|
||||
}
|
||||
|
||||
private void generateFields(Printer out) {
|
||||
for (Field field : getUsedFields()) {
|
||||
out.println("private final " + type(InjectorGeneratorUtil.getEffectiveFieldType(field)) + " " + field.getName() + ";");
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<Field> getUsedFields() {
|
||||
return ContainerUtil.filter(fields, new Condition<Field>() {
|
||||
@Override
|
||||
public boolean value(Field field) {
|
||||
return dependencies.getUsedFields().contains(field) || field.isPublic();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void generateConstructor(String injectorClassName, Printer p) {
|
||||
// Constructor parameters
|
||||
if (parameters.isEmpty()) {
|
||||
p.println("public ", injectorClassName, "() {");
|
||||
}
|
||||
else {
|
||||
p.print("public ", injectorClassName);
|
||||
generateParameterList(p, parameters);
|
||||
}
|
||||
|
||||
p.pushIndent();
|
||||
|
||||
InjectionLogicGenerator.generateForFields(p, getUsedFields());
|
||||
|
||||
p.popIndent();
|
||||
p.println("}");
|
||||
}
|
||||
|
||||
private void generateParameterList(Printer p, Collection<Parameter> parameters) {
|
||||
p.printlnWithNoIndent("(");
|
||||
p.pushIndent();
|
||||
for (Iterator<Parameter> iterator = parameters.iterator(); iterator.hasNext(); ) {
|
||||
Parameter parameter = iterator.next();
|
||||
p.printIndent();
|
||||
if (parameter.isRequired()) {
|
||||
p.printWithNoIndent("@NotNull ");
|
||||
}
|
||||
p.printWithNoIndent(type(parameter.getType()), " ", parameter.getName());
|
||||
if (iterator.hasNext()) {
|
||||
p.printlnWithNoIndent(",");
|
||||
}
|
||||
}
|
||||
p.printlnWithNoIndent();
|
||||
p.popIndent();
|
||||
p.println(") {");
|
||||
}
|
||||
|
||||
private void generateDestroy(@NotNull String injectorClassName, @NotNull Printer out) {
|
||||
out.println("@PreDestroy");
|
||||
out.println("public void destroy() {");
|
||||
out.pushIndent();
|
||||
for (Field field : fields) {
|
||||
// TODO: type of field may be different from type of object
|
||||
List<Method> preDestroyMethods = InjectorGeneratorUtil
|
||||
.getPreDestroyMethods(InjectorGeneratorUtil.getEffectiveFieldType(field).getClazz());
|
||||
for (Method preDestroy : preDestroyMethods) {
|
||||
out.println(field.getName() + "." + preDestroy.getName() + "();");
|
||||
}
|
||||
if (preDestroyMethods.size() > 0) {
|
||||
out.println();
|
||||
}
|
||||
}
|
||||
out.popIndent();
|
||||
out.println("}");
|
||||
}
|
||||
|
||||
private void generateGetters(Printer out) {
|
||||
for (Field field : fields) {
|
||||
if (!field.isPublic()) continue;
|
||||
String visibility = "public";
|
||||
out.println(visibility + " " + type(field.getType()) + " " + field.getGetterName() + "() {");
|
||||
out.pushIndent();
|
||||
|
||||
out.println("return this." + field.getName() + ";");
|
||||
|
||||
out.popIndent();
|
||||
out.println("}");
|
||||
out.println();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void generateFactoryMethods(Printer p) {
|
||||
if (factoryMethods.isEmpty()) return;
|
||||
p.println();
|
||||
|
||||
p.pushIndent();
|
||||
for (FactoryMethod method : factoryMethods) {
|
||||
generateFactoryMethod(p, method);
|
||||
}
|
||||
p.popIndent();
|
||||
}
|
||||
|
||||
private Collection<Field> computeFieldsForFactoryMethod(FactoryMethod method, Field resultField) {
|
||||
Dependencies localDependencies = new Dependencies();
|
||||
|
||||
Map<Parameter, Field> parameterToField = Maps.newHashMap();
|
||||
for (Parameter parameter : method.getParameters()) {
|
||||
Field field = new Field(true, parameter.getType(), parameter.getName());
|
||||
localDependencies.addSatisfiedField(field);
|
||||
parameterToField.put(parameter, field);
|
||||
}
|
||||
|
||||
for (Field storedField : fields) {
|
||||
localDependencies.addSatisfiedField(storedField);
|
||||
}
|
||||
|
||||
localDependencies.addField(resultField);
|
||||
|
||||
Collection<Field> fields = Lists.newArrayList(localDependencies.satisfyDependencies());
|
||||
fields.add(resultField);
|
||||
return fields;
|
||||
}
|
||||
|
||||
private void generateFactoryMethod(Printer p, FactoryMethod method) {
|
||||
Field resultField = new Field(true, method.getReturnType(), "_result");
|
||||
Collection<Field> fields = computeFieldsForFactoryMethod(method, resultField);
|
||||
|
||||
p.print("public ", type(method.getReturnType()), " ", method.getName());
|
||||
generateParameterList(p, method.getParameters());
|
||||
|
||||
p.pushIndent();
|
||||
|
||||
InjectionLogicGenerator.generateForLocalVariables(importManager, p, fields);
|
||||
|
||||
p.println("return ", resultField.getName(), ";");
|
||||
|
||||
p.popIndent();
|
||||
p.println("}");
|
||||
}
|
||||
|
||||
private CharSequence type(DiType type) {
|
||||
return importManager.render(type);
|
||||
}
|
||||
|
||||
private CharSequence type(Class<?> type) {
|
||||
return type(DiType.fromReflectionType(type));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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.Lists;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class DiType {
|
||||
@NotNull
|
||||
private final Class<?> clazz;
|
||||
@NotNull
|
||||
private final List<DiType> typeParameters;
|
||||
|
||||
public DiType(@NotNull Class<?> clazz, @NotNull List<DiType> typeParameters) {
|
||||
this.clazz = clazz;
|
||||
this.typeParameters = typeParameters;
|
||||
|
||||
if (clazz.getTypeParameters().length != typeParameters.size()) {
|
||||
throw new IllegalStateException("type parameter count mismatch: " + clazz + ", " + typeParameters);
|
||||
}
|
||||
}
|
||||
|
||||
public DiType(@NotNull Class<?> clazz) {
|
||||
this(clazz, Collections.<DiType>emptyList());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Class<?> getClazz() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<DiType> getTypeParameters() {
|
||||
return typeParameters;
|
||||
}
|
||||
|
||||
public boolean isAssignableFrom(@NotNull DiType that) {
|
||||
if (!this.clazz.isAssignableFrom(that.clazz)) {
|
||||
return false;
|
||||
}
|
||||
// TODO: following code incorrectly assumes that each type parameter
|
||||
// is projected into type parameter in the same position
|
||||
return this.typeParameters.equals(that.typeParameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
DiType type = (DiType) o;
|
||||
|
||||
if (!clazz.equals(type.clazz)) return false;
|
||||
if (!typeParameters.equals(type.typeParameters)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = clazz.hashCode();
|
||||
result = 31 * result + typeParameters.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static DiType fromReflectionType(@NotNull Type type) {
|
||||
if (type instanceof Class<?>) {
|
||||
return new DiType((Class) type);
|
||||
}
|
||||
if (type instanceof ParameterizedType) {
|
||||
ParameterizedType parameterizedType = (ParameterizedType) type;
|
||||
Class<?> owner = (Class<?>) parameterizedType.getRawType();
|
||||
List<DiType> diTypeParameters = Lists.newArrayList();
|
||||
for (Type typeParameter : parameterizedType.getActualTypeArguments()) {
|
||||
diTypeParameters.add(fromReflectionType(typeParameter));
|
||||
}
|
||||
return new DiType(owner, diTypeParameters);
|
||||
}
|
||||
throw new IllegalArgumentException("unsupported type: " + type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static DiType collectionOf(@NotNull Class<?> type) {
|
||||
return collectionOf(new DiType(type));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static DiType collectionOf(@NotNull DiType type) {
|
||||
return new DiType(List.class, Lists.newArrayList(type));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static DiType listOf(@NotNull Class<?> type) {
|
||||
return collectionOf(new DiType(type));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static DiType listOf(@NotNull DiType type) {
|
||||
return new DiType(List.class, Lists.newArrayList(type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (typeParameters.size() > 0) {
|
||||
return clazz + "<...>";
|
||||
}
|
||||
else {
|
||||
return clazz.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface Expression {
|
||||
@NotNull
|
||||
String renderAsCode();
|
||||
|
||||
@NotNull
|
||||
Collection<DiType> getTypesToImport();
|
||||
|
||||
@Nullable
|
||||
DiType getType();
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class FactoryMethod {
|
||||
private final String name;
|
||||
private final List<Parameter> parameters;
|
||||
private final DiType returnType;
|
||||
|
||||
public FactoryMethod(@NotNull String name, @NotNull DiType returnType, @NotNull List<Parameter> parameters) {
|
||||
this.name = name;
|
||||
this.parameters = parameters;
|
||||
this.returnType = returnType;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<Parameter> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DiType getReturnType() {
|
||||
return returnType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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.Lists;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import static org.jetbrains.jet.di.InjectorGeneratorUtil.var;
|
||||
|
||||
class Field {
|
||||
|
||||
public static Field create(boolean isPublic, DiType type, String name, @Nullable Expression init) {
|
||||
Field field = new Field(isPublic, type, name);
|
||||
if (init != null) {
|
||||
field.setInitialization(init);
|
||||
}
|
||||
return field;
|
||||
}
|
||||
|
||||
private final DiType type;
|
||||
private final String name;
|
||||
private final boolean isPublic;
|
||||
|
||||
@NotNull
|
||||
private Expression initialization;
|
||||
|
||||
private final List<SetterDependency> dependencies = Lists.newArrayList();
|
||||
|
||||
Field(boolean isPublic, DiType type, String name) {
|
||||
this.isPublic = isPublic;
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this.initialization = new InstantiateType(type);
|
||||
}
|
||||
|
||||
public DiType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getTypeName() {
|
||||
return type.getClazz().getSimpleName();
|
||||
}
|
||||
|
||||
public String getGetterName() {
|
||||
String prefix;
|
||||
if (getType().getClazz() == boolean.class || getType().getClazz() == Boolean.class) {
|
||||
prefix = "is";
|
||||
}
|
||||
else {
|
||||
prefix = "get";
|
||||
}
|
||||
return prefix + StringUtil.capitalize(getName());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Expression getInitialization() {
|
||||
return initialization;
|
||||
}
|
||||
|
||||
public void setInitialization(@NotNull Expression initialization) {
|
||||
this.initialization = initialization;
|
||||
}
|
||||
|
||||
public List<SetterDependency> getDependencies() {
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
public boolean isPublic() {
|
||||
return isPublic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getTypeName() + " " + getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Field field = (Field) o;
|
||||
|
||||
if (!name.equals(field.name)) return false;
|
||||
if (!type.equals(field.type)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = type.hashCode();
|
||||
result = 31 * result + name.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<Field> getFieldsAccessibleViaGetters() {
|
||||
Class<?> clazz = type.getClazz();
|
||||
List<Field> result = Lists.newArrayList();
|
||||
for (Method method : allGetters(clazz)) {
|
||||
MethodCall init = new MethodCall(this, method);
|
||||
DiType initType = init.getType();
|
||||
result.add(create(false, initType, var(initType), init));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Collection<Method> allGetters(@NotNull Class clazz) {
|
||||
Map<String, Method> getters = new TreeMap<String, Method>();
|
||||
for (Method method : clazz.getMethods()) {
|
||||
if (method.getDeclaringClass() == Object.class) {
|
||||
continue;
|
||||
}
|
||||
if (isGetter(method)) {
|
||||
if (!getters.containsKey(method.getName())) {
|
||||
getters.put(method.getName(), method);
|
||||
}
|
||||
}
|
||||
}
|
||||
return getters.values();
|
||||
}
|
||||
|
||||
private static boolean isGetter(@NotNull Method method) {
|
||||
String name = method.getName();
|
||||
return name.startsWith("get") && name.length() > 3 && method.getParameterTypes().length == 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class GeneratorsFileUtil {
|
||||
@SuppressWarnings("UseOfSystemOutOrSystemErr")
|
||||
public static void writeFileIfContentChanged(File file, String newText) throws IOException {
|
||||
writeFileIfContentChanged(file, newText, true);
|
||||
}
|
||||
|
||||
@SuppressWarnings("UseOfSystemOutOrSystemErr")
|
||||
public static void writeFileIfContentChanged(File file, String newText, boolean logNotChanged) throws IOException {
|
||||
File parentFile = file.getParentFile();
|
||||
if (!parentFile.exists()) {
|
||||
if (parentFile.mkdirs()) {
|
||||
System.out.println("Directory created: " + parentFile.getAbsolutePath());
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Cannot create directory: " + parentFile);
|
||||
}
|
||||
}
|
||||
|
||||
if (checkFileIgnoringLineSeparators(file, newText)) {
|
||||
if (logNotChanged) {
|
||||
System.out.println("Not changed: " + file.getAbsolutePath());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
boolean useTmpfile = !SystemInfo.isWindows;
|
||||
|
||||
File tmpfile = useTmpfile ? new File(file.getName() + ".tmp") : file;
|
||||
|
||||
FileUtil.writeToFile(tmpfile, newText);
|
||||
System.out.println("File written: " + tmpfile.getAbsolutePath());
|
||||
if (useTmpfile) {
|
||||
if (!tmpfile.renameTo(file)) {
|
||||
throw new RuntimeException("failed to rename " + tmpfile + " to " + file);
|
||||
}
|
||||
System.out.println("Renamed " + tmpfile + " to " + file);
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
private static boolean checkFileIgnoringLineSeparators(File file, String content) {
|
||||
String currentContent;
|
||||
try {
|
||||
currentContent = FileUtil.loadFile(file, true);
|
||||
}
|
||||
catch (Throwable ignored) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return StringUtil.convertLineSeparators(content).equals(currentContent);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public class GetSingleton implements Expression {
|
||||
|
||||
public static GetSingleton byMethod(@NotNull Class<?> singletonClass, @NotNull String methodName) {
|
||||
return new GetSingleton(singletonClass, methodName, "()");
|
||||
}
|
||||
|
||||
public static GetSingleton byField(@NotNull Class<?> singletonClass, @NotNull String fieldName) {
|
||||
return new GetSingleton(singletonClass, fieldName, "");
|
||||
}
|
||||
|
||||
private final Class<?> singletonClass;
|
||||
private final String memberName;
|
||||
private final String callSuffix;
|
||||
|
||||
private GetSingleton(@NotNull Class<?> singletonClass, @NotNull String name, String callSuffix) {
|
||||
this.singletonClass = singletonClass;
|
||||
this.memberName = name;
|
||||
this.callSuffix = callSuffix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return renderAsCode();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String renderAsCode() {
|
||||
return singletonClass.getSimpleName() + "." + memberName + callSuffix;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<DiType> getTypesToImport() {
|
||||
return Collections.singletonList(new DiType(singletonClass));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DiType getType() {
|
||||
return new DiType(singletonClass);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.Lists;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public class GivenExpression implements Expression {
|
||||
private final String expression;
|
||||
private final Collection<DiType> typesToImport;
|
||||
|
||||
|
||||
public GivenExpression(@NotNull String expression) {
|
||||
this(expression, Collections.<DiType>emptyList());
|
||||
}
|
||||
|
||||
public GivenExpression(@NotNull String expression, @NotNull DiType... typesToImport) {
|
||||
this(expression, Arrays.asList(typesToImport));
|
||||
}
|
||||
|
||||
public GivenExpression(@NotNull String expression, @NotNull Class<?>... typesToImport) {
|
||||
this(expression, convertClassesToDiTypes(typesToImport));
|
||||
}
|
||||
|
||||
private static Collection<DiType> convertClassesToDiTypes(Class<?>[] typesToImport) {
|
||||
Collection<DiType> types = Lists.newArrayList();
|
||||
for (Class<?> aClass : typesToImport) {
|
||||
types.add(new DiType(aClass));
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
public GivenExpression(@NotNull String expression, @NotNull Collection<DiType> typesToImport) {
|
||||
this.expression = expression;
|
||||
this.typesToImport = typesToImport;
|
||||
}
|
||||
|
||||
public String getExpression() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "given<" + expression + ">";
|
||||
}
|
||||
|
||||
public DiType getType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String renderAsCode() {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<DiType> getTypesToImport() {
|
||||
return typesToImport;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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 org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.utils.DFS;
|
||||
import org.jetbrains.jet.utils.Printer;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class InjectionLogicGenerator {
|
||||
|
||||
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 prefixForInitialization(Field field) {
|
||||
return "this.";
|
||||
}
|
||||
}.generate(p, fields);
|
||||
}
|
||||
|
||||
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 prefixForInitialization(Field field) {
|
||||
return importManager.render(field.getType()) + " ";
|
||||
}
|
||||
}.generate(p, fields);
|
||||
}
|
||||
|
||||
protected void generate(@NotNull Printer p, @NotNull Collection<Field> fields) {
|
||||
List<Field> topOrder = DFS.topologicalOrder(fields, new DFS.Neighbors<Field>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public Iterable<Field> getNeighbors(Field current) {
|
||||
Expression initialization = current.getInitialization();
|
||||
if (initialization instanceof ConstructorCall) {
|
||||
ConstructorCall call = (ConstructorCall) initialization;
|
||||
return call.getConstructorArguments();
|
||||
}
|
||||
else if (initialization instanceof MethodCall) {
|
||||
return Collections.singletonList(((MethodCall) initialization).getReceiver());
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
});
|
||||
Collections.reverse(topOrder);
|
||||
|
||||
// Initialize fields
|
||||
for (Field field : topOrder) {
|
||||
//if (!backsParameter.contains(field) || field.isPublic()) {
|
||||
p.println(prefixForInitialization(field), field.getName(), " = ", field.getInitialization().renderAsCode(), ";");
|
||||
//}
|
||||
}
|
||||
p.printlnWithNoIndent();
|
||||
|
||||
// Call setters
|
||||
for (Field field : fields) {
|
||||
for (SetterDependency dependency : field.getDependencies()) {
|
||||
String prefix = prefixForSetterCall(field);
|
||||
String dependencyName = dependency.getDependency().getName();
|
||||
String dependentName = dependency.getDependent().getName();
|
||||
p.println(prefix, dependentName, ".", dependency.getSetterName(), "(", dependencyName, ");");
|
||||
}
|
||||
if (!field.getDependencies().isEmpty()) {
|
||||
p.printlnWithNoIndent();
|
||||
}
|
||||
}
|
||||
|
||||
// call @PostConstruct
|
||||
for (Field field : fields) {
|
||||
// TODO: type of field may be different from type of object
|
||||
List<Method> postConstructMethods = InjectorGeneratorUtil
|
||||
.getPostConstructMethods(InjectorGeneratorUtil.getEffectiveFieldType(field).getClazz());
|
||||
for (Method postConstruct : postConstructMethods) {
|
||||
p.println(prefixForPostConstructorCall(field), field.getName(), ".", postConstruct.getName(), "();");
|
||||
}
|
||||
if (postConstructMethods.size() > 0) {
|
||||
p.printlnWithNoIndent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract String prefixForInitialization(Field field);
|
||||
|
||||
protected abstract String prefixForSetterCall(Field field);
|
||||
|
||||
protected abstract String prefixForPostConstructorCall(Field field);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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
|
||||
|
||||
public fun generator(
|
||||
targetSourceRoot: String,
|
||||
injectorPackageName: String,
|
||||
injectorClassName: String,
|
||||
generatedBy: String,
|
||||
body: DependencyInjectorGenerator.() -> Unit
|
||||
): DependencyInjectorGenerator {
|
||||
val generator = DependencyInjectorGenerator()
|
||||
generator.configure(targetSourceRoot, injectorPackageName, injectorClassName, generatedBy)
|
||||
generator.body()
|
||||
return generator
|
||||
}
|
||||
|
||||
inline public fun <reified T> DependencyInjectorGenerator.field(
|
||||
name: String = defaultName(javaClass<T>()),
|
||||
init: Expression? = null,
|
||||
useAsContext: Boolean = false
|
||||
) {
|
||||
addField(false, DiType(javaClass<T>()), name, init, useAsContext)
|
||||
}
|
||||
|
||||
inline public fun <reified T> DependencyInjectorGenerator.publicField(
|
||||
name: String = defaultName(javaClass<T>()),
|
||||
init: Expression? = null,
|
||||
useAsContext: Boolean = false
|
||||
) {
|
||||
addField(true, DiType(javaClass<T>()), name, init, useAsContext)
|
||||
}
|
||||
|
||||
inline public fun <reified T> DependencyInjectorGenerator.parameter(
|
||||
name: String = defaultName(javaClass<T>()),
|
||||
useAsContext: Boolean = false
|
||||
) {
|
||||
addParameter(false, DiType(javaClass<T>()), name, true, useAsContext)
|
||||
}
|
||||
|
||||
inline public fun <reified T> DependencyInjectorGenerator.publicParameter(
|
||||
name: String = defaultName(javaClass<T>()),
|
||||
useAsContext: Boolean = false
|
||||
) {
|
||||
addParameter(true, DiType(javaClass<T>()), name, true, useAsContext)
|
||||
}
|
||||
|
||||
public fun defaultName(entityType: Class<*>): String = InjectorGeneratorUtil.`var`(DiType(entityType))
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.Lists;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
public class InjectorGeneratorUtil {
|
||||
public static DiType getEffectiveFieldType(Field field) {
|
||||
DiType implType = field.getInitialization().getType();
|
||||
return implType == null ? field.getType() : implType;
|
||||
}
|
||||
|
||||
public static List<Method> getPostConstructMethods(Class<?> clazz) {
|
||||
return getInjectSpecialMethods(clazz, PostConstruct.class);
|
||||
}
|
||||
|
||||
public static List<Method> getPreDestroyMethods(Class<?> clazz) {
|
||||
return getInjectSpecialMethods(clazz, PreDestroy.class);
|
||||
}
|
||||
|
||||
private static List<Method> getInjectSpecialMethods(Class<?> clazz, Class<? extends Annotation> annotationClass) {
|
||||
List<Method> r = Lists.newArrayList();
|
||||
for (Method method : clazz.getMethods()) {
|
||||
if (method.getAnnotation(annotationClass) != null) {
|
||||
if (method.getParameterTypes().length != 0) {
|
||||
throw new IllegalStateException("@PostConstruct method must have no arguments: " + method);
|
||||
}
|
||||
r.add(method);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String var(@NotNull DiType type) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(StringUtil.decapitalize(type.getClazz().getSimpleName().replaceFirst("(?<=.)Impl$", "")));
|
||||
if (type.getTypeParameters().size() > 0) {
|
||||
sb.append("Of");
|
||||
}
|
||||
for (DiType parameter : type.getTypeParameters()) {
|
||||
sb.append(StringUtil.capitalize(var(parameter)));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private InjectorGeneratorUtil() {}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class InstantiateType implements Expression {
|
||||
|
||||
private final DiType type;
|
||||
|
||||
public InstantiateType(@NotNull DiType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public InstantiateType(@NotNull Class<?> theClass) {
|
||||
this(new DiType(theClass));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DiType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[Instantiate type: " + getType() + "]";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String renderAsCode() {
|
||||
throw new UnsupportedOperationException("This should be replaced by some concrete expression by the time this method is called");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<DiType> getTypesToImport() {
|
||||
throw new UnsupportedOperationException("This should be replaced by some concrete expression by the time this method is called");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2010-2014 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 java.lang.reflect.Method
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
|
||||
public class MethodCall(
|
||||
val receiver: Field,
|
||||
val method: Method
|
||||
) : Expression {
|
||||
override fun renderAsCode(): String {
|
||||
return "${receiver.getName()}.${method.getName()}()"
|
||||
}
|
||||
|
||||
override fun getTypesToImport() = listOf<DiType>()
|
||||
|
||||
override fun getType(): DiType = DiType.fromReflectionType(method.getGenericReturnType())
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
class Parameter {
|
||||
private final DiType type;
|
||||
private final String name;
|
||||
private final Field field;
|
||||
private final boolean required;
|
||||
|
||||
Parameter(DiType type, String name, Field field, boolean required) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this.field = field;
|
||||
this.required = required;
|
||||
}
|
||||
|
||||
public DiType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Field getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public boolean isRequired() {
|
||||
return required;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
Parameter parameter = (Parameter) o;
|
||||
|
||||
if (name != null ? !name.equals(parameter.name) : parameter.name != null) return false;
|
||||
if (type != null ? !type.equals(parameter.type) : parameter.type != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = type != null ? type.hashCode() : 0;
|
||||
result = 31 * result + (name != null ? name.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public class ParameterExpression implements Expression {
|
||||
private final Parameter parameter;
|
||||
|
||||
public ParameterExpression(Parameter parameter) {
|
||||
this.parameter = parameter;
|
||||
}
|
||||
|
||||
public Parameter getParameter() {
|
||||
return parameter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "parameter<" + parameter.getName() + ">";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String renderAsCode() {
|
||||
return parameter.getName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<DiType> getTypesToImport() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DiType getType() {
|
||||
return parameter.getType();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
class SetterDependency {
|
||||
private final Field dependent;
|
||||
private final String setterName;
|
||||
private final Field dependency;
|
||||
|
||||
SetterDependency(Field dependent, String setterName, Field dependency) {
|
||||
this.dependent = dependent;
|
||||
this.setterName = setterName;
|
||||
this.dependency = dependency;
|
||||
}
|
||||
|
||||
public Field getDependent() {
|
||||
return dependent;
|
||||
}
|
||||
|
||||
public String getSetterName() {
|
||||
return setterName;
|
||||
}
|
||||
|
||||
public Field getDependency() {
|
||||
return dependency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return dependent.getName() + "." + setterName + "(" + dependency.getName() + ")";
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ abstract class BuiltInsSourceGenerator(val out: PrintWriter) {
|
||||
protected open fun getPackage(): String = "kotlin"
|
||||
|
||||
final fun generate() {
|
||||
out.println(File("injector-generator/copyright.txt").readText())
|
||||
out.println(File("generators/injector-generator/copyright.txt").readText())
|
||||
// Don't include generator class name in the message: these are built-in sources,
|
||||
// and we don't want to scare users with any internal information about our project
|
||||
out.println("// Auto-generated file. DO NOT EDIT!")
|
||||
|
||||
@@ -36,7 +36,7 @@ fun main(args: Array<String>) {
|
||||
fun generate(): String {
|
||||
val sb = StringBuilder()
|
||||
val p = Printer(sb)
|
||||
p.println(FileUtil.loadFile(File("injector-generator/copyright.txt")))
|
||||
p.println(FileUtil.loadFile(File("generators/injector-generator/copyright.txt")))
|
||||
p.println("package org.jetbrains.jet.lang.evaluate")
|
||||
p.println()
|
||||
p.println("import java.math.BigInteger")
|
||||
@@ -61,7 +61,7 @@ fun generate(): String {
|
||||
for (function in functions) {
|
||||
val parametersTypes = function.getParametersTypes()
|
||||
|
||||
when (parametersTypes.size) {
|
||||
when (parametersTypes.size()) {
|
||||
1 -> unaryOperationsMap.add(function.getName().asString() to parametersTypes)
|
||||
2 -> binaryOperationsMap.add(function.getName().asString() to parametersTypes)
|
||||
else -> throw IllegalStateException("Couldn't add following method from builtins to operations map: ${function.getName()} in class ${descriptor.getName()}")
|
||||
|
||||
@@ -38,7 +38,7 @@ public class GenerateKeywordStrings {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Printer p = new Printer(sb);
|
||||
|
||||
p.println(FileUtil.loadFile(new File("injector-generator/copyright.txt")));
|
||||
p.println(FileUtil.loadFile(new File("generators/injector-generator/copyright.txt")));
|
||||
p.println("package org.jetbrains.jet.renderer;");
|
||||
p.println();
|
||||
p.println("import java.util.Arrays;");
|
||||
|
||||
@@ -76,7 +76,7 @@ public class TestGenerator {
|
||||
StringBuilder out = new StringBuilder();
|
||||
Printer p = new Printer(out);
|
||||
|
||||
p.println(FileUtil.loadFile(new File("injector-generator/copyright.txt")));
|
||||
p.println(FileUtil.loadFile(new File("generators/injector-generator/copyright.txt")));
|
||||
p.println("package ", suiteClassPackage, ";");
|
||||
p.println();
|
||||
p.println("import com.intellij.testFramework.TestDataPath;");
|
||||
|
||||
Reference in New Issue
Block a user