My ComplexPackagingElement implementation doest not package elements in getSubstitution method
已回答
I have created MyComplexPackagingElement class which is extended from ComplexPackagingElement to build my artifact . Overried method getSubstitution returns a list of DirectoryCopyPackagingElement. But the directory does not copied when building my artifact.
public class MyComplexPackagingElement
extends ComplexPackagingElement<MyComplexPackagingElement>
implements FacetBasedPackagingElement {
public static final String FACET_ATTRIBUTE = "facetId";
private String path;
private String facetId;
private MyFacet myFacet;
private FacetPointer<MyFacet> pointer;
public MyComplexPackagingElement(Project project) {
super(MyComplexPackagingElementType.getInstance());
this.myProject = project;
}
public MyComplexPackagingElement(MyFacet myFacet) {
super(MyComplexPackagingElementType.getInstance());
this.myFacet = myFacet;
this.path = myFacet.getPath();
this.pointer = FacetPointersManager.getInstance(myFacet.getModule().getProject()).create(myFacet);
this.facetId = pointer.getId();
}
@Override
public @Nullable List<? extends PackagingElement<?>> getSubstitution(@NotNull PackagingElementResolvingContext context, @NotNull ArtifactType artifactType) {
return Lists.newArrayList(new DirectoryCopyPackagingElement(path));
}
@Override
public @NotNull PackagingElementPresentation createPresentation(@NotNull ArtifactEditorContext context) {
return new MyComplexPackagingElementPresentation(myFacet, context, pointer, "resources");
}
@Attribute(FACET_ATTRIBUTE)
public String getFacetId() {
return this.facetId;
}
public void setFacetId(String facetId) {
this.facetId = facetId;
}
@Override
public boolean isEqualTo(@NotNull PackagingElement<?> element) {
if (element instanceof MyComplexPackagingElement) {
MyComplexPackagingElement other = (MyComplexPackagingElement)element;
return Objects.equals(path, other.path) && Objects.equals(facetId, other.facetId);
}
return false;
}
@Override
public @Nullable MyComplexPackagingElement getState() {
return this;
}
@Override
public void loadState(@NotNull MyComplexPackagingElement state) {
this.facetId = state.getFacetId();
this.pointer = (this.facetId != null) ? FacetPointersManager.getInstance(this.myProject).create(this.facetId) : null;
if (this.pointer != null) {
this.myFacet = Objects.requireNonNull(this.pointer.getFacet());
this.path = this.myFacet.getPath();
}
}
@Nullable
@Override
public MyFacet findFacet(@NotNull PackagingElementResolvingContext context) {
return ReadAction.compute(() -> this.pointer.findFacet(context.getModulesProvider(), context.getFacetsProvider()));
}
@Override
public String toString() {
return "my-facet-contents:" + this.pointer.getFacetName() + "(" + this.pointer.getModuleName() + ")";
}
}
public class MyComplexPackagingElementType extends ComplexPackagingElementType<MyComplexPackagingElement> {
public static MyComplexPackagingElementType getInstance() {
return PackagingElementType.getInstance(MyComplexPackagingElementType.class);
}
public static final String TYPE_ID = "my-facet-contents";
public MyComplexPackagingElementType() {
super(TYPE_ID, () -> "My Facet Contents");
}
@Override
public boolean canCreate(@NotNull ArtifactEditorContext context, @NotNull Artifact artifact) {
Module[] modules = context.getModulesProvider().getModules();
List<MyFacet> myFacets = MyFacetSourceItemsProvider.getMyFacets(context, modules);
return !myFacets.isEmpty();
}
@Override
public @NotNull List<? extends PackagingElement<?>> chooseAndCreate(@NotNull ArtifactEditorContext context,
@NotNull Artifact artifact,
@NotNull CompositePackagingElement<?> parent) {
Collection<MyFacet> facets = MyFacetSourceItemsProvider.getMyFacets(context, context.getModulesProvider().getModules());
ChooseFacetsDialog dialog = new ChooseFacetsDialog(context.getProject(), Lists.newArrayList(facets), "Choose My Facet", "");
dialog.show();
List<MyComplexPackagingElement> elements = Lists.newArrayList();
if (dialog.isOK()) {
for (MyFacet facet : dialog.getChosenElements()) {
elements.add(new MyComplexPackagingElement(facet));
}
}
return elements;
}
@Override
public @NotNull MyComplexPackagingElement createEmpty(@NotNull Project project) {
return new MyComplexPackagingElement(project);
}
@Override
public @NlsActions.ActionText String getShowContentActionText() {
return "Show Content of the Facet";
}
}
<extensions defaultExtensionNs="com.intellij">
<facetType implementation="com.example.demo.artifact.facet.MyFacetType" />
<packaging.artifactType implementation="com.example.demo.artifact.MyArtifactType" />
<packaging.elementType implementation="com.example.demo.artifact.facet.MyComplexPackagingElementType" />
<packaging.sourceItemProvider implementation="com.example.demo.artifact.facet.MyFacetSourceItemsProvider" />
</extensions>
The usage is as follows:
// not work
// getFacetResourcesPackagingElements returns Lists.newArrayList(new MyComplexPackagingElement(path));
root.addOrFindChildren(myFacet.getFacetResourcesPackagingElements());
But this will work
root.addOrFindChildren(Lists.newArrayList(new DirectoryCopyPackagingElement(path)));
Have I made any mistakes? How do I get MyComplexPackagingElement to work?
Any help would be appreciated!
请先登录再写评论。
Hi,
Please provide full context. What is the rest of the implementation? What is the full context you invoke it in? How is it registered in plugin.xml? What is the platform type and version?
Thanks for your reply. I have updated this post. And the entire project is here.
The implementation looks correct for me. However, when you invoke Build Project, IDE starts a separate process which don't have access to most of IntelliJ API. If you want to modify behavior of the build process to support custom elements in artifacts, you need to write a plugin for the build process, see the docs for details. Currently, it uses different API to access the project configuration, so you'll need to provide a different implementation for the model elements using Jps* interfaces (JpsComplexPackagingElement) and implement code which loads it from the artifact XML file (via JpsModelSerializerExtension).
In general, I wouldn't recommend providing custom elements for artifacts. It's possible, but rather complicated. And the result can be used only when build is invoked from IntelliJ IDEA, but usually we want to be able to build our projects from command line to perform it on CI servers. So if you want to customize build process for some framework, it's better to write a plugin to some build system (Maven, Gradle, …). If you do this, there may be no need to write a plugin for IntelliJ IDEA at all, since it may invoke Maven/Gradle tasks directly. But if it isn't enough, you may customize how Maven/Gradle projects are imported to include data from your plugin in the project configuration in IntelliJ.
Thanks for your reply. I have solved this problem and updated my demo project. Thank you again.