Commit 366f7db5 authored by Evan W. Patton's avatar Evan W. Patton Committed by Jeffrey Schiller

Merge annotation processors into a single step

Change-Id: I0c25b6a01f60830908058bdab1866c12314e642e
parent 9ae9b122
......@@ -73,10 +73,7 @@
<target name="CheckDocs">
<uptodate property="Docs.uptodate">
<srcfiles dir="${appinventor.dir}/docs/markdown">
<exclude name="_layouts/*" />
<exclude name="Gemfile*" />
<exclude name="_config.yml" />
<exclude name=".sass-cache/**/*" />
<include name="reference/**/*" />
</srcfiles>
<firstmatchmapper>
<globmapper from="*.md" to="${appinventor.dir}/docs/html/*.html" />
......@@ -88,7 +85,7 @@
<!-- =====================================================================
Builds the documentation from the corresponding Markdown files.
===================================================================== -->
<target name="BuildDocs" depends="components_Markdown,CheckDocs"
<target name="BuildDocs" depends="components_AndroidRuntime,CheckDocs"
unless="Docs.uptodate">
<!-- Jenkins will pass -Dforce.builddocs=true to ensure docs build correctly -->
<property name="force.builddocs" value="false" />
......@@ -498,7 +495,7 @@
===================================================================== -->
<target name="AiClientLib"
description="App Inventor Client library - compile java source to bytecode"
depends="common_CommonUtils,common_CommonVersion,components_CommonConstants,components_JsonComponentDescription,components_ComponentTranslation">
depends="components_AndroidRuntime">
<mkdir dir="${build.war.dir}/WEB-INF/classes"/>
<ai.javac encoding="utf-8"
destdir="${build.war.dir}/WEB-INF/classes"
......
......@@ -17,13 +17,13 @@
In-browser blocks editor for App Inventor based on Blockly
</description>
<target name="all"
depends="BlocklyCompile, BlocklyTestbed">
</target>
<target name="all"
depends="BlocklyCompile">
</target>
<target name="tests"
depends="BlocklyeditorTests">
</target>
<target name="tests"
depends="BlocklyTestbed, BlocklyeditorTests">
</target>
<!-- =====================================================================
Import common directory, task, and target definitions.
......@@ -81,7 +81,7 @@
<target name="BlocklyTestbed"
description="Testbed for blockly code generation. To use this, open blocklyeditor/src/demos/yail/index.html (using a file:/// url) in a browser"
depends="components_JsonComponentDescription, common_CommonTestUtils">
depends="components_AndroidRuntime, common_CommonTestUtils">
<mkdir dir="${run.lib.dir}" />
<echo message="var componentTypeJson = " file="${public.build.dir}/component-types.js" />
......
......@@ -272,16 +272,6 @@
<!-- targets that build dependencies -->
<!-- ====================================================================
blockseditor_BlocksEditor builds:
- build/blockseditor/BlocksEditor.jar
==================================================================== -->
<target name="blockseditor_BlocksEditor">
<ant inheritAll="false" useNativeBasedir="true" dir="${appinventor.dir}/blockseditor"
target="BlocksEditor"/>
</target>
<!-- ====================================================================
blocklyeditor_BlocklyCompile builds:
- build/blockly-all.js
......@@ -292,41 +282,6 @@
target="BlocklyCompile"/>
</target>
<!-- ====================================================================
components_ComponentTranslation builds:
common/build/src/com/google/appinventor/ComponentsTranslation.java
==================================================================== -->
<target name="components_ComponentTranslation">
<ant inheritAll="false" useNativeBaseDir="true" dir="${appinventor.dir}/components"
target="ComponentTranslation"/>
</target>
<target name="components_Markdown">
<ant inheritAll="false" useNativeBaseDir="true" dir="${appinventor.dir}/components"
target="Markdown"/>
</target>
<!-- ====================================================================
buildserver_StarterApp builds:
- build/buildserver/AppInventorPhoneApp.apk
==================================================================== -->
<target name="buildserver_StarterApp">
<ant inheritAll="false" useNativeBasedir="true" dir="${appinventor.dir}/buildserver"
target="StarterApp"/>
</target>
<!-- ====================================================================
common_CommonTranslations builds:
- build/common/CommonTranslations.jar
==================================================================== -->
<target name="common_CommonTranslations">
<ant inheritAll="false" useNativeBasedir="true" dir="${appinventor.dir}/common"
target="CommonTranslations"/>
</target>
<!-- ====================================================================
common_CommonUtils builds:
- build/common/CommonUtils.jar
......@@ -369,16 +324,6 @@
target="AndroidRuntime"/>
</target>
<!-- ====================================================================
components_Barcode builds:
- build/components/Barcode.jar
==================================================================== -->
<target name="components_Barcode">
<ant inheritAll="false" useNativeBasedir="true" dir="${appinventor.dir}/components"
target="Barcode"/>
</target>
<!-- ====================================================================
components_CommonConstants builds:
- build/components/CommonConstants.jar
......@@ -390,25 +335,4 @@
target="CommonConstants"/>
</target>
<!-- ====================================================================
components_ComponentList builds:
- build/components/simple_components.txt
- build/components/simple_components_build_info.json
==================================================================== -->
<target name="components_ComponentList">
<ant inheritAll="false" useNativeBasedir="true" dir="${appinventor.dir}/components"
target="ComponentList"/>
</target>
<!-- ====================================================================
components_JsonComponentDescription builds:
- build/components/simple_components.json
==================================================================== -->
<target name="components_JsonComponentDescription">
<ant inheritAll="false" useNativeBasedir="true" dir="${appinventor.dir}/components"
target="JsonComponentDescription"/>
</target>
</project>
......@@ -48,8 +48,7 @@
the jars needed to compile the build server classes.
===================================================================== -->
<target name="BuildServer"
depends="init,CopyToRunLibDir,components_AndroidRuntime,components_Barcode,components_ComponentList,
components_JsonComponentDescription">
depends="init,CopyToRunLibDir,components_AndroidRuntime">
<property name="BuildServer-class.dir" location="${class.dir}/BuildServer" />
<mkdir dir="${BuildServer-class.dir}" />
......@@ -65,7 +64,7 @@
<copy todir="${classes.files.dir}" flatten="true">
<fileset dir="${src.dir}/${buildserver.pkg}/resources" includes="*"/>
<fileset dir="${build.dir}/components"
includes="AndroidRuntime.jar,Barcode.jar,simple_components.txt,simple_components_build_info.json,simple_components.json"/>
includes="AndroidRuntime.jar,simple_components.txt,simple_components_build_info.json,simple_components.json"/>
<!-- Map assets for build server -->
<fileset dir="${lib.dir}/leaflet" includes="leaflet.js,leaflet.css" />
<fileset dir="${lib.dir}/leaflet/assets" includes="*"/>
......
......@@ -13,7 +13,7 @@
</description>
<target name="all"
depends="CommonUtils,CommonVersion,CommonTestUtils">
depends="CommonUtils,CommonVersion">
</target>
<target name="tests"
......@@ -60,24 +60,6 @@
</target>
<!-- =====================================================================
CommonTranslations: library containing translation classes.
===================================================================== -->
<target name="CommonTranslations"
description="Generate library containing translation classes"
depends="init">
<property name="CommonTranslations-class.dir" location="${class.dir}/CommonTranslations" />
<mkdir dir="${CommonTranslations-class.dir}" />
<ai.javac destdir="${CommonTranslations-class.dir}">
<include name="${common.pkg}/translations/*.java" />
</ai.javac>
<jar destfile="${public.build.dir}/CommonTranslations.jar">
<fileset dir="${CommonTranslations-class.dir}"/>
</jar>
</target>
<!-- =====================================================================
CommonUtilsTests: build and run the CommonUtils tests and generate the output results
===================================================================== -->
......
......@@ -13,9 +13,7 @@
</description>
<target name="all"
depends="CommonConstants,AndroidRuntime,
JsonComponentDescription,
ComponentList,ComponentTranslation,Barcode">
depends="CommonConstants,AndroidRuntime">
</target>
<target name="tests"
......@@ -118,6 +116,7 @@
===================================================================== -->
<property name="public.deps.dir" location="${public.build.dir}/deps" />
<target name="CopyComponentLibraries"
depends="Barcode"
description="Copies libraries needed for components into the public build directory">
<property name="support.dir" location="${lib.dir}/android/support" />
<property name="support.version" value="28.0.0" />
......@@ -181,13 +180,32 @@
<pathelement location="${public.build.dir}/CommonConstants.jar" />
</path>
<target name="AndroidRuntime.uptodate">
<uptodate property="AndroidRuntime.uptodate" targetfile="${public.build.dir}/AndroidRuntime.jar">
<srcfiles dir="${src.dir}" includes="**/*.java" />
<srcfiles dir="${public.deps.dir}" includes="*" />
</uptodate>
</target>
<!-- =====================================================================
AndroidRuntime: library providing runtime support for components
===================================================================== -->
<property name="AndroidRuntime-class.dir" location="${class.dir}/AndroidRuntime" />
<target name="AndroidRuntime"
description="Generate runtime library implementing components"
depends="CommonConstants,HtmlEntities,common_CommonVersion,CopyComponentLibraries">
unless="AndroidRuntime.uptodate"
depends="common_CommonVersion,HtmlEntities,CopyComponentLibraries,AnnotationProcessors,AndroidRuntime.uptodate">
<mkdir dir="${AndroidRuntime-class.dir}" />
<!-- We need to delete all the classes before running javac below. Otherwise, javac will only
process the Java files whose classes are not up-to-date and we'll end up with only a subset
of the results. For example, if only Label.java was modified, our annotation processor code
will only be executed for Label.java and we'll only have results for Label.java. -->
<delete>
<fileset dir="${AndroidRuntime-class.dir}">
<include name="**/*"/>
</fileset>
</delete>
<mkdir dir="${AndroidRuntime-class.dir}" />
<ai.javac destdir="${AndroidRuntime-class.dir}">
......@@ -195,10 +213,9 @@
<exclude name="${zxing.pkg}/**/*.java" /> <!-- exclude zxing package -->
<exclude name="${components.pkg}/scripts/**/*.java" /> <!-- exclude components/script package -->
<exclude name="${components.pkg}/common/**/*.java" /> <!-- exclude components/common package -->
<!--<include name="${components.pkg}/annotations/*.java" /> -->
<!--<include name="${components.pkg}/runtime/**/*.java" /> -->
<classpath>
<path refid="AndroidRuntime.path" />
<pathelement location="${local.build.dir}/AnnotationProcessors.jar" />
<pathelement location="${public.deps.dir}/android.jar" />
</classpath>
</ai.javac>
......@@ -208,7 +225,35 @@
<zipfileset src="${local.build.dir}/HtmlEntities.jar"/>
<zipfileset src="${public.build.dir}/CommonConstants.jar"/>
<zipfileset src="${build.dir}/common/CommonVersion.jar" />
<exclude name="simple_components.json"/>
<exclude name="simple_components_build_info.json"/>
<exclude name="simple_components.txt"/>
<exclude name="component-doc.html"/>
<exclude name="ComponentsTranslation.java"/>
<exclude name="AutogeneratedOdeMessages.java"/>
</jar>
<!-- Move AnnotationProcessor products into place -->
<copy todir="${public.build.dir}">
<fileset dir="${AndroidRuntime-class.dir}">
<include name="simple_components.txt" />
<include name="simple_components.json" />
<include name="simple_components_build_info.json" />
<include name="component-doc.html" />
</fileset>
</copy>
<mkdir dir="${public.build.dir}/ComponentTranslation/src/com/google/appinventor/client"/>
<copy todir="${public.build.dir}/ComponentTranslation/src/com/google/appinventor/client">
<fileset dir="${AndroidRuntime-class.dir}">
<include name="*.java"/>
</fileset>
</copy>
<copy todir="${appinventor.dir}/docs/markdown/reference/components/">
<fileset dir="${AndroidRuntime-class.dir}">
<include name="*.md" />
<exclude name="internal.md" />
</fileset>
</copy>
</target>
<!-- =====================================================================
......@@ -251,107 +296,6 @@
</ai.dojunit>
</target>
<!-- =====================================================================
Define task ai.apt for running the annotation processor.
This is based on the "javac" task instead of the "apt" task because
the apt task does not offer any useful additional tags. We don't use
the "ai.javac" task here because it does dependancy checking that is
not appropriate for annotation processing.
===================================================================== -->
<macrodef name="ai.apt">
<attribute name="apt-classdir" />
<attribute name="apt-processor" />
<attribute name="apt-target" />
<sequential>
<mkdir dir="@{apt-classdir}" />
<!-- Look at all source files to determine whether the target is up-to-date. This will catch
changes to the Java files in the annotations, common, runtime, and scripts packages and .txt
files in scripts/templates. -->
<uptodate property="target.uptodate" targetfile="@{apt-target}">
<srcfiles dir="${src.dir}" />
</uptodate>
<!-- We need to delete all the classes before running javac below. Otherwise, javac will only
process the Java files whose classes are not up-to-date and we'll end up with only a subset
of the results. For example, if only Label.java was modified, our annotation processor code
will only be executed for Label.java and we'll only have results for Label.java. -->
<delete>
<fileset dir="@{apt-classdir}">
<include name="**/*" unless="target.uptodate"/>
</fileset>
</delete>
<javac destdir="@{apt-classdir}"
encoding="utf-8"
sourcepath=""
source="7"
target="7"
srcdir="${src.dir}"
includeantruntime="false">
<include name="**/*.java" /> <!-- include all java files -->
<exclude name="${zxing.pkg}/**/*.java" /> <!-- exclude zxing package -->
<exclude name="${components.pkg}/scripts/**/*.java" /> <!-- exclude components/script package -->
<exclude name="${components.pkg}/common/**/*.java" /> <!-- exclude components/common package -->
<exclude name="${components.pkg}/annotations/**/*.java" /> <!-- exclude components/annotations package -->
<classpath>
<path refid="AndroidRuntime.path" />
<pathelement location="${public.build.dir}/AndroidRuntime.jar" />
<pathelement location="${public.deps.dir}/android.jar" />
</classpath>
<compilerarg line="-processorpath ${local.build.dir}/AnnotationProcessors.jar"/>
<compilerarg line="-processor @{apt-processor}" />
</javac>
</sequential>
</macrodef>
<!-- =====================================================================
ComponentProcessingLib: common library for annotation processors that
run over the components.
===================================================================== -->
<target name="ComponentProcessingLib"
description="Generate library for component annotation processors"
depends="CommonConstants">
<property name="ComponentProcessingLib-class.dir"
location="${class.dir}/ComponentProcessingLib" />
<mkdir dir="${ComponentProcessingLib-class.dir}" />
<ai.javac destdir="${ComponentProcessingLib-class.dir}"
source="1.7" target="1.7">
<include name="${components.pkg}/scripts/ComponentProcessor.java" />
<include name="${components.pkg}/annotations/*.java" />
<include name="${components.pkg}/annotations/androidmanifest/*.java" />
<classpath>
<pathelement location="${public.build.dir}/CommonConstants.jar" />
<pathelement location="${lib.dir}/guava/guava-14.0.1.jar" />
</classpath>
</ai.javac>
<jar basedir="${ComponentProcessingLib-class.dir}"
destfile="${local.build.dir}/ComponentProcessingLib.jar" />
</target>
<target name="CheckAnnotationProcessors"
description="Tests whether or not the annotation processors need to be recompiled.">
<uptodate property="AnnotationProcessors.uptodate"
targetfile="${local.build.dir}/AnnotationProcessors.jar">
<srcfiles dir="${src.dir}">
<include name="${components.pkg}/scripts/*.java" />
</srcfiles>
<srcfiles dir="${local.build.dir}">
<filename name="ComponentProcessingLib.jar"/>
<filename name="HtmlEntities.jar"/>
</srcfiles>
<srcfiles dir="${public.build.dir}">
<filename name="CommonConstants.jar"/>
</srcfiles>
<srcfiles dir="${build.dir}/common">
<filename name="CommonUtils.jar"/>
</srcfiles>
<srcfiles dir="${lib.dir}/guava">
<filename name="guava-14.0.1.jar"/>
</srcfiles>
</uptodate>
</target>
<!-- =====================================================================
AnnotationProcessors: plugins for processing component annotations
Note that AnnotationProcessors.jar, produced here, will contain all
......@@ -360,8 +304,7 @@
===================================================================== -->
<target name="AnnotationProcessors"
description="Create plugins for annotation processing"
depends="ComponentProcessingLib,CommonConstants,HtmlEntities,common_CommonUtils,CheckAnnotationProcessors"
unless="AnnotationProcessors.uptodate">
depends="common_CommonUtils,CommonConstants">
<property name="AnnotationProcessors-class.dir"
location="${class.dir}/AnnotationProcessors" />
......@@ -370,13 +313,13 @@
<ai.javac destdir="${AnnotationProcessors-class.dir}"
source="1.7" target="1.7">
<include name="${components.pkg}/scripts/*.java" />
<exclude name="${components.pkg}/scripts/ExternalComponentGenerator.java" />
<include name="${components.pkg}/annotations/*.java" />
<include name="${components.pkg}/annotations/androidmanifest/*.java" />
<classpath>
<pathelement location="${local.build.dir}/ComponentProcessingLib.jar"/>
<pathelement location="${local.build.dir}/HtmlEntities.jar" />
<pathelement location="${public.build.dir}/CommonConstants.jar" />
<pathelement location="${build.dir}/common/CommonUtils.jar" />
<pathelement location="${lib.dir}/guava/guava-14.0.1.jar" />
<pathelement location="${lib.dir}/json/json.jar" />
</classpath>
</ai.javac>
......@@ -388,107 +331,17 @@
<jar basedir="${AnnotationProcessors-class.dir}"
destfile="${local.build.dir}/AnnotationProcessors.jar" >
<zipfileset src="${local.build.dir}/ComponentProcessingLib.jar"/>
<zipfileset src="${local.build.dir}/HtmlEntities.jar"/>
<zipfileset src="${public.build.dir}/CommonConstants.jar"/>
<zipfileset src="${build.dir}/common/CommonUtils.jar" />
<zipfileset src="${lib.dir}/guava/guava-14.0.1.jar" />
<zipfileset src="${lib.dir}/json/json.jar" />
<fileset dir="${src.dir}">
<include name="META-INF/**/*"/>
</fileset>
</jar>
</target>
<!-- =====================================================================
JsonComponentDescription: create simple_components.json.
===================================================================== -->
<target name="JsonComponentDescription"
description="Make simple_components.json."
depends="AnnotationProcessors,AndroidRuntime,HtmlEntities,CommonConstants,common_CommonUtils">
<property name="JsonComponentDescription-class.dir"
location="${class.dir}/JsonComponentDescription" />
<ai.apt apt-classdir="${JsonComponentDescription-class.dir}"
apt-processor="com.google.appinventor.components.scripts.ComponentDescriptorGenerator"
apt-target="${JsonComponentDescription-class.dir}/simple_components.json"/>
<copy file="${JsonComponentDescription-class.dir}/simple_components.json"
todir="${public.build.dir}"/>
</target>
<!-- =====================================================================
ComponentList: create simple_components.txt and
simple_components_build_info.json
===================================================================== -->
<target name="ComponentList"
description="Make simple_components.txt and simple_components_build_info.json."
depends="AnnotationProcessors,AndroidRuntime,HtmlEntities,CommonConstants,Barcode">
<property name="ComponentList-class.dir" location="${class.dir}/ComponentList" />
<mkdir dir="${ComponentList-class.dir}" />
<ai.apt apt-classdir="${ComponentList-class.dir}"
apt-processor="com.google.appinventor.components.scripts.ComponentListGenerator"
apt-target="${ComponentList-class.dir}/simple_components.txt"/>
<copy file="${ComponentList-class.dir}/simple_components.txt"
todir="${public.build.dir}"/>
<copy file="${ComponentList-class.dir}/simple_components_build_info.json"
todir="${public.build.dir}"/>
</target>
<!-- =====================================================================
ComponentTranslation: create ComponentsTranslation.java
===================================================================== -->
<target name="ComponentTranslation"
description="Build ComponentsTranslation.java at build time
from annotations"
depends="AnnotationProcessors,AndroidRuntime,HtmlEntities,CommonConstants">
<property name="ComponentTranslation-class.dir" location="${class.dir}/ComponentTranslation" />
<mkdir dir="${ComponentTranslation-class.dir}" />
<ai.apt apt-classdir="${ComponentTranslation-class.dir}"
apt-processor="com.google.appinventor.components.scripts.ComponentTranslationGenerator"
apt-target="${ComponentTranslation-class.dir}/ComponentsTranslation.java"/>
<copy file="${ComponentTranslation-class.dir}/ComponentsTranslation.java"
todir="${public.build.dir}/ComponentTranslation/src/com/google/appinventor/client/" />
<copy file="${ComponentTranslation-class.dir}/AutogeneratedOdeMessages.java"
todir="${public.build.dir}/ComponentTranslation/src/com/google/appinventor/client/" />
</target>
<!-- =====================================================================
ComponentDocumentation: create component documentation from source
===================================================================== -->
<target name="ComponentDocumentation"
description="Make component documentation from source annotations."
depends="AnnotationProcessors,AndroidRuntime,HtmlEntities,CommonConstants">
<property name="ComponentDocumentation-class.dir"
location="${class.dir}/ComponentDocumentation" />
<mkdir dir="${ComponentDocumentation-class.dir}" />
<ai.apt apt-classdir="${ComponentDocumentation-class.dir}"
apt-processor="com.google.appinventor.components.scripts.DocumentationGenerator"
apt-target="${ComponentDocumentation-class.dir}/component-doc.html"/>
<copy file="${ComponentDocumentation-class.dir}/component-doc.html"
todir="${public.build.dir}"/>
</target>
<target name="Markdown"
depends="AnnotationProcessors,AndroidRuntime">
<property name="ComponentDocumentation-class.dir"
location="${class.dir}/ComponentDocumentation" />
<mkdir dir="${ComponentDocumentation-class.dir}" />
<ai.apt apt-classdir="${ComponentDocumentation-class.dir}"
apt-processor="com.google.appinventor.components.scripts.MarkdownDocumentationGenerator"
apt-target="${ComponentDocumentation-class.dir}"/>
<copy todir="${appinventor.dir}/docs/markdown/reference/components/">
<fileset dir="${ComponentDocumentation-class.dir}">
<include name="*.md" />
<exclude name="internal.md" />
</fileset>
</copy>
</target>
<!-- ======================================================================
Internal Inclusion of ZXing 2.1
====================================================================== -->
......@@ -498,10 +351,6 @@
===================================================================== -->
<property name="barcode.pkg" value="com/google/zxing/client/android" />
<!-- =====================================================================
OpenBlocks: library containing openblocks code
===================================================================== -->
<target name="Barcode"
depends=""
description="Generate ZXing embedded library">
......@@ -517,7 +366,7 @@
</ai.javac>
<jar basedir="${Barcode-class.dir}"
destfile="${public.build.dir}/Barcode.jar" />
destfile="${public.deps.dir}/Barcode.jar" />
</target>
......@@ -527,7 +376,7 @@
===================================================================== -->
<target name="ExternalComponentGenerator"
description="generate extension files"
depends="AndroidRuntime, JsonComponentDescription, ComponentList">
depends="AndroidRuntime">
<mkdir dir="${ExternalComponentGenerator-class.dir}" />
<mkdir dir="${ExternalComponent.dir}" />
<mkdir dir="${ExternalComponent-class.dir}" />
......
com.google.appinventor.components.scripts.ComponentDescriptorGenerator
com.google.appinventor.components.scripts.ComponentListGenerator
com.google.appinventor.components.scripts.ComponentTranslationGenerator
com.google.appinventor.components.scripts.MarkdownDocumentationGenerator
......@@ -52,6 +52,7 @@ import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.AnnotationValueVisitor;
......@@ -862,6 +863,11 @@ public abstract class ComponentProcessor extends AbstractProcessor {
return SUPPORTED_ANNOTATION_TYPES;
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.RELEASE_7;
}
@Override
public void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
......@@ -935,8 +941,8 @@ public abstract class ComponentProcessor extends AbstractProcessor {
throw new RuntimeException(e);
}
// Indicate that we have successfully handled the annotations.
return true;
// We need to return false here so that sibling annotation processors can run
return false;
}
/*
......
......@@ -19,3 +19,5 @@ out/
*.pyc
.vagrant/
*.log
.build/
.jekyll-cache/
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment