diff --git a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/GradleProperty.java b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/GradleProperty.java index ca1967d39d2f..fbab52352039 100644 --- a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/GradleProperty.java +++ b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/GradleProperty.java @@ -16,7 +16,6 @@ package org.jetbrains.plugins.gradle.model; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.io.Serializable; @@ -29,7 +28,4 @@ public interface GradleProperty extends Serializable { @NotNull String getTypeFqn(); - - @Nullable - Serializable getValue(); } diff --git a/plugins/gradle/tooling-extension-impl/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.serialization.SerializationService b/plugins/gradle/tooling-extension-impl/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.serialization.SerializationService index 458be61fc128..b769012f023e 100644 --- a/plugins/gradle/tooling-extension-impl/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.serialization.SerializationService +++ b/plugins/gradle/tooling-extension-impl/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.serialization.SerializationService @@ -16,4 +16,5 @@ # org.jetbrains.plugins.gradle.tooling.serialization.ExternalProjectSerializationService org.jetbrains.plugins.gradle.tooling.serialization.BuildScriptClasspathModelSerializationService -org.jetbrains.plugins.gradle.tooling.serialization.RepositoriesModelSerializationService \ No newline at end of file +org.jetbrains.plugins.gradle.tooling.serialization.RepositoriesModelSerializationService +org.jetbrains.plugins.gradle.tooling.serialization.GradleExtensionsSerializationService \ No newline at end of file diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleConfiguration.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleConfiguration.java index bc3c8add2560..bcc95c3f9ee3 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleConfiguration.java +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleConfiguration.java @@ -51,4 +51,28 @@ public final class DefaultGradleConfiguration implements GradleConfiguration { public boolean isScriptClasspathConfiguration() { return scriptClasspathConfiguration; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + DefaultGradleConfiguration that = (DefaultGradleConfiguration)o; + + if (visible != that.visible) return false; + if (scriptClasspathConfiguration != that.scriptClasspathConfiguration) return false; + if (name != null ? !name.equals(that.name) : that.name != null) return false; + if (description != null ? !description.equals(that.description) : that.description != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = name != null ? name.hashCode() : 0; + result = 31 * result + (description != null ? description.hashCode() : 0); + result = 31 * result + (visible ? 1 : 0); + result = 31 * result + (scriptClasspathConfiguration ? 1 : 0); + return result; + } } diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleConvention.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleConvention.java index 5410a592f2a4..0f4cd763128d 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleConvention.java +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleConvention.java @@ -10,7 +10,7 @@ public final class DefaultGradleConvention extends DefaultGradleProperty impleme @PropertyMapping({"name", "typeFqn"}) public DefaultGradleConvention(@NotNull String name, @Nullable String typeFqn) { - super(name, typeFqn, null); + super(name, typeFqn); } public DefaultGradleConvention(GradleConvention convention) { diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleExtension.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleExtension.java index 27c76e888918..90480520dfca 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleExtension.java +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleExtension.java @@ -10,7 +10,7 @@ public final class DefaultGradleExtension extends DefaultGradleProperty implemen @PropertyMapping({"name", "typeFqn"}) public DefaultGradleExtension(@NotNull String name, @Nullable String typeFqn) { - super(name, typeFqn, null); + super(name, typeFqn); } public DefaultGradleExtension(GradleExtension extension) { diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleExtensions.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleExtensions.java index d15fbc3d8e8b..441c07a84c5b 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleExtensions.java +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleExtensions.java @@ -110,4 +110,32 @@ public class DefaultGradleExtensions implements GradleExtensions { public List getConfigurations() { return configurations == null ? Collections.emptyList() : configurations; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + DefaultGradleExtensions that = (DefaultGradleExtensions)o; + + if (extensions != null ? !extensions.equals(that.extensions) : that.extensions != null) return false; + if (conventions != null ? !conventions.equals(that.conventions) : that.conventions != null) return false; + if (gradleProperties != null ? !gradleProperties.equals(that.gradleProperties) : that.gradleProperties != null) return false; + if (tasks != null ? !tasks.equals(that.tasks) : that.tasks != null) return false; + if (configurations != null ? !configurations.equals(that.configurations) : that.configurations != null) return false; + if (parentProjectPath != null ? !parentProjectPath.equals(that.parentProjectPath) : that.parentProjectPath != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = extensions != null ? extensions.hashCode() : 0; + result = 31 * result + (conventions != null ? conventions.hashCode() : 0); + result = 31 * result + (gradleProperties != null ? gradleProperties.hashCode() : 0); + result = 31 * result + (tasks != null ? tasks.hashCode() : 0); + result = 31 * result + (configurations != null ? configurations.hashCode() : 0); + result = 31 * result + (parentProjectPath != null ? parentProjectPath.hashCode() : 0); + return result; + } } diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleProperty.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleProperty.java index ba0223c08882..65d591285095 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleProperty.java +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultGradleProperty.java @@ -5,8 +5,6 @@ import com.intellij.serialization.PropertyMapping; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.Serializable; - /** * @author Vladislav.Soroka */ @@ -15,18 +13,15 @@ public class DefaultGradleProperty implements GradleProperty { private final String name; @NotNull private final String rootTypeFqn; - @Nullable - private final Serializable value; - @PropertyMapping({"name", "typeFqn", "value"}) - public DefaultGradleProperty(@NotNull String name, @Nullable String typeFqn, @Nullable Serializable value) { + @PropertyMapping({"name", "typeFqn"}) + public DefaultGradleProperty(@NotNull String name, @Nullable String typeFqn) { this.name = name; rootTypeFqn = typeFqn == null ? "Object" : typeFqn; - this.value = value; } public DefaultGradleProperty(GradleProperty property) { - this(property.getName(), property.getTypeFqn(), property.getValue()); + this(property.getName(), property.getTypeFqn()); } @NotNull @@ -41,9 +36,23 @@ public class DefaultGradleProperty implements GradleProperty { return rootTypeFqn; } - @Nullable @Override - public Serializable getValue() { - return value; + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + DefaultGradleProperty property = (DefaultGradleProperty)o; + + if (!name.equals(property.name)) return false; + if (!rootTypeFqn.equals(property.rootTypeFqn)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = name.hashCode(); + result = 31 * result + rootTypeFqn.hashCode(); + return result; } } diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ProjectExtensionsDataBuilderImpl.groovy b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ProjectExtensionsDataBuilderImpl.groovy index bc4ebaffe05a..7c3d4ac6e790 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ProjectExtensionsDataBuilderImpl.groovy +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ProjectExtensionsDataBuilderImpl.groovy @@ -43,7 +43,7 @@ class ProjectExtensionsDataBuilderImpl implements ModelBuilderService { extensions.extraProperties.properties.each { name, value -> if(name == 'extraModelBuilder' || name.contains('.')) return String typeFqn = getType(value) - result.gradleProperties.add(new DefaultGradleProperty(name, typeFqn, value.toString())) + result.gradleProperties.add(new DefaultGradleProperty(name, typeFqn)) } for (it in extensions.findAll()) { @@ -66,7 +66,7 @@ class ProjectExtensionsDataBuilderImpl implements ModelBuilderService { return result } - private List extractKeysViaReflection(ExtensionContainer convention) { + private static List extractKeysViaReflection(ExtensionContainer convention) { def m = convention.class.getMethod("getAsMap") return (m.invoke(convention) as Map).keySet().asList() as List } diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/serialization/GradleExtensionsSerializationService.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/serialization/GradleExtensionsSerializationService.java new file mode 100644 index 000000000000..8415719c6283 --- /dev/null +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/serialization/GradleExtensionsSerializationService.java @@ -0,0 +1,312 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.tooling.serialization; + +import com.amazon.ion.IonReader; +import com.amazon.ion.IonType; +import com.amazon.ion.IonWriter; +import com.amazon.ion.system.IonBinaryWriterBuilder; +import com.amazon.ion.system.IonReaderBuilder; +import com.intellij.openapi.util.Getter; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.gradle.model.*; +import org.jetbrains.plugins.gradle.tooling.util.IntObjectMap; +import org.jetbrains.plugins.gradle.tooling.util.ObjectCollector; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import static org.jetbrains.plugins.gradle.tooling.serialization.ToolingStreamUtils.*; + +/** + * @author Vladislav.Soroka + */ +public class GradleExtensionsSerializationService implements SerializationService { + private final WriteContext myWriteContext = new WriteContext(); + private final ReadContext myReadContext = new ReadContext(); + + @Override + public byte[] write(GradleExtensions gradleExtensions, Class modelClazz) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + IonWriter writer = IonBinaryWriterBuilder.standard().build(out); + try { + write(writer, myWriteContext, gradleExtensions); + } + finally { + writer.close(); + } + return out.toByteArray(); + } + + @Override + public GradleExtensions read(byte[] object, Class modelClazz) throws IOException { + IonReader reader = IonReaderBuilder.standard().build(object); + try { + return read(reader, myReadContext); + } + finally { + reader.close(); + } + } + + @Override + public Class getModelClass() { + return GradleExtensions.class; + } + + private static void write(final IonWriter writer, final WriteContext context, final GradleExtensions model) throws IOException { + context.objectCollector.add(model, new ObjectCollector.Processor() { + @Override + public void process(boolean isAdded, int objectId) throws IOException { + writer.stepIn(IonType.STRUCT); + writer.setFieldName(OBJECT_ID_FIELD); + writer.writeInt(objectId); + if (isAdded) { + writeString(writer, "parentProjectPath", model.getParentProjectPath()); + writeConfigurations(writer, context, model.getConfigurations()); + writeConventions(writer, context, model.getConventions()); + writeExtensions(writer, context, model.getExtensions()); + writeGradleProperties(writer, context, model.getGradleProperties()); + // do not write tasks, as it will be added from ExternalProject model at BaseGradleProjectResolverExtension.populateModuleExtraModels + } + writer.stepOut(); + } + }); + } + + private static void writeConfigurations(IonWriter writer, + WriteContext context, + List configurations) throws IOException { + writer.setFieldName("configurations"); + writer.stepIn(IonType.LIST); + for (GradleConfiguration configuration : configurations) { + writeConfiguration(writer, context, configuration); + } + writer.stepOut(); + } + + + static void writeConfiguration(final IonWriter writer, + final WriteContext context, + final GradleConfiguration configuration) throws IOException { + context.configurationsCollector.add(configuration, new ObjectCollector.Processor() { + @Override + public void process(boolean isAdded, int objectId) throws IOException { + writer.stepIn(IonType.STRUCT); + writer.setFieldName(OBJECT_ID_FIELD); + writer.writeInt(objectId); + if (isAdded) { + writeString(writer, "name", configuration.getName()); + writeString(writer, "description", configuration.getDescription()); + writeBoolean(writer, "visible", configuration.isVisible()); + writeBoolean(writer, "scriptClasspathConfiguration", configuration.isScriptClasspathConfiguration()); + } + writer.stepOut(); + } + }); + } + + private static void writeConventions(IonWriter writer, + WriteContext context, + List conventions) throws IOException { + writer.setFieldName("conventions"); + writer.stepIn(IonType.LIST); + for (GradleConvention convention : conventions) { + write(writer, context, convention); + } + writer.stepOut(); + } + + private static void writeExtensions(IonWriter writer, + WriteContext context, + List extensions) throws IOException { + writer.setFieldName("extensions"); + writer.stepIn(IonType.LIST); + for (GradleExtension extension : extensions) { + write(writer, context, extension); + } + writer.stepOut(); + } + + private static void writeGradleProperties(IonWriter writer, + WriteContext context, + List properties) throws IOException { + writer.setFieldName("properties"); + writer.stepIn(IonType.LIST); + for (GradleProperty property : properties) { + write(writer, context, property); + } + writer.stepOut(); + } + + static void write(final IonWriter writer, + final WriteContext context, + final GradleProperty property) throws IOException { + context.propertiesCollector.add(property, new ObjectCollector.Processor() { + @Override + public void process(boolean isAdded, int objectId) throws IOException { + writer.stepIn(IonType.STRUCT); + writer.setFieldName(OBJECT_ID_FIELD); + writer.writeInt(objectId); + if (isAdded) { + writeString(writer, "name", property.getName()); + writeString(writer, "typeFqn", property.getTypeFqn()); + } + writer.stepOut(); + } + }); + } + + @Nullable + private static GradleExtensions read(final IonReader reader, final ReadContext context) { + if (reader.next() == null) return null; + reader.stepIn(); + + GradleExtensions extensions = + context.objectMap.computeIfAbsent(readInt(reader, OBJECT_ID_FIELD), new Getter() { + @Override + public DefaultGradleExtensions get() { + DefaultGradleExtensions gradleExtensions = new DefaultGradleExtensions(); + gradleExtensions.setParentProjectPath(readString(reader, "parentProjectPath")); + gradleExtensions.getConfigurations().addAll(readConfigurations(reader, context)); + gradleExtensions.getConventions().addAll(readConventions(reader, context)); + gradleExtensions.getExtensions().addAll(readExtensions(reader, context)); + gradleExtensions.getGradleProperties().addAll(readGradleProperties(reader, context)); + // do not read tasks, as it will be added from ExternalProject model at BaseGradleProjectResolverExtension.populateModuleExtraModels + return gradleExtensions; + } + }); + reader.stepOut(); + return extensions; + } + + private static List readConfigurations(IonReader reader, ReadContext context) { + List list = new ArrayList(); + reader.next(); + reader.stepIn(); + DefaultGradleConfiguration configuration; + while ((configuration = readConfiguration(reader, context)) != null) { + list.add(configuration); + } + reader.stepOut(); + return list; + } + + @Nullable + private static DefaultGradleConfiguration readConfiguration(final IonReader reader, ReadContext context) { + if (reader.next() == null) return null; + reader.stepIn(); + DefaultGradleConfiguration configuration = + context.configurationsMap.computeIfAbsent(readInt(reader, OBJECT_ID_FIELD), new Getter() { + @Override + public DefaultGradleConfiguration get() { + return new DefaultGradleConfiguration( + assertNotNull(readString(reader, "name")), + readString(reader, "description"), + readBoolean(reader, "visible"), + readBoolean(reader, "scriptClasspathConfiguration")); + } + }); + reader.stepOut(); + return configuration; + } + + private static List readConventions(IonReader reader, ReadContext context) { + List list = new ArrayList(); + reader.next(); + reader.stepIn(); + DefaultGradleConvention entry; + while ((entry = readConvention(reader, context)) != null) { + list.add(entry); + } + reader.stepOut(); + return list; + } + + @Nullable + private static DefaultGradleConvention readConvention(final IonReader reader, ReadContext context) { + if (reader.next() == null) return null; + reader.stepIn(); + DefaultGradleConvention convention = + context.conventionsMap.computeIfAbsent(readInt(reader, OBJECT_ID_FIELD), new Getter() { + @Override + public DefaultGradleConvention get() { + return new DefaultGradleConvention(assertNotNull(readString(reader, "name")), readString(reader, "typeFqn")); + } + }); + reader.stepOut(); + return convention; + } + + private static List readExtensions(IonReader reader, ReadContext context) { + List list = new ArrayList(); + reader.next(); + reader.stepIn(); + DefaultGradleExtension entry; + while ((entry = readExtension(reader, context)) != null) { + list.add(entry); + } + reader.stepOut(); + return list; + } + + @Nullable + private static DefaultGradleExtension readExtension(final IonReader reader, ReadContext context) { + if (reader.next() == null) return null; + reader.stepIn(); + DefaultGradleExtension convention = + context.extensionsMap.computeIfAbsent(readInt(reader, OBJECT_ID_FIELD), new Getter() { + @Override + public DefaultGradleExtension get() { + return new DefaultGradleExtension(assertNotNull(readString(reader, "name")), readString(reader, "typeFqn")); + } + }); + reader.stepOut(); + return convention; + } + + private static List readGradleProperties(IonReader reader, ReadContext context) { + List list = new ArrayList(); + reader.next(); + reader.stepIn(); + DefaultGradleProperty entry; + while ((entry = readGradleProperty(reader, context)) != null) { + list.add(entry); + } + reader.stepOut(); + return list; + } + + @Nullable + private static DefaultGradleProperty readGradleProperty(final IonReader reader, ReadContext context) { + if (reader.next() == null) return null; + reader.stepIn(); + DefaultGradleProperty convention = + context.propertiesMap.computeIfAbsent(readInt(reader, OBJECT_ID_FIELD), new Getter() { + @Override + public DefaultGradleProperty get() { + return new DefaultGradleProperty(assertNotNull(readString(reader, "name")), readString(reader, "typeFqn")); + } + }); + reader.stepOut(); + return convention; + } + + private static class ReadContext { + private final IntObjectMap objectMap = new IntObjectMap(); + private final IntObjectMap configurationsMap = new IntObjectMap(); + private final IntObjectMap conventionsMap = new IntObjectMap(); + private final IntObjectMap extensionsMap = new IntObjectMap(); + private final IntObjectMap propertiesMap = new IntObjectMap(); + } + + private static class WriteContext { + private final ObjectCollector objectCollector = new ObjectCollector(); + private final ObjectCollector configurationsCollector = + new ObjectCollector(); + private final ObjectCollector propertiesCollector = + new ObjectCollector(); + } +} + diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/serialization/RepositoriesModelSerializationService.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/serialization/RepositoriesModelSerializationService.java index bbda07ecf040..5c46b6a3c9d3 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/serialization/RepositoriesModelSerializationService.java +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/serialization/RepositoriesModelSerializationService.java @@ -31,11 +31,11 @@ public class RepositoriesModelSerializationService implements SerializationServi private final ReadContext myReadContext = new ReadContext(); @Override - public byte[] write(RepositoriesModel classpathModel, Class modelClazz) throws IOException { + public byte[] write(RepositoriesModel repositoriesModel, Class modelClazz) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); IonWriter writer = IonBinaryWriterBuilder.standard().build(out); try { - write(writer, myWriteContext, classpathModel); + write(writer, myWriteContext, repositoriesModel); } finally { writer.close(); @@ -109,7 +109,7 @@ public class RepositoriesModelSerializationService implements SerializationServi if (reader.next() == null) return null; reader.stepIn(); - RepositoriesModel project = + RepositoriesModel model = context.objectMap.computeIfAbsent(readInt(reader, OBJECT_ID_FIELD), new Getter() { @Override public RepositoriesModelImpl get() { @@ -122,7 +122,7 @@ public class RepositoriesModelSerializationService implements SerializationServi } }); reader.stepOut(); - return project; + return model; } private static List readRepositories(IonReader reader, ReadContext context) { diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/serialization/ToolingStreamUtils.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/serialization/ToolingStreamUtils.java index 6bd9c2bdc5c6..5485427271bc 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/serialization/ToolingStreamUtils.java +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/serialization/ToolingStreamUtils.java @@ -109,6 +109,11 @@ public class ToolingStreamUtils { writer.writeString(value); } + public static void writeBoolean(@NotNull IonWriter writer, @NotNull String fieldName, boolean value) throws IOException { + writer.setFieldName(fieldName); + writer.writeBool(value); + } + public static void writeFile(@NotNull IonWriter writer, @NotNull String fieldName, @Nullable File file) throws IOException { writeString(writer, fieldName, file == null ? null : file.getPath()); }