mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-02-04 15:06:56 +07:00
IDEA-161641 - initial Jlink artifacts support
IDEA-161641 - moved jlink packages to java.impl and java.compiler.impl modules IDEA-161641 - small refactoring IDEA-161641 - small refactoring IDEA-161641 - fixed jlink tab ui, partially setup build task provider IDEA-161641 - initial jlink implementation GitOrigin-RevId: 2ce649f886ea43d362414d7b949f07feac5d231d
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b566b6e97d
commit
3ad3f5c6fe
@@ -0,0 +1,2 @@
|
||||
# Copyright 2000-2021 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.
|
||||
com.intellij.packaging.impl.jlink.JLinkArtifactBuildTaskProvider
|
||||
@@ -0,0 +1,2 @@
|
||||
# Copyright 2000-2021 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.
|
||||
com.intellij.packaging.impl.jlink.JpsJLinkModelSerializerExtension
|
||||
@@ -0,0 +1,191 @@
|
||||
// Copyright 2000-2021 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 com.intellij.packaging.impl.jlink;
|
||||
|
||||
import com.intellij.execution.CommandLineUtil;
|
||||
import com.intellij.execution.process.BaseOSProcessHandler;
|
||||
import com.intellij.execution.process.ProcessAdapter;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.execution.process.ProcessOutputTypes;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.NlsSafe;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.builders.artifacts.ArtifactBuildTaskProvider;
|
||||
import org.jetbrains.jps.incremental.BuildTask;
|
||||
import org.jetbrains.jps.incremental.CompileContext;
|
||||
import org.jetbrains.jps.incremental.ProjectBuildException;
|
||||
import org.jetbrains.jps.incremental.messages.BuildMessage;
|
||||
import org.jetbrains.jps.incremental.messages.CompilerMessage;
|
||||
import org.jetbrains.jps.model.JpsElement;
|
||||
import org.jetbrains.jps.model.artifact.JpsArtifact;
|
||||
import org.jetbrains.jps.model.library.sdk.JpsSdk;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class JLinkArtifactBuildTaskProvider extends ArtifactBuildTaskProvider {
|
||||
|
||||
@Override
|
||||
public @NotNull List<? extends BuildTask> createArtifactBuildTasks(@NotNull JpsArtifact artifact,
|
||||
@NotNull ArtifactBuildPhase buildPhase) {
|
||||
if (buildPhase != ArtifactBuildPhase.POST_PROCESSING || !(artifact.getArtifactType() instanceof JpsJLinkArtifactType)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final JpsElement properties = artifact.getProperties();
|
||||
if (!(properties instanceof JpsJLinkProperties)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Collections.singletonList(new JLinkBuildTask(artifact));
|
||||
}
|
||||
|
||||
private static class JLinkBuildTask extends BuildTask {
|
||||
private static final Logger LOG = Logger.getInstance(JLinkBuildTask.class);
|
||||
private final JpsArtifact myArtifact;
|
||||
|
||||
private JLinkBuildTask(@NotNull JpsArtifact artifact) {
|
||||
myArtifact = artifact;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(CompileContext context) throws ProjectBuildException {
|
||||
LOG.warn("jlink task was started");
|
||||
|
||||
Set<JpsSdk<?>> sdks = context.getProjectDescriptor().getProjectJavaSdks();
|
||||
if (sdks.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
ModuleFinder moduleFinder = ModuleFinder.of(Path.of(myArtifact.getOutputFilePath()));
|
||||
String modulesStr = moduleFinder.findAll().stream().map(mr -> mr.descriptor().name()).collect(Collectors.joining(","));
|
||||
if (modulesStr.isEmpty()) {
|
||||
error(context, "No module has been found");
|
||||
return;
|
||||
}
|
||||
JpsSdk<?> javaSdk = sdks.iterator().next();
|
||||
String sdkHomePath = javaSdk.getHomePath();
|
||||
String jLinkPath = sdkHomePath + File.separatorChar + "bin" + File.separatorChar + "jlink";
|
||||
List<String> commands = new ArrayList<>();
|
||||
commands.add(jLinkPath);
|
||||
JpsJLinkProperties properties = (JpsJLinkProperties)myArtifact.getProperties();
|
||||
if (properties.compressionLevel.hasCompression()) {
|
||||
addOption(commands, "--compress", String.valueOf(properties.compressionLevel.myValue));
|
||||
}
|
||||
if (properties.verbose) {
|
||||
commands.add("--verbose");
|
||||
}
|
||||
commands.add("--module-path");
|
||||
commands.add(myArtifact.getOutputFilePath());
|
||||
commands.add("--add-modules");
|
||||
commands.add(modulesStr);
|
||||
String outputPath = myArtifact.getOutputFilePath() + File.separator + "jdk";
|
||||
addOption(commands, "--output", outputPath);
|
||||
|
||||
LOG.warn(String.join(" ", commands));
|
||||
|
||||
try {
|
||||
FileUtil.delete(Path.of(outputPath));
|
||||
}
|
||||
catch (IOException e) {
|
||||
error(context,"Couldn't delete existing run-time image: " + e.getMessage());
|
||||
}
|
||||
|
||||
final int errorCode = startProcess(context, commands, properties);
|
||||
if (errorCode != 0) {
|
||||
error(context,"jlink task has failed");
|
||||
}
|
||||
|
||||
LOG.warn("jlink task was finished");
|
||||
}
|
||||
|
||||
private int startProcess(@NotNull CompileContext context, @NotNull List<String> commands, @NotNull JpsJLinkProperties properties) {
|
||||
try {
|
||||
final AtomicInteger exitCode = new AtomicInteger();
|
||||
final @NlsSafe StringBuilder errorOutput = new StringBuilder();
|
||||
final List<@NlsSafe String> delayedInfoOutput = new ArrayList<>();
|
||||
|
||||
final Process process = new ProcessBuilder(CommandLineUtil.toCommandLine(commands)).start();
|
||||
BaseOSProcessHandler handler = new BaseOSProcessHandler(process, commands.toString(), null);
|
||||
handler.addProcessListener(new ProcessAdapter() {
|
||||
@Override
|
||||
public void startNotified(@NotNull ProcessEvent event) {
|
||||
if (properties.verbose) {
|
||||
LOG.info("Started " + commands);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processTerminated(@NotNull ProcessEvent event) {
|
||||
if (properties.verbose) {
|
||||
LOG.info("Terminated " + commands + ", exit code: " + event.getExitCode());
|
||||
}
|
||||
exitCode.set(event.getExitCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextAvailable(@NotNull ProcessEvent event, @NotNull Key outputType) {
|
||||
String message = StringUtil.trimTrailing(event.getText());
|
||||
if (outputType == ProcessOutputTypes.STDERR) {
|
||||
LOG.error(message, (Throwable)null);
|
||||
errorOutput.append(event.getText());
|
||||
}
|
||||
else {
|
||||
LOG.info(message);
|
||||
if (properties.verbose) {
|
||||
info(context, message);
|
||||
}
|
||||
else {
|
||||
delayedInfoOutput.add(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
handler.startNotify();
|
||||
handler.waitFor();
|
||||
|
||||
int result = exitCode.get();
|
||||
if (result != 0) {
|
||||
final String message = errorOutput.toString();
|
||||
if (!StringUtil.isEmptyOrSpaces(message)) {
|
||||
error(context, message);
|
||||
}
|
||||
for (@NlsSafe String info : delayedInfoOutput) {
|
||||
error(context, info);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
catch (Exception e) {
|
||||
error(context, e.getMessage());
|
||||
LOG.warn(e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static void addOption(List<String> commands, @NotNull String key, @Nullable String value) {
|
||||
if (!StringUtil.isEmpty(value)) {
|
||||
commands.add(key);
|
||||
commands.add(value);
|
||||
}
|
||||
}
|
||||
|
||||
private void error(@NotNull CompileContext compileContext, @Nls String message) {
|
||||
compileContext.processMessage(new CompilerMessage("jlink", BuildMessage.Kind.ERROR, message));
|
||||
}
|
||||
|
||||
private void info(@NotNull CompileContext compileContext, @Nls String message) {
|
||||
compileContext.processMessage(new CompilerMessage("jlink", BuildMessage.Kind.INFO, message));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright 2000-2021 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 com.intellij.packaging.impl.jlink;
|
||||
|
||||
import org.jetbrains.jps.model.artifact.JpsArtifactType;
|
||||
import org.jetbrains.jps.model.ex.JpsElementTypeBase;
|
||||
|
||||
public class JpsJLinkArtifactType extends JpsElementTypeBase<JpsJLinkProperties> implements JpsArtifactType<JpsJLinkProperties> {
|
||||
|
||||
public static final JpsJLinkArtifactType INSTANCE = new JpsJLinkArtifactType();
|
||||
|
||||
private JpsJLinkArtifactType() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2000-2021 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 com.intellij.packaging.impl.jlink;
|
||||
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.xmlb.XmlSerializer;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
|
||||
import org.jetbrains.jps.model.serialization.artifact.ArtifactPropertiesState;
|
||||
import org.jetbrains.jps.model.serialization.artifact.JpsArtifactPropertiesSerializer;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class JpsJLinkModelSerializerExtension extends JpsModelSerializerExtension {
|
||||
|
||||
@Override
|
||||
public @NotNull List<? extends JpsArtifactPropertiesSerializer<?>> getArtifactTypePropertiesSerializers() {
|
||||
return Collections.singletonList(new JpsJLinkArtifactPropertiesSerializer());
|
||||
}
|
||||
|
||||
static class JpsJLinkArtifactPropertiesSerializer extends JpsArtifactPropertiesSerializer<JpsJLinkProperties> {
|
||||
|
||||
JpsJLinkArtifactPropertiesSerializer() {
|
||||
super("jlink", JpsJLinkArtifactType.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JpsJLinkProperties loadProperties(List<ArtifactPropertiesState> stateList) {
|
||||
final ArtifactPropertiesState state = findApplicationProperties(stateList);
|
||||
if (state != null) {
|
||||
final Element options = state.getOptions();
|
||||
if (options != null) {
|
||||
return new JpsJLinkProperties(XmlSerializer.deserialize(options, JpsJLinkProperties.class));
|
||||
}
|
||||
}
|
||||
return new JpsJLinkProperties();
|
||||
}
|
||||
|
||||
private static ArtifactPropertiesState findApplicationProperties(List<ArtifactPropertiesState> stateList) {
|
||||
return ContainerUtil.find(stateList, state -> "jlink-properties".equals(state.getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
// Copyright 2000-2021 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 com.intellij.packaging.impl.jlink;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.model.ex.JpsElementBase;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class JpsJLinkProperties extends JpsElementBase<JpsJLinkProperties> {
|
||||
public CompressionLevel compressionLevel = CompressionLevel.ZERO;
|
||||
public boolean verbose;
|
||||
|
||||
public JpsJLinkProperties() {
|
||||
}
|
||||
|
||||
public JpsJLinkProperties(@NotNull JpsJLinkProperties properties) {
|
||||
copyToThis(properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull JpsJLinkProperties createCopy() {
|
||||
return new JpsJLinkProperties(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyChanges(@NotNull JpsJLinkProperties modified) {
|
||||
copyToThis(modified);
|
||||
}
|
||||
|
||||
private void copyToThis(@NotNull JpsJLinkProperties copy) {
|
||||
compressionLevel = copy.compressionLevel;
|
||||
verbose = copy.verbose;
|
||||
}
|
||||
|
||||
public enum CompressionLevel {
|
||||
ZERO(0),
|
||||
FIRST(1),
|
||||
SECOND(2);
|
||||
|
||||
public final int myValue;
|
||||
CompressionLevel(int value) {
|
||||
this.myValue = value;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CompressionLevel getLevelByValue(int value) {
|
||||
return Stream.of(values()).filter(v -> v.myValue == value).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public boolean hasCompression() {
|
||||
return this == FIRST || this == SECOND;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -269,6 +269,7 @@
|
||||
</extensionPoints>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<compileServer.plugin classpath="java-compiler-impl.jar"/>
|
||||
|
||||
<notificationGroup id="jps configuration error"
|
||||
toolWindowId="Build"
|
||||
@@ -383,6 +384,8 @@
|
||||
implementation="com.intellij.openapi.roots.ui.configuration.artifacts.sourceItems.ArtifactsSourceItemsProvider"/>
|
||||
<packaging.artifactType implementation="com.intellij.packaging.impl.artifacts.JarArtifactType" order="first"/>
|
||||
<packaging.artifactType implementation="com.intellij.packaging.impl.artifacts.PlainArtifactType" order="last"/>
|
||||
<packaging.artifactType implementation="com.intellij.packaging.jlink.JLinkArtifactType"/>
|
||||
<packaging.artifactPropertiesProvider implementation="com.intellij.packaging.jlink.JLinkArtifactPropertiesProvider"/>
|
||||
<compiler.buildTargetScopeProvider implementation="com.intellij.packaging.impl.compiler.ArtifactBuildTargetScopeProvider"/>
|
||||
|
||||
<projectTaskRunner implementation="com.intellij.task.impl.JpsProjectTaskRunner" id="jps" order="last"/>
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
// Copyright 2000-2021 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 com.intellij.packaging.jlink;
|
||||
|
||||
import com.intellij.packaging.artifacts.ArtifactProperties;
|
||||
import com.intellij.packaging.ui.ArtifactEditorContext;
|
||||
import com.intellij.packaging.ui.ArtifactPropertiesEditor;
|
||||
import com.intellij.util.xmlb.XmlSerializerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class JLinkArtifactProperties extends ArtifactProperties<JLinkArtifactProperties> {
|
||||
public CompressionLevel compressionLevel = CompressionLevel.ZERO;
|
||||
public boolean verbose;
|
||||
|
||||
@Override
|
||||
public ArtifactPropertiesEditor createEditor(@NotNull ArtifactEditorContext context) {
|
||||
return new JLinkArtifactPropertiesEditor(this, context.getProject());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable JLinkArtifactProperties getState() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(@NotNull JLinkArtifactProperties state) {
|
||||
XmlSerializerUtil.copyBean(state, this);
|
||||
}
|
||||
|
||||
public enum CompressionLevel {
|
||||
ZERO(0),
|
||||
FIRST(1),
|
||||
SECOND(2);
|
||||
|
||||
public final int myValue;
|
||||
CompressionLevel(int value) {
|
||||
this.myValue = value;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CompressionLevel getLevelByValue(int value) {
|
||||
return Stream.of(values()).filter(v -> v.myValue == value).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public boolean hasCompression() {
|
||||
return this == FIRST || this == SECOND;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// Copyright 2000-2021 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 com.intellij.packaging.jlink;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.ComboBox;
|
||||
import com.intellij.packaging.ui.ArtifactPropertiesEditor;
|
||||
import com.intellij.util.ui.FormBuilder;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Optional;
|
||||
|
||||
import static com.intellij.packaging.jlink.JLinkArtifactProperties.CompressionLevel;
|
||||
|
||||
public class JLinkArtifactPropertiesEditor extends ArtifactPropertiesEditor {
|
||||
private final JLinkArtifactProperties myProperties;
|
||||
private final Project myProject;
|
||||
|
||||
private ComboBox<Integer> myCompressionLevel;
|
||||
private JCheckBox myVerbose;
|
||||
|
||||
public JLinkArtifactPropertiesEditor(@NotNull JLinkArtifactProperties properties, @NotNull Project project) {
|
||||
myProperties = properties;
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
@Nls
|
||||
@Override
|
||||
public String getTabName() {
|
||||
return "JLink";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable JComponent createComponent() {
|
||||
final FormBuilder builder = new FormBuilder();
|
||||
|
||||
myCompressionLevel = new ComboBox<>(EnumSet.allOf(CompressionLevel.class).stream().map(level -> level.myValue).toArray(Integer[]::new));
|
||||
myCompressionLevel.setItem(myProperties.compressionLevel.myValue);
|
||||
builder.addLabeledComponent("Compress level", myCompressionLevel);
|
||||
|
||||
myVerbose = new JCheckBox("Enable verbose tracing", myProperties.verbose);
|
||||
builder.addComponent(myVerbose);
|
||||
|
||||
return builder.getPanel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModified() {
|
||||
if (myProperties.compressionLevel != CompressionLevel.getLevelByValue(myCompressionLevel.getItem())) return true;
|
||||
if (myProperties.verbose != myVerbose.isSelected()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply() {
|
||||
myProperties.compressionLevel = Optional.ofNullable(myCompressionLevel.getItem())
|
||||
.map(i -> CompressionLevel.getLevelByValue(i))
|
||||
.orElse(CompressionLevel.ZERO);
|
||||
myProperties.verbose = myVerbose.isSelected();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright 2000-2021 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 com.intellij.packaging.jlink;
|
||||
|
||||
import com.intellij.packaging.artifacts.ArtifactProperties;
|
||||
import com.intellij.packaging.artifacts.ArtifactPropertiesProvider;
|
||||
import com.intellij.packaging.artifacts.ArtifactType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class JLinkArtifactPropertiesProvider extends ArtifactPropertiesProvider {
|
||||
protected JLinkArtifactPropertiesProvider() {
|
||||
super("jlink-properties");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull ArtifactProperties<?> createProperties(@NotNull ArtifactType artifactType) {
|
||||
return new JLinkArtifactProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailableFor(@NotNull ArtifactType type) {
|
||||
return type instanceof JLinkArtifactType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2000-2021 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 com.intellij.packaging.jlink;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.packaging.artifacts.ArtifactType;
|
||||
import com.intellij.packaging.elements.CompositePackagingElement;
|
||||
import com.intellij.packaging.elements.PackagingElementFactory;
|
||||
import com.intellij.packaging.elements.PackagingElementOutputKind;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public class JLinkArtifactType extends ArtifactType {
|
||||
protected JLinkArtifactType() {
|
||||
super("jlink", () -> "Run-time image");
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Icon getIcon() {
|
||||
return AllIcons.Nodes.Artifact;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable String getDefaultPathFor(@NotNull PackagingElementOutputKind kind) {
|
||||
return "/";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull CompositePackagingElement<?> createRootElement(@NotNull String artifactName) {
|
||||
return PackagingElementFactory.getInstance().createArtifactRootElement();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user