From 6653118dd8101381d78a766880dbda5d7ba39ccb Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Fri, 16 Jun 2017 00:57:06 +0300 Subject: [PATCH] Allow to edit TeaVM build properties from IDEA UI --- .../idea/jps/model/TeaVMBuildStrategy.java | 3 + .../idea/jps/model/TeaVMJpsConfiguration.java | 21 ++- .../teavm/idea/jps/model/TeaVMProperty.java | 50 +++++++ .../jps/remote/TeaVMRemoteBuildRequest.java | 2 + .../idea/jps/InProcessBuildStrategy.java | 10 ++ .../teavm/idea/jps/RemoteBuildStrategy.java | 7 + .../java/org/teavm/idea/jps/TeaVMBuild.java | 9 ++ .../teavm/idea/daemon/TeaVMBuildDaemon.java | 1 + .../teavm/idea/maven/TeaVMMavenImporter.java | 16 +++ .../idea/ui/TeaVMConfigurationPanel.java | 131 +++++++++++++++++- 10 files changed, 246 insertions(+), 4 deletions(-) create mode 100644 tools/idea/jps-common/src/main/java/org/teavm/idea/jps/model/TeaVMProperty.java diff --git a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/model/TeaVMBuildStrategy.java b/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/model/TeaVMBuildStrategy.java index c9cc9ca9e..168a666cb 100644 --- a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/model/TeaVMBuildStrategy.java +++ b/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/model/TeaVMBuildStrategy.java @@ -16,6 +16,7 @@ package org.teavm.idea.jps.model; import java.util.List; +import java.util.Properties; import org.teavm.tooling.TeaVMTargetType; import org.teavm.vm.TeaVMProgressListener; @@ -44,5 +45,7 @@ public interface TeaVMBuildStrategy { void setIncremental(boolean incremental); + void setProperties(Properties properties); + TeaVMBuildResult build(); } diff --git a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/model/TeaVMJpsConfiguration.java b/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/model/TeaVMJpsConfiguration.java index f8de6b826..407e8cc11 100644 --- a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/model/TeaVMJpsConfiguration.java +++ b/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/model/TeaVMJpsConfiguration.java @@ -15,10 +15,13 @@ */ package org.teavm.idea.jps.model; +import com.intellij.util.xmlb.annotations.AbstractCollection; +import com.intellij.util.xmlb.annotations.Tag; import com.intellij.util.xmlb.annotations.Transient; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.stream.Collectors; import org.jetbrains.annotations.NotNull; import org.jetbrains.jps.model.JpsElementChildRole; import org.jetbrains.jps.model.ex.JpsElementBase; @@ -38,9 +41,9 @@ public class TeaVMJpsConfiguration extends JpsElementBase private String mainClass; private String targetDirectory; - private boolean minifying; private boolean sourceMapsFileGenerated = true; private boolean sourceFilesCopied = true; + private List properties = new ArrayList<>(); public TeaVMTargetType getTargetType() { return targetType; @@ -82,6 +85,16 @@ public class TeaVMJpsConfiguration extends JpsElementBase this.sourceFilesCopied = sourceFilesCopied; } + @Tag("properties") + @AbstractCollection(surroundWithTag = false) + public List getProperties() { + return properties; + } + + public void setProperties(List properties) { + this.properties = properties; + } + public static List getAll(JpsModule module) { List configurations = new ArrayList<>(); for (JpsElementChildRole role : Arrays.asList(JS_ROLE, WEBASSEMBLY_ROLE)) { @@ -105,8 +118,12 @@ public class TeaVMJpsConfiguration extends JpsElementBase public void applyChanges(@NotNull TeaVMJpsConfiguration modified) { mainClass = modified.mainClass; targetDirectory = modified.targetDirectory; - minifying = modified.minifying; sourceMapsFileGenerated = modified.sourceMapsFileGenerated; sourceFilesCopied = modified.sourceFilesCopied; + + properties.clear(); + properties.addAll(modified.properties.stream() + .map(property -> property.createCopy()) + .collect(Collectors.toList())); } } diff --git a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/model/TeaVMProperty.java b/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/model/TeaVMProperty.java new file mode 100644 index 000000000..61f981a02 --- /dev/null +++ b/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/model/TeaVMProperty.java @@ -0,0 +1,50 @@ +/* + * Copyright 2017 Alexey Andreev. + * + * 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.teavm.idea.jps.model; + +import com.intellij.util.xmlb.annotations.Attribute; +import com.intellij.util.xmlb.annotations.Tag; + +@Tag("property") +public class TeaVMProperty { + private String key = ""; + private String value = ""; + + @Attribute("key") + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + @Attribute("value") + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public TeaVMProperty createCopy() { + TeaVMProperty copy = new TeaVMProperty(); + copy.key = key; + copy.value = value; + return copy; + } +} diff --git a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/remote/TeaVMRemoteBuildRequest.java b/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/remote/TeaVMRemoteBuildRequest.java index 79a921e99..67f7e86dc 100644 --- a/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/remote/TeaVMRemoteBuildRequest.java +++ b/tools/idea/jps-common/src/main/java/org/teavm/idea/jps/remote/TeaVMRemoteBuildRequest.java @@ -18,6 +18,7 @@ package org.teavm.idea.jps.remote; import java.io.Serializable; import java.util.ArrayList; import java.util.List; +import java.util.Properties; import org.teavm.tooling.TeaVMTargetType; public class TeaVMRemoteBuildRequest implements Serializable { @@ -31,4 +32,5 @@ public class TeaVMRemoteBuildRequest implements Serializable { public boolean debugInformationGenerated; public boolean sourceFilesCopied; public boolean incremental; + public Properties properties; } diff --git a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/InProcessBuildStrategy.java b/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/InProcessBuildStrategy.java index eb76477d7..77f4f8a16 100644 --- a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/InProcessBuildStrategy.java +++ b/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/InProcessBuildStrategy.java @@ -21,6 +21,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Properties; import java.util.Set; import java.util.stream.Collectors; import org.jetbrains.jps.incremental.CompileContext; @@ -50,6 +51,7 @@ public class InProcessBuildStrategy implements TeaVMBuildStrategy { private boolean sourceFilesCopied; private final List sourceFileProviders = new ArrayList<>(); private TeaVMProgressListener progressListener; + private Properties properties = new Properties(); public InProcessBuildStrategy(CompileContext context) { this.context = context; @@ -115,6 +117,12 @@ public class InProcessBuildStrategy implements TeaVMBuildStrategy { public void setIncremental(boolean incremental) { } + @Override + public void setProperties(Properties properties) { + this.properties.clear(); + this.properties.putAll(properties); + } + @Override public TeaVMBuildResult build() { TeaVMTool tool = new TeaVMTool(); @@ -131,6 +139,8 @@ public class InProcessBuildStrategy implements TeaVMBuildStrategy { tool.setMinifying(false); + tool.getProperties().putAll(properties); + for (SourceFileProvider fileProvider : sourceFileProviders) { tool.addSourceFileProvider(fileProvider); } diff --git a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/RemoteBuildStrategy.java b/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/RemoteBuildStrategy.java index de887b208..165211183 100644 --- a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/RemoteBuildStrategy.java +++ b/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/RemoteBuildStrategy.java @@ -19,6 +19,7 @@ import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import java.util.Collection; import java.util.List; +import java.util.Properties; import org.teavm.callgraph.CallGraph; import org.teavm.diagnostics.Problem; import org.teavm.diagnostics.ProblemProvider; @@ -102,6 +103,12 @@ public class RemoteBuildStrategy implements TeaVMBuildStrategy { request.incremental = incremental; } + @Override + public void setProperties(Properties properties) { + request.properties = new Properties(); + request.properties.putAll(properties); + } + @Override public TeaVMBuildResult build() { TeaVMRemoteBuildResponse response; diff --git a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/TeaVMBuild.java b/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/TeaVMBuild.java index 04bdd2d91..fec193394 100644 --- a/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/TeaVMBuild.java +++ b/tools/idea/jps-plugin/src/main/java/org/teavm/idea/jps/TeaVMBuild.java @@ -31,6 +31,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Properties; import java.util.Queue; import java.util.Set; import java.util.stream.Stream; @@ -59,6 +60,7 @@ import org.teavm.diagnostics.ProblemProvider; import org.teavm.idea.jps.model.TeaVMBuildResult; import org.teavm.idea.jps.model.TeaVMBuildStrategy; import org.teavm.idea.jps.model.TeaVMJpsConfiguration; +import org.teavm.idea.jps.model.TeaVMProperty; import org.teavm.idea.jps.remote.TeaVMBuilderAssistant; import org.teavm.idea.jps.remote.TeaVMElementLocation; import org.teavm.model.CallLocation; @@ -114,6 +116,13 @@ class TeaVMBuild { buildStrategy.setTargetDirectory(config.getTargetDirectory()); buildStrategy.setProgressListener(createProgressListener(context)); buildStrategy.setIncremental(!isRebuild(target)); + + Properties properties = new Properties(); + for (TeaVMProperty property : config.getProperties()) { + properties.put(property.getKey(), property.getValue()); + } + buildStrategy.setProperties(properties); + TeaVMBuildResult buildResult = buildStrategy.build(); if (!buildResult.isErrorOccurred() && buildResult.getProblems().getSevereProblems().isEmpty()) { diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/daemon/TeaVMBuildDaemon.java b/tools/idea/plugin/src/main/java/org/teavm/idea/daemon/TeaVMBuildDaemon.java index 798f01740..588eaba7c 100644 --- a/tools/idea/plugin/src/main/java/org/teavm/idea/daemon/TeaVMBuildDaemon.java +++ b/tools/idea/plugin/src/main/java/org/teavm/idea/daemon/TeaVMBuildDaemon.java @@ -181,6 +181,7 @@ public class TeaVMBuildDaemon extends UnicastRemoteObject implements TeaVMRemote tool.setSourceMapsFileGenerated(request.sourceMapsFileGenerated); tool.setDebugInformationGenerated(request.debugInformationGenerated); tool.setSourceFilesCopied(request.sourceFilesCopied); + tool.getProperties().putAll(request.properties); tool.setMinifying(false); diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/maven/TeaVMMavenImporter.java b/tools/idea/plugin/src/main/java/org/teavm/idea/maven/TeaVMMavenImporter.java index b25208505..ca3d8ddf7 100644 --- a/tools/idea/plugin/src/main/java/org/teavm/idea/maven/TeaVMMavenImporter.java +++ b/tools/idea/plugin/src/main/java/org/teavm/idea/maven/TeaVMMavenImporter.java @@ -20,6 +20,7 @@ import com.intellij.facet.FacetType; import com.intellij.facet.ModifiableFacetModel; import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider; import com.intellij.openapi.module.Module; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -37,6 +38,7 @@ import org.teavm.idea.TeaVMFacetConfiguration; import org.teavm.idea.TeaVMFacetType; import org.teavm.idea.TeaVMWebAssemblyFacetType; import org.teavm.idea.jps.model.TeaVMJpsConfiguration; +import org.teavm.idea.jps.model.TeaVMProperty; import org.teavm.tooling.TeaVMTargetType; public class TeaVMMavenImporter extends MavenImporter { @@ -127,12 +129,26 @@ public class TeaVMMavenImporter extends MavenImporter { case "mainClass": configuration.setMainClass(child.getTextTrim()); break; + case "properties": + configuration.setProperties(extractProperties(child)); + break; } } facet.getConfiguration().loadState(configuration); } + private List extractProperties(Element element) { + List properties = new ArrayList<>(); + for (Element child : element.getChildren()) { + TeaVMProperty property = new TeaVMProperty(); + property.setKey(child.getName()); + property.setValue(child.getTextTrim()); + properties.add(property); + } + return properties; + } + private TeaVMTargetType getTargetType(Element source) { for (Element child : source.getChildren()) { if (child.getName().equals("targetType")) { diff --git a/tools/idea/plugin/src/main/java/org/teavm/idea/ui/TeaVMConfigurationPanel.java b/tools/idea/plugin/src/main/java/org/teavm/idea/ui/TeaVMConfigurationPanel.java index 72ce92122..108ab053c 100644 --- a/tools/idea/plugin/src/main/java/org/teavm/idea/ui/TeaVMConfigurationPanel.java +++ b/tools/idea/plugin/src/main/java/org/teavm/idea/ui/TeaVMConfigurationPanel.java @@ -26,10 +26,16 @@ import com.intellij.openapi.util.Computable; import com.intellij.psi.PsiClass; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiMethodUtil; +import com.intellij.ui.IdeBorderFactory; +import com.intellij.ui.ToolbarDecorator; import com.intellij.ui.components.JBLabel; +import com.intellij.ui.table.JBTable; +import com.intellij.util.ui.EditableModel; +import java.awt.BorderLayout; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; @@ -37,16 +43,21 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; +import java.util.stream.Collectors; import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; import javax.swing.JPanel; +import javax.swing.table.AbstractTableModel; import org.teavm.idea.jps.model.TeaVMJpsConfiguration; +import org.teavm.idea.jps.model.TeaVMProperty; class TeaVMConfigurationPanel extends JPanel { private final TextFieldWithBrowseButton mainClassField = new TextFieldWithBrowseButton(event -> chooseMainClass()); private final TextFieldWithBrowseButton targetDirectoryField = new TextFieldWithBrowseButton(); private final JComboBox> sourceMapsField = new JComboBox<>(new DefaultComboBoxModel<>()); private final JComboBox> copySourcesField = new JComboBox<>(new DefaultComboBoxModel<>()); + private final JBTable propertiesTable = new JBTable(); + private final PropertiesModel propertiesModel = new PropertiesModel(); private final TeaVMJpsConfiguration initialConfiguration = new TeaVMJpsConfiguration(); private final Project project; @@ -73,6 +84,7 @@ class TeaVMConfigurationPanel extends JPanel { TeaVMConfigurationPanel(Project project) { this.project = project; + propertiesTable.setModel(propertiesModel); setupLayout(); FileChooserDescriptor targetDirectoryChooserDescriptor = FileChooserDescriptorFactory @@ -134,7 +146,12 @@ class TeaVMConfigurationPanel extends JPanel { constraints.fill = GridBagConstraints.BOTH; constraints.weighty = 100; constraints.weightx = 1; - add(new JPanel(), constraints); + + JPanel propertiesPanel = new JPanel(new BorderLayout()); + propertiesPanel.setBorder(IdeBorderFactory.createTitledBorder("Properties")); + propertiesPanel.add(ToolbarDecorator.createDecorator(propertiesTable).createPanel(), BorderLayout.CENTER); + + add(propertiesPanel, constraints); } private static JBLabel bold(JBLabel label) { @@ -150,27 +167,54 @@ class TeaVMConfigurationPanel extends JPanel { for (Field field : fields) { loadField(field, config); } + + copyProperties(config.getProperties(), propertiesModel.getProperties()); } void save(TeaVMJpsConfiguration config) { for (Field field : fields) { saveField(field, config); } + copyProperties(propertiesModel.getProperties(), config.getProperties()); updateInitialConfiguration(config); } boolean isModified() { - return fields.stream().anyMatch(this::isFieldModified); + return fields.stream().anyMatch(this::isFieldModified) || arePropertiesModified(); } private boolean isFieldModified(Field field) { return !Objects.equals(field.dataSupplier.apply(initialConfiguration), field.editSupplier.get()); } + private boolean arePropertiesModified() { + if (initialConfiguration.getProperties().size() != propertiesModel.getProperties().size()) { + return true; + } + + for (int i = 0; i < initialConfiguration.getProperties().size(); ++i) { + TeaVMProperty initialProperty = initialConfiguration.getProperties().get(i); + TeaVMProperty property = propertiesModel.getProperties().get(i); + if (!initialProperty.getKey().equals(property.getKey()) + || !initialProperty.getValue().equals(property.getValue())) { + return true; + } + } + + return false; + } + private void updateInitialConfiguration(TeaVMJpsConfiguration config) { for (Field field : fields) { copyField(field, config); } + + copyProperties(config.getProperties(), initialConfiguration.getProperties()); + } + + private void copyProperties(List from, List to) { + to.clear(); + to.addAll(from.stream().map(property -> property.createCopy()).collect(Collectors.toList())); } private void copyField(Field field, TeaVMJpsConfiguration config) { @@ -232,4 +276,87 @@ class TeaVMConfigurationPanel extends JPanel { this.editSupplier = editSupplier; } } + + class PropertiesModel extends AbstractTableModel implements EditableModel { + private List properties = new ArrayList<>(); + + List getProperties() { + return properties; + } + + @Override + public void addRow() { + properties.add(new TeaVMProperty()); + } + + @Override + public void exchangeRows(int oldIndex, int newIndex) { + TeaVMProperty old = properties.get(oldIndex); + properties.set(oldIndex, properties.get(newIndex)); + properties.set(newIndex, old); + } + + @Override + public boolean canExchangeRows(int oldIndex, int newIndex) { + return true; + } + + @Override + public void removeRow(int idx) { + properties.remove(idx); + } + + @Override + public int getRowCount() { + return properties.size(); + } + + @Override + public int getColumnCount() { + return 2; + } + + @Override + public String getColumnName(int column) { + switch (column) { + case 0: + return "Name"; + case 1: + return "Value"; + default: + throw new IllegalArgumentException(); + } + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + switch (columnIndex) { + case 0: + return properties.get(rowIndex).getKey(); + case 1: + return properties.get(rowIndex).getValue(); + default: + throw new IllegalArgumentException(); + } + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + switch (columnIndex) { + case 0: + properties.get(rowIndex).setKey((String) aValue); + break; + case 1: + properties.get(rowIndex).setValue((String) aValue); + break; + default: + throw new IllegalArgumentException(); + } + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + return true; + } + } }