|
13 | 13 | * See the License for the specific language governing permissions and |
14 | 14 | * limitations under the License. |
15 | 15 | */ |
| 16 | +//file:noinspection GrMethodMayBeStatic |
| 17 | +//file:noinspection GrMethodMayBeStatic |
16 | 18 | package org.jamplate.gradle |
17 | 19 |
|
18 | | -import org.jamplate.model.Compilation |
19 | | -import org.jamplate.model.Memory |
20 | | -import org.jamplate.model.Value |
21 | | -import org.json.JSONArray |
22 | | -import org.json.JSONObject |
| 20 | +import org.gradle.api.Project |
| 21 | +import org.gradle.api.file.SourceDirectorySet |
| 22 | +import org.gradle.api.model.ObjectFactory |
| 23 | +import org.gradle.api.plugins.JavaPluginConvention |
| 24 | +import org.gradle.api.tasks.SourceSet |
| 25 | +import org.jamplate.diagnostic.Diagnostic |
| 26 | +import org.jamplate.diagnostic.Message |
| 27 | +import org.jamplate.glucose.internal.memory.Address |
| 28 | +import org.jamplate.glucose.spec.GlucoseSpec |
| 29 | +import org.jamplate.impl.unit.Action |
| 30 | +import org.jamplate.impl.unit.UnitImpl |
| 31 | +import org.jamplate.unit.Unit |
23 | 32 |
|
24 | | -import java.util.function.Function |
| 33 | +import static org.jamplate.glucose.internal.util.Values.text |
| 34 | +import static org.jamplate.util.Specs.listener |
25 | 35 |
|
26 | 36 | class JamplateExtension { |
27 | | - Map<String, Object> defaultMemory = new HashMap<>() |
28 | | - Function<Compilation, Memory> memorySupplier |
| 37 | + Map<String, Unit> units = new HashMap<>() |
29 | 38 |
|
30 | | - void memory(String address, String value) { |
31 | | - defaultMemory.put(address, value) |
| 39 | + Project project |
| 40 | + |
| 41 | + /** |
| 42 | + * The factory passed by the plugin. |
| 43 | + * |
| 44 | + * @since 0.3.0 ~2021.07.11 |
| 45 | + */ |
| 46 | + ObjectFactory factory |
| 47 | + |
| 48 | + JamplateExtension(Project project, ObjectFactory factory) { |
| 49 | + Objects.requireNonNull(project, "project") |
| 50 | + Objects.requireNonNull(factory, "factory") |
| 51 | + this.project = project |
| 52 | + this.factory = factory |
32 | 53 | } |
33 | 54 |
|
34 | | - void memory(String address, Number number) { |
35 | | - defaultMemory.put(address, number) |
| 55 | + Unit unit( |
| 56 | + String module, |
| 57 | + taskName = defaultTaskName(module), |
| 58 | + input = defaultInputFile(module), |
| 59 | + output = defaultOutputFile(module) |
| 60 | + ) { |
| 61 | + return units.computeIfAbsent(module, { |
| 62 | + Unit unit = new UnitImpl(new GlucoseSpec()) |
| 63 | + |
| 64 | + unit.spec.add listener({ event -> |
| 65 | + if (event.action == Action.PRE_EXEC) { |
| 66 | + event.memory.set Address.PROJECT, text(input) |
| 67 | + event.memory.set Address.OUTPUT, text(output) |
| 68 | + } |
| 69 | + }) |
| 70 | + unit.spec.add(listener({ event -> |
| 71 | + if (event.action == Action.DIAGNOSTIC) { |
| 72 | + Diagnostic diagnostic = event.diagnostic |
| 73 | + |
| 74 | + if (!diagnostic.empty) { |
| 75 | + Message message = diagnostic.first() |
| 76 | + Throwable exception = message.exception |
| 77 | + |
| 78 | + diagnostic.flush(true) |
| 79 | + |
| 80 | + if (exception != null) |
| 81 | + throw exception |
| 82 | + } |
| 83 | + } |
| 84 | + })) |
| 85 | + |
| 86 | + //create the jamplate task |
| 87 | + project.tasks.create(taskName, ProcessJamplateTask) { |
| 88 | + it.input = input |
| 89 | + it.output = output |
| 90 | + it.unit = unit |
| 91 | + } |
| 92 | + |
| 93 | + return unit |
| 94 | + }) |
36 | 95 | } |
37 | 96 |
|
38 | | - void memory(String address, Closure value) { |
39 | | - defaultMemory.put address, (Value) { |
40 | | - memory -> |
41 | | - Object v = value(memory) |
| 97 | + void java( |
| 98 | + String module, |
| 99 | + taskName = defaultTaskName(module), |
| 100 | + input = defaultInputFile(module), |
| 101 | + output = defaultOutputFile(module) |
| 102 | + ) { |
| 103 | + SourceSet sourceSet = project.convention.getPlugin(JavaPluginConvention).sourceSets.getByName(module) |
| 104 | + |
| 105 | + //create new jamplates source set |
| 106 | + SourceDirectorySet jamSourceSet = |
| 107 | + factory |
| 108 | + .sourceDirectorySet( |
| 109 | + "${module}.jamplate", |
| 110 | + "Jamplate ${module} extends Java ${module}" |
| 111 | + ) |
| 112 | + .srcDir input |
| 113 | + |
| 114 | + //register the source set |
| 115 | + sourceSet.allSource.source jamSourceSet |
| 116 | + |
| 117 | + //register the source set as a java source |
| 118 | + sourceSet.allJava.source jamSourceSet |
42 | 119 |
|
43 | | - if (v instanceof Map) |
44 | | - return new JSONObject((Map) v).toString() |
45 | | - if (v instanceof Collection) |
46 | | - return new JSONArray((Collection) v).toString() |
47 | | - if (v instanceof String) |
48 | | - return v |
| 120 | + //register the folder containing the generated code as java source folder |
| 121 | + sourceSet.java.srcDir output |
49 | 122 |
|
50 | | - return String.valueOf(v) |
| 123 | + //make the java compile task run after the jamplate task |
| 124 | + project.tasks.named(sourceSet.compileJavaTaskName) { |
| 125 | + it.dependsOn taskName |
51 | 126 | } |
52 | 127 | } |
53 | 128 |
|
54 | | - void memory(String address, List value) { |
55 | | - defaultMemory.put(address, value) |
| 129 | + void source( |
| 130 | + String module, |
| 131 | + taskName = defaultTaskName(module), |
| 132 | + input = defaultInputFile(module), |
| 133 | + output = defaultOutputFile(module) |
| 134 | + ) { |
| 135 | + //create new jamplates source set |
| 136 | + factory |
| 137 | + .sourceDirectorySet( |
| 138 | + "${module}.jamplate", |
| 139 | + "Jamplate ${module}" |
| 140 | + ) |
| 141 | + .srcDir input |
| 142 | + |
| 143 | + project.tasks.named('build') { it.dependsOn(taskName) } |
| 144 | + } |
| 145 | + |
| 146 | + protected String defaultTaskName(String module) { |
| 147 | + return "process${module == "main" ? "" : camelCase(module)}Jamplate" |
56 | 148 | } |
57 | 149 |
|
58 | | - void memory(String address, Map value) { |
59 | | - defaultMemory.put(address, new JSONObject(value)) |
| 150 | + protected File defaultInputFile(String module) { |
| 151 | + return new File(project.projectDir, "src/$module/jamplate") |
60 | 152 | } |
61 | 153 |
|
62 | | - void memory(Map map) { |
63 | | - defaultMemory.putAll(map) |
| 154 | + protected File defaultOutputFile(String module) { |
| 155 | + return new File(project.buildDir, "jamplate/$module") |
64 | 156 | } |
65 | 157 |
|
66 | | - void replaceMemorySupplier(Function<Compilation, Memory> memorySupplier) { |
67 | | - this.memorySupplier = memorySupplier |
| 158 | + /** |
| 159 | + * Return the given {@code string} formatted as {@code camelCase}. |
| 160 | + * |
| 161 | + * @param string the string to be formatted as {@code camelCase}. |
| 162 | + * @return the given {@code string} formatted as {@code camelCase}. |
| 163 | + * @throws NullPointerException if the given {@code string} is null. |
| 164 | + * @since 0.0.1 ~2020.09.15 |
| 165 | + */ |
| 166 | + protected static String camelCase(String string) { |
| 167 | + Objects.requireNonNull(string, "string") |
| 168 | + return string.length() <= 1 ? |
| 169 | + string.toUpperCase() : |
| 170 | + string.substring(0, 1) |
| 171 | + .toUpperCase() + |
| 172 | + string.substring(1, string.length()) |
| 173 | + .toLowerCase() |
68 | 174 | } |
69 | 175 | } |
0 commit comments