Merge branch 'idea-facet'

This commit is contained in:
Alexey Andreev 2016-11-06 21:13:28 +03:00
commit 156e7c98ee
12 changed files with 271 additions and 97 deletions

View File

@ -22,23 +22,14 @@ import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
import org.jetbrains.jps.model.module.JpsModule;
public class TeaVMJpsConfiguration extends JpsElementBase<TeaVMJpsConfiguration> {
private static final JpsElementChildRole<TeaVMJpsConfiguration> ROLE = JpsElementChildRoleBase.create(
static final JpsElementChildRole<TeaVMJpsConfiguration> ROLE = JpsElementChildRoleBase.create(
"TeaVM configuration");
private boolean enabled;
private String mainClass;
private String targetDirectory;
private boolean minifying;
private boolean sourceMapsFileGenerated = true;
private boolean sourceFilesCopied = true;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getMainClass() {
return mainClass;
}
@ -97,7 +88,6 @@ public class TeaVMJpsConfiguration extends JpsElementBase<TeaVMJpsConfiguration>
@Override
public void applyChanges(@NotNull TeaVMJpsConfiguration modified) {
enabled = modified.enabled;
mainClass = modified.mainClass;
targetDirectory = modified.targetDirectory;
minifying = modified.minifying;

View File

@ -16,23 +16,33 @@
package org.teavm.idea.jps.model;
import com.intellij.util.xmlb.XmlSerializer;
import java.util.Objects;
import java.util.Arrays;
import java.util.List;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.model.JpsElement;
import org.jetbrains.jps.model.module.JpsModule;
import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
import org.jetbrains.jps.model.serialization.facet.JpsFacetConfigurationSerializer;
public class TeaVMModelSerializerService extends JpsModelSerializerExtension {
@NotNull
@Override
public void loadModuleOptions(@NotNull JpsModule module, @NotNull Element rootElement) {
rootElement.getChildren("component").stream()
.filter(child -> Objects.equals(child.getAttributeValue("name"), "teavm"))
.forEach(child -> readConfig(module, child));
public List<? extends JpsFacetConfigurationSerializer<?>> getFacetConfigurationSerializers() {
return Arrays.asList(serializer);
}
private void readConfig(@NotNull JpsModule module, @NotNull Element element) {
TeaVMJpsConfiguration config = XmlSerializer.deserialize(element, TeaVMJpsConfiguration.class);
assert config != null;
config.setTo(module);
JpsFacetConfigurationSerializer<TeaVMJpsConfiguration> serializer =
new JpsFacetConfigurationSerializer<TeaVMJpsConfiguration>(TeaVMJpsConfiguration.ROLE,
"teavm-js", "TeaVM (JS)") {
@Override
protected TeaVMJpsConfiguration loadExtension(@NotNull Element element, String s, JpsElement jpsElement,
JpsModule jpsModule) {
return XmlSerializer.deserialize(element, TeaVMJpsConfiguration.class);
}
@Override
protected void saveExtension(TeaVMJpsConfiguration configuration, Element element, JpsModule jpsModule) {
}
};
}

View File

@ -97,7 +97,7 @@ class TeaVMBuild {
storage = context.getProjectDescriptor().dataManager.getStorage(target, storageProvider);
TeaVMJpsConfiguration config = TeaVMJpsConfiguration.get(module);
if (config == null || !config.isEnabled()) {
if (config == null) {
return false;
}

View File

@ -21,7 +21,7 @@ import com.intellij.openapi.components.Storage;
import org.jetbrains.annotations.Nullable;
import org.teavm.idea.jps.model.TeaVMJpsConfiguration;
@State(name = "teavm", storages = @Storage(id = "other", file = "$MODULE_FILE$"))
@State(name = "teavm", storages = @Storage(value = "$MODULE_FILE$"))
public class TeaVMConfigurationStorage implements PersistentStateComponent<TeaVMJpsConfiguration> {
private TeaVMJpsConfiguration state = new TeaVMJpsConfiguration();

View File

@ -0,0 +1,26 @@
/*
* Copyright 2016 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;
import com.intellij.facet.Facet;
import com.intellij.openapi.module.Module;
import org.jetbrains.annotations.NotNull;
public class TeaVMFacet extends Facet<TeaVMFacetConfiguration> {
public TeaVMFacet(@NotNull Module module, @NotNull String name, @NotNull TeaVMFacetConfiguration configuration) {
super(TeaVMFacetType.getInstance(), module, name, configuration, null);
}
}

View File

@ -0,0 +1,57 @@
/*
* Copyright 2016 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;
import com.intellij.facet.FacetConfiguration;
import com.intellij.facet.ui.FacetEditorContext;
import com.intellij.facet.ui.FacetEditorTab;
import com.intellij.facet.ui.FacetValidatorsManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import org.jdom.Element;
import org.jetbrains.annotations.Nullable;
import org.teavm.idea.jps.model.TeaVMJpsConfiguration;
import org.teavm.idea.ui.TeaVMFacetEditorTab;
public class TeaVMFacetConfiguration implements FacetConfiguration, PersistentStateComponent<TeaVMJpsConfiguration> {
private TeaVMJpsConfiguration state = new TeaVMJpsConfiguration();
@Override
public FacetEditorTab[] createEditorTabs(FacetEditorContext editorContext,
FacetValidatorsManager validatorsManager) {
return new FacetEditorTab[] { new TeaVMFacetEditorTab(editorContext.getModule(), state) };
}
@Override
public void readExternal(Element element) throws InvalidDataException {
}
@Override
public void writeExternal(Element element) throws WriteExternalException {
}
@Nullable
@Override
public TeaVMJpsConfiguration getState() {
return state;
}
@Override
public void loadState(TeaVMJpsConfiguration state) {
this.state = state;
}
}

View File

@ -0,0 +1,64 @@
/*
* Copyright 2016 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;
import com.intellij.facet.Facet;
import com.intellij.facet.FacetType;
import com.intellij.facet.FacetTypeId;
import com.intellij.facet.FacetTypeRegistry;
import com.intellij.openapi.module.JavaModuleType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.util.IconLoader;
import javax.swing.Icon;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class TeaVMFacetType extends FacetType<TeaVMFacet, TeaVMFacetConfiguration> {
public static final FacetTypeId<TeaVMFacet> TYPE_ID = new FacetTypeId<>("teavm-js");
private static final Icon icon = IconLoader.getIcon("/teavm-16.png");
public TeaVMFacetType() {
super(TYPE_ID, "teavm-js", "TeaVM (JS)");
}
@Override
public TeaVMFacetConfiguration createDefaultConfiguration() {
return new TeaVMFacetConfiguration();
}
@Override
public TeaVMFacet createFacet(@NotNull Module module, String name, @NotNull TeaVMFacetConfiguration configuration,
@Nullable Facet underlyingFacet) {
return new TeaVMFacet(module, name, configuration);
}
@Override
public boolean isSuitableModuleType(ModuleType moduleType) {
return moduleType instanceof JavaModuleType;
}
@Nullable
@Override
public Icon getIcon() {
return icon;
}
@NotNull
public static TeaVMFacetType getInstance() {
return (TeaVMFacetType) FacetTypeRegistry.getInstance().findFacetType(TYPE_ID);
}
}

View File

@ -15,10 +15,9 @@
*/
package org.teavm.idea.maven;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.facet.FacetManager;
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleServiceManager;
import java.util.List;
import java.util.Map;
import org.jdom.Element;
@ -29,12 +28,11 @@ import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.project.MavenProjectChanges;
import org.jetbrains.idea.maven.project.MavenProjectsProcessorTask;
import org.jetbrains.idea.maven.project.MavenProjectsTree;
import org.teavm.idea.TeaVMConfigurationStorage;
import org.teavm.idea.TeaVMFacet;
import org.teavm.idea.TeaVMFacetType;
import org.teavm.idea.jps.model.TeaVMJpsConfiguration;
public class TeaVMMavenImporter extends MavenImporter {
private static final Logger logger = Logger.getInstance(TeaVMMavenImporter.class);
public TeaVMMavenImporter() {
super("org.teavm", "teavm-maven-plugin");
}
@ -49,41 +47,41 @@ public class TeaVMMavenImporter extends MavenImporter {
MavenRootModelAdapter rootModel, MavenProjectsTree mavenModel, MavenProject mavenProject,
MavenProjectChanges changes, Map<MavenProject, String> mavenProjectToModuleName,
List<MavenProjectsProcessorTask> postTasks) {
TeaVMConfigurationStorage configurationStorage = ModuleServiceManager.getService(module,
TeaVMConfigurationStorage.class);
if (configurationStorage == null) {
logger.warn("Could not load component to retrieve TeaVM build configuration");
return;
}
TeaVMJpsConfiguration configuration = configurationStorage.getState();
FacetManager facetManager = FacetManager.getInstance(module);
for (MavenPlugin mavenPlugin : mavenProject.getPlugins()) {
if (mavenPlugin.getGroupId().equals(myPluginGroupID)
&& mavenPlugin.getArtifactId().equals(myPluginArtifactID)) {
updateConfiguration(mavenPlugin, configuration);
updateConfiguration(mavenPlugin, facetManager, module);
}
}
}
configurationStorage.loadState(configuration);
}
private void updateConfiguration(MavenPlugin plugin, TeaVMJpsConfiguration configuration) {
private void updateConfiguration(MavenPlugin plugin, FacetManager facetManager, Module module) {
if (plugin.getConfigurationElement() != null) {
updateConfiguration(plugin.getConfigurationElement(), configuration);
updateConfiguration(plugin.getConfigurationElement(), facetManager, module);
}
for (MavenPlugin.Execution execution : plugin.getExecutions()) {
if (execution.getGoals().contains("compile")) {
if (execution.getConfigurationElement() != null) {
updateConfiguration(execution.getConfigurationElement(), configuration);
updateConfiguration(execution.getConfigurationElement(), facetManager, module);
}
break;
}
}
}
private void updateConfiguration(Element source, TeaVMJpsConfiguration configuration) {
configuration.setEnabled(true);
private void updateConfiguration(Element source, FacetManager facetManager, Module module) {
TeaVMFacet facet = facetManager.getFacetByType(TeaVMFacetType.TYPE_ID);
if (facet == null) {
TeaVMFacetType type = TeaVMFacetType.getInstance();
facet = new TeaVMFacet(module, "TeaVM (JS)", type.createDefaultConfiguration());
facetManager.addFacet(type, facet.getName(), facet);
}
TeaVMJpsConfiguration configuration = facet.getConfiguration().getState();
for (Element child : source.getChildren()) {
switch (child.getName()) {
case "sourceFilesCopied":
@ -103,5 +101,7 @@ public class TeaVMMavenImporter extends MavenImporter {
break;
}
}
facet.getConfiguration().loadState(configuration);
}
}

View File

@ -16,21 +16,21 @@
package org.teavm.idea.ui;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleServiceManager;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import javax.swing.JComponent;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.Nullable;
import org.teavm.idea.TeaVMConfigurationStorage;
import org.teavm.idea.jps.model.TeaVMJpsConfiguration;
public class TeaVMConfigurable implements Configurable {
private final Module module;
private TeaVMConfigurationPanel panel;
private TeaVMJpsConfiguration configuration;
public TeaVMConfigurable(Module module) {
public TeaVMConfigurable(Module module, TeaVMJpsConfiguration configuration) {
this.module = module;
this.configuration = configuration;
}
@Nls
@ -61,23 +61,12 @@ public class TeaVMConfigurable implements Configurable {
@Override
public void apply() throws ConfigurationException {
TeaVMJpsConfiguration config = new TeaVMJpsConfiguration();
panel.save(config);
TeaVMConfigurationStorage configStorage = ModuleServiceManager.getService(module,
TeaVMConfigurationStorage.class);
assert configStorage != null;
configStorage.loadState(config);
panel.save(configuration);
}
@Override
public void reset() {
if (panel == null) {
return;
}
TeaVMConfigurationStorage configStorage = ModuleServiceManager.getService(module,
TeaVMConfigurationStorage.class);
assert configStorage != null;
panel.load(configStorage.getState());
panel.load(configuration);
}
@Override

View File

@ -38,25 +38,19 @@ import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JPanel;
import org.teavm.idea.jps.model.TeaVMJpsConfiguration;
class TeaVMConfigurationPanel extends JPanel {
private final JCheckBox enabledCheckBox = new JCheckBox("TeaVM enabled for this module");
private final TextFieldWithBrowseButton mainClassField = new TextFieldWithBrowseButton(event -> chooseMainClass());
private final TextFieldWithBrowseButton targetDirectoryField = new TextFieldWithBrowseButton();
private final JComboBox<ComboBoxItem<Boolean>> minifyingField = new JComboBox<>(new DefaultComboBoxModel<>());
private final JComboBox<ComboBoxItem<Boolean>> sourceMapsField = new JComboBox<>(new DefaultComboBoxModel<>());;
private final JComboBox<ComboBoxItem<Boolean>> sourceMapsField = new JComboBox<>(new DefaultComboBoxModel<>());
private final JComboBox<ComboBoxItem<Boolean>> copySourcesField = new JComboBox<>(new DefaultComboBoxModel<>());
private final TeaVMJpsConfiguration initialConfiguration = new TeaVMJpsConfiguration();
private final Project project;
private final List<JComponent> editComponents = Arrays.asList(mainClassField, targetDirectoryField,
minifyingField, sourceMapsField, copySourcesField);
private final List<ComboBoxItem<Boolean>> minifiedOptions = Arrays.asList(new ComboBoxItem<>(false, "Readable"),
new ComboBoxItem<>(true, "Minified (obfuscated)"));
@ -67,8 +61,6 @@ class TeaVMConfigurationPanel extends JPanel {
new ComboBoxItem<>(false, "Skip"));
private final List<Field<?>> fields = Arrays.asList(
new Field<>(TeaVMJpsConfiguration::setEnabled, TeaVMJpsConfiguration::isEnabled,
enabledCheckBox::setSelected, enabledCheckBox::isSelected),
new Field<>(TeaVMJpsConfiguration::setMainClass, TeaVMJpsConfiguration::getMainClass,
mainClassField::setText, mainClassField::getText),
new Field<>(TeaVMJpsConfiguration::setTargetDirectory, TeaVMJpsConfiguration::getTargetDirectory,
@ -88,7 +80,6 @@ class TeaVMConfigurationPanel extends JPanel {
TeaVMConfigurationPanel(Project project) {
this.project = project;
enabledCheckBox.addActionListener(event -> updateEnabledState());
setupLayout();
FileChooserDescriptor targetDirectoryChooserDescriptor = FileChooserDescriptorFactory
@ -96,24 +87,14 @@ class TeaVMConfigurationPanel extends JPanel {
targetDirectoryField.addBrowseFolderListener("Target Directory", "Please, select folder where TeaVM should"
+ "write generated JS files", project, targetDirectoryChooserDescriptor);
minifiedOptions.stream().forEach(minifyingField::addItem);
sourceMapsOptions.stream().forEach(sourceMapsField::addItem);
copySourcesOptions.stream().forEach(copySourcesField::addItem);
minifiedOptions.forEach(minifyingField::addItem);
sourceMapsOptions.forEach(sourceMapsField::addItem);
copySourcesOptions.forEach(copySourcesField::addItem);
}
private void setupLayout() {
setLayout(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.gridwidth = GridBagConstraints.REMAINDER;
constraints.anchor = GridBagConstraints.BASELINE_LEADING;
constraints.insets.left = 5;
constraints.insets.right = 5;
constraints.insets.bottom = 25;
constraints.insets.top = 10;
constraints.weighty = 1;
add(enabledCheckBox, constraints);
GridBagConstraints labelConstraints = new GridBagConstraints();
labelConstraints.gridwidth = GridBagConstraints.REMAINDER;
labelConstraints.anchor = GridBagConstraints.BASELINE_LEADING;
@ -153,16 +134,17 @@ class TeaVMConfigurationPanel extends JPanel {
add(minifyingField, fieldConstraints);
add(bold(new JBLabel("Source maps")), labelConstraints);
add(new JBLabel("Indicates whether TeaVM should generate source maps. With source maps "
+ "you can debug code in the browser's devtools."), descriptionConstraints);
add(new JBLabel("Indicates whether TeaVM should generate source maps."), descriptionConstraints);
add(new JBLabel("With source maps you can debug code in the browser's devtools."), descriptionConstraints);
add(sourceMapsField, fieldConstraints);
add(bold(new JBLabel("Copy source code")), labelConstraints);
add(new JBLabel("Source maps require your server to provide source code."), descriptionConstraints);
add(new JBLabel("TeaVM can copy source code to the corresponding location, which is very convenient if "
+ "you are going to debug in the browser."), descriptionConstraints);
add(new JBLabel("TeaVM can copy source code to the corresponding location,"), descriptionConstraints);
add(new JBLabel("which is very convenient if you are going to debug in the browser."), descriptionConstraints);
add(copySourcesField, fieldConstraints);
GridBagConstraints constraints = new GridBagConstraints();
constraints.fill = GridBagConstraints.BOTH;
constraints.weighty = 100;
constraints.weightx = 1;
@ -182,7 +164,6 @@ class TeaVMConfigurationPanel extends JPanel {
for (Field<?> field : fields) {
loadField(field, config);
}
updateEnabledState();
}
void save(TeaVMJpsConfiguration config) {
@ -206,12 +187,6 @@ class TeaVMConfigurationPanel extends JPanel {
}
}
private void updateEnabledState() {
for (JComponent component : editComponents) {
component.setEnabled(enabledCheckBox.isSelected());
}
}
private <T> void copyField(Field<T> field, TeaVMJpsConfiguration config) {
field.dataConsumer.accept(initialConfiguration, field.dataSupplier.apply(config));
}

View File

@ -0,0 +1,64 @@
/*
* Copyright 2016 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.ui;
import com.intellij.facet.ui.FacetEditorTab;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.ConfigurationException;
import javax.swing.JComponent;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.teavm.idea.jps.model.TeaVMJpsConfiguration;
public class TeaVMFacetEditorTab extends FacetEditorTab {
private TeaVMConfigurable configurable;
public TeaVMFacetEditorTab(Module module, TeaVMJpsConfiguration configuration) {
configurable = new TeaVMConfigurable(module, configuration);
}
@NotNull
@Override
public JComponent createComponent() {
return configurable.createComponent();
}
@Nls
@Override
public String getDisplayName() {
return "General settings";
}
@Override
public boolean isModified() {
return configurable.isModified();
}
@Override
public void apply() throws ConfigurationException {
configurable.apply();
}
@Override
public void disposeUIResources() {
configurable.disposeUIResources();
}
@Override
public void reset() {
configurable.reset();
}
}

View File

@ -26,13 +26,12 @@
</application-components>
<extensions defaultExtensionNs="com.intellij">
<moduleConfigurable instance="org.teavm.idea.ui.TeaVMConfigurable"/>
<moduleService serviceInterface="org.teavm.idea.TeaVMConfigurationStorage"
serviceImplementation="org.teavm.idea.TeaVMConfigurationStorage"/>
<compileServer.plugin classpath="jps/teavm-jps-plugin.jar;teavm-all.jar;teavm-jps-common.jar"/>
<buildProcess.parametersProvider implementation="org.teavm.idea.TeaVMJPSConfigurator"/>
<configurationType implementation="org.teavm.idea.debug.TeaVMDebugConfigurationType"/>
<programRunner implementation="org.teavm.idea.debug.TeaVMDebugRunner"/>
<facetType implementation="org.teavm.idea.TeaVMFacetType"/>
</extensions>
<extensions defaultExtensionNs="org.jetbrains.idea.maven">