From 906bed48fd7690ce1c60abcd484d09ca648f4f47 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Tue, 1 Oct 2019 19:12:07 +0300 Subject: [PATCH] [Gradle] Annotation processing model serialization service IDEA-187868 GitOrigin-RevId: a51f01647dd321d75c6e4df46d51710ac006348e --- .../serialization/ToolingStreamApiUtils.java | 12 ++ ...tooling.serialization.SerializationService | 3 +- .../AnnotationProcessingModelBuilder.java | 6 +- .../AnnotationProcessingConfigImpl.java | 25 ++-- .../AnnotationProcessingModelImpl.java | 14 ++ ...onProcessingModelSerializationService.java | 125 ++++++++++++++++-- .../serialization/ToolingSerializerTest.kt | 9 +- 7 files changed, 175 insertions(+), 19 deletions(-) diff --git a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/tooling/serialization/ToolingStreamApiUtils.java b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/tooling/serialization/ToolingStreamApiUtils.java index 795061872c34..130582673ef5 100644 --- a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/tooling/serialization/ToolingStreamApiUtils.java +++ b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/tooling/serialization/ToolingStreamApiUtils.java @@ -167,6 +167,18 @@ public class ToolingStreamApiUtils { return set; } + public static List readStringList(@NotNull IonReader reader) { + List list = new ArrayList(); + reader.next(); + reader.stepIn(); + String nextString; + while ((nextString = readString(reader, null)) != null) { + list.add(nextString); + } + reader.stepOut(); + return list; + } + public static void assertFieldName(@NotNull IonReader reader, @Nullable String fieldName) { String readerFieldName = reader.getFieldName(); assert fieldName == null || fieldName.equals(readerFieldName) : 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 2b0dcfbb8157..80c8938691ef 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 @@ -18,4 +18,5 @@ org.jetbrains.plugins.gradle.tooling.serialization.ExternalProjectSerializationS org.jetbrains.plugins.gradle.tooling.serialization.BuildScriptClasspathModelSerializationService org.jetbrains.plugins.gradle.tooling.serialization.RepositoriesModelSerializationService org.jetbrains.plugins.gradle.tooling.serialization.GradleExtensionsSerializationService -org.jetbrains.plugins.gradle.tooling.serialization.ExternalTestsSerializationService \ No newline at end of file +org.jetbrains.plugins.gradle.tooling.serialization.ExternalTestsSerializationService +org.jetbrains.plugins.gradle.tooling.serialization.AnnotationProcessingModelSerializationService \ No newline at end of file diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/AnnotationProcessingModelBuilder.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/AnnotationProcessingModelBuilder.java index 8e12f221ec43..3638c6f02b97 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/AnnotationProcessingModelBuilder.java +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/AnnotationProcessingModelBuilder.java @@ -60,7 +60,11 @@ public class AnnotationProcessingModelBuilder extends AbstractModelBuilderServic annotationProcessorArgs.add(arg); } } - sourceSetConfigs.put(sourceSet.getName(), new AnnotationProcessingConfigImpl(files, annotationProcessorArgs)); + Set paths = new LinkedHashSet(files.size()); + for (File file : files) { + paths.add(file.getAbsolutePath()); + } + sourceSetConfigs.put(sourceSet.getName(), new AnnotationProcessingConfigImpl(paths, annotationProcessorArgs)); } } } diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/internal/AnnotationProcessingConfigImpl.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/internal/AnnotationProcessingConfigImpl.java index 28860fae3b64..2c5db76e6e95 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/internal/AnnotationProcessingConfigImpl.java +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/internal/AnnotationProcessingConfigImpl.java @@ -1,13 +1,12 @@ // 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.internal; +import org.gradle.internal.impldep.com.google.common.base.Objects; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.gradle.model.AnnotationProcessingConfig; -import java.io.File; import java.io.Serializable; import java.util.Collection; -import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -15,12 +14,8 @@ public class AnnotationProcessingConfigImpl implements AnnotationProcessingConfi private final Set myPaths; private final List myArgs; - public AnnotationProcessingConfigImpl(Set files, List args) { - Set paths = new LinkedHashSet(files.size()); - for (File file : files) { - paths.add(file.getAbsolutePath()); - } - myPaths = paths; + public AnnotationProcessingConfigImpl(Set files, List args) { + myPaths = files; myArgs = args; } @@ -35,4 +30,18 @@ public class AnnotationProcessingConfigImpl implements AnnotationProcessingConfi public Collection getAnnotationProcessorArguments() { return myArgs; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AnnotationProcessingConfigImpl config = (AnnotationProcessingConfigImpl)o; + return Objects.equal(myPaths, config.myPaths) && + Objects.equal(myArgs, config.myArgs); + } + + @Override + public int hashCode() { + return Objects.hashCode(myPaths, myArgs); + } } diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/internal/AnnotationProcessingModelImpl.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/internal/AnnotationProcessingModelImpl.java index 941547454adf..9be52d706eac 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/internal/AnnotationProcessingModelImpl.java +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/internal/AnnotationProcessingModelImpl.java @@ -1,6 +1,7 @@ // 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.internal; +import org.gradle.internal.impldep.com.google.common.base.Objects; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.model.AnnotationProcessingConfig; @@ -27,4 +28,17 @@ public class AnnotationProcessingModelImpl implements AnnotationProcessingModel, public AnnotationProcessingConfig bySourceSetName(@NotNull String sourceSetName) { return configs.get(sourceSetName); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AnnotationProcessingModelImpl model = (AnnotationProcessingModelImpl)o; + return Objects.equal(configs, model.configs); + } + + @Override + public int hashCode() { + return Objects.hashCode(configs); + } } diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/serialization/AnnotationProcessingModelSerializationService.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/serialization/AnnotationProcessingModelSerializationService.java index 98ef26c534ce..4386c78a9a79 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/serialization/AnnotationProcessingModelSerializationService.java +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/serialization/AnnotationProcessingModelSerializationService.java @@ -2,13 +2,27 @@ 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 com.intellij.util.ThrowableConsumer; +import org.jetbrains.plugins.gradle.model.AnnotationProcessingConfig; import org.jetbrains.plugins.gradle.model.AnnotationProcessingModel; +import org.jetbrains.plugins.gradle.tooling.internal.AnnotationProcessingConfigImpl; +import org.jetbrains.plugins.gradle.tooling.internal.AnnotationProcessingModelImpl; +import org.jetbrains.plugins.gradle.tooling.util.IntObjectMap; +import org.jetbrains.plugins.gradle.tooling.util.ObjectCollector; import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.jetbrains.plugins.gradle.tooling.serialization.ToolingStreamApiUtils.*; public class AnnotationProcessingModelSerializationService implements SerializationService { @@ -16,7 +30,8 @@ public class AnnotationProcessingModelSerializationService implements Serializat private final ReadContext myReadContext = new ReadContext(); @Override - public byte[] write(AnnotationProcessingModel annotationProcessingModel, Class modelClazz) throws IOException { + public byte[] write(AnnotationProcessingModel annotationProcessingModel, Class modelClazz) + throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); IonWriter writer = IonBinaryWriterBuilder.standard().build(out); try { @@ -28,10 +43,6 @@ public class AnnotationProcessingModelSerializationService implements Serializat return out.toByteArray(); } - private void write(IonWriter writer, WriteContext context, AnnotationProcessingModel model) { - - } - @Override public AnnotationProcessingModel read(byte[] object, Class modelClazz) throws IOException { IonReader reader = IonReaderBuilder.standard().build(object); @@ -43,8 +54,101 @@ public class AnnotationProcessingModelSerializationService implements Serializat } } - private AnnotationProcessingModel read(IonReader reader, ReadContext context) { - return null; + private static void write(final IonWriter writer, final WriteContext context, final AnnotationProcessingModel 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) { + writeConfigs(writer, context, model.allConfigs()); + } + writer.stepOut(); + } + }); + } + + private static void writeConfigs(final IonWriter writer, + final WriteContext context, + Map configs) throws IOException { + writeMap(writer, "configs", configs, new ThrowableConsumer() { + @Override + public void consume(String s) throws IOException { + writer.writeString(s); + } + }, new ThrowableConsumer() { + @Override + public void consume(AnnotationProcessingConfig config) throws IOException { + writeConfig(writer, context, config); + } + }); + } + + private static void writeConfig(final IonWriter writer, + final WriteContext context, + final AnnotationProcessingConfig config) throws IOException { + context.configCollector.add(config, 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) { + writeStrings(writer, "args", config.getAnnotationProcessorArguments()); + writeStrings(writer, "paths", config.getAnnotationProcessorPath()); + } + writer.stepOut(); + } + }); + } + + private static AnnotationProcessingModel read(final IonReader reader, final ReadContext context) { + if (reader.next() == null) return null; + reader.stepIn(); + + AnnotationProcessingModelImpl model = + context.objectMap + .computeIfAbsent(readInt(reader, OBJECT_ID_FIELD), new IntObjectMap.SimpleObjectFactory() { + @Override + public AnnotationProcessingModelImpl create() { + Map configs = readConfigs(reader, context); + return new AnnotationProcessingModelImpl(configs); + } + }); + reader.stepOut(); + return model; + } + + private static Map readConfigs(final IonReader reader, final ReadContext context) { + return readMap(reader, new Getter() { + @Override + public String get() { + return readString(reader, null); + } + }, new Getter() { + @Override + public AnnotationProcessingConfig get() { + return readConfig(reader, context); + } + }); + } + + private static AnnotationProcessingConfig readConfig(final IonReader reader, final ReadContext context) { + reader.next(); + reader.stepIn(); + AnnotationProcessingConfigImpl config = + context.configMap + .computeIfAbsent(readInt(reader, OBJECT_ID_FIELD), new IntObjectMap.SimpleObjectFactory() { + @Override + public AnnotationProcessingConfigImpl create() { + List args = readStringList(reader); + Set files = readStringSet(reader); + return new AnnotationProcessingConfigImpl(files, args); + } + }); + reader.stepOut(); + return config; } @Override @@ -53,10 +157,15 @@ public class AnnotationProcessingModelSerializationService implements Serializat } private static class WriteContext { + private final ObjectCollector objectCollector = + new ObjectCollector(); + private final ObjectCollector configCollector = + new ObjectCollector(); } private static class ReadContext { - + private final IntObjectMap objectMap = new IntObjectMap(); + private final IntObjectMap configMap = new IntObjectMap(); } } diff --git a/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/serialization/ToolingSerializerTest.kt b/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/serialization/ToolingSerializerTest.kt index 7011047eeb2c..b0d43ce43f49 100644 --- a/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/serialization/ToolingSerializerTest.kt +++ b/plugins/gradle/tooling-extension-impl/testSources/org/jetbrains/plugins/gradle/tooling/serialization/ToolingSerializerTest.kt @@ -13,6 +13,7 @@ import org.jetbrains.plugins.gradle.model.DefaultExternalProjectDependency import org.jetbrains.plugins.gradle.model.DefaultGradleExtensions import org.jetbrains.plugins.gradle.model.ExternalTask import org.jetbrains.plugins.gradle.model.tests.DefaultExternalTestsModel +import org.jetbrains.plugins.gradle.tooling.internal.AnnotationProcessingModelImpl import org.jetbrains.plugins.gradle.tooling.internal.BuildScriptClasspathModelImpl import org.jetbrains.plugins.gradle.tooling.internal.RepositoriesModelImpl import org.jetbrains.plugins.gradle.tooling.serialization.internal.IdeaProjectSerializationService @@ -121,6 +122,12 @@ class ToolingSerializerTest { }, serializer) } + @Test + @Throws(Exception::class) + fun `annotation processing model serialization test`() { + doTest(AnnotationProcessingModelImpl::class.java) + } + @Throws(IOException::class) private fun doTest(modelClazz: Class) { doTest(modelClazz, null) @@ -166,7 +173,7 @@ class ToolingSerializerTest { } else { gradleProject.parent = parentGradleProject - gradleProject.setChildren(emptyList()); + gradleProject.setChildren(emptyList()) } }