-
Notifications
You must be signed in to change notification settings - Fork 116
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Provide auto completion for bnd instructions in maven xml documents
The bnd-maven and felix-bundle plugin provide a way to use bnd-instructions to build OSGi bundles. As this is a complex syntax that can not be expressed as regular maven-mojo configuration lemminx-maven can not supply any useful completions. This adds a new lemminx-extension that provides such completions in a very basic way to support people writing such custom configuration. Signed-off-by: Christoph Läubrich <[email protected]>
- Loading branch information
Showing
13 changed files
with
314 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
org.eclipse.m2e.bnd.ui/OSGI-INF/org.eclipse.m2e.bnd.ui.BndPluginAdapter.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.4.0" name="org.eclipse.m2e.bnd.ui.BndPluginAdapter"> | ||
<property name="adaptableClass" type="String" value="org.eclipse.core.resources.IProject"/> | ||
<property name="adapterNames" type="String" value="aQute.bnd.build.Project"/> | ||
<service> | ||
<provide interface="org.eclipse.core.runtime.IAdapterFactory"/> | ||
</service> | ||
<implementation class="org.eclipse.m2e.bnd.ui.BndPluginAdapter"/> | ||
</scr:component> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<classpath> | ||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-21"/> | ||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> | ||
<classpathentry kind="src" path="src"/> | ||
<classpathentry kind="output" path="bin"/> | ||
</classpath> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<projectDescription> | ||
<name>org.eclipse.m2e.editor.lemminx.bnd</name> | ||
<comment></comment> | ||
<projects> | ||
</projects> | ||
<buildSpec> | ||
<buildCommand> | ||
<name>org.eclipse.jdt.core.javabuilder</name> | ||
<arguments> | ||
</arguments> | ||
</buildCommand> | ||
<buildCommand> | ||
<name>org.eclipse.pde.ManifestBuilder</name> | ||
<arguments> | ||
</arguments> | ||
</buildCommand> | ||
<buildCommand> | ||
<name>org.eclipse.pde.SchemaBuilder</name> | ||
<arguments> | ||
</arguments> | ||
</buildCommand> | ||
</buildSpec> | ||
<natures> | ||
<nature>org.eclipse.pde.PluginNature</nature> | ||
<nature>org.eclipse.jdt.core.javanature</nature> | ||
</natures> | ||
</projectDescription> |
2 changes: 2 additions & 0 deletions
2
org.eclipse.m2e.editor.lemminx.bnd/.settings/org.eclipse.core.resources.prefs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
eclipse.preferences.version=1 | ||
encoding/<project>=UTF-8 |
9 changes: 9 additions & 0 deletions
9
org.eclipse.m2e.editor.lemminx.bnd/.settings/org.eclipse.jdt.core.prefs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
eclipse.preferences.version=1 | ||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=21 | ||
org.eclipse.jdt.core.compiler.compliance=21 | ||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error | ||
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled | ||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error | ||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning | ||
org.eclipse.jdt.core.compiler.release=enabled | ||
org.eclipse.jdt.core.compiler.source=21 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
Manifest-Version: 1.0 | ||
Bundle-ManifestVersion: 2 | ||
Bundle-Name: Lemminx Bnd Extension | ||
Bundle-SymbolicName: org.eclipse.m2e.editor.lemminx.bnd;singleton:=true | ||
Bundle-Version: 1.0.0.qualifier | ||
Require-Bundle: org.eclipse.wildwebdeveloper.xml | ||
Bundle-Vendor: Eclipse | ||
Automatic-Module-Name: org.eclipse.m2e.editor.lemminx.bnd | ||
Bundle-RequiredExecutionEnvironment: JavaSE-21 | ||
Import-Package: aQute.bnd.help;version="[2.0.0,3.0.0)", | ||
org.eclipse.core.runtime;version="[3.7.0,4.0.0)", | ||
org.osgi.framework;version="[1.10.0,2.0.0)", | ||
org.osgi.framework.wiring;version="[1.2.0,2.0.0)", | ||
org.osgi.resource;version="[1.0.0,2.0.0)" |
1 change: 1 addition & 0 deletions
1
...ditor.lemminx.bnd/META-INF/services/org.eclipse.lemminx.services.extensions.IXMLExtension
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
org.eclipse.m2e.editor.lemminx.bnd.BndLemminxPlugin |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
source.. = src/ | ||
output.. = bin/ | ||
bin.includes = META-INF/,\ | ||
.,\ | ||
plugin.xml | ||
jars.extra.classpath = platform:/plugin/org.eclipse.wildwebdeveloper.xml/language-servers/server/org.eclipse.lemminx-uber.jar |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<?eclipse version="3.4"?> | ||
<plugin> | ||
<extension | ||
point="org.eclipse.wildwebdeveloper.xml.lemminxExtension"> | ||
<classpathExtensionProvider | ||
provider="org.eclipse.m2e.editor.lemminx.bnd.BndClasspathExtensionProvider"> | ||
</classpathExtensionProvider> | ||
</extension> | ||
|
||
</plugin> |
78 changes: 78 additions & 0 deletions
78
...tor.lemminx.bnd/src/org/eclipse/m2e/editor/lemminx/bnd/BndClasspathExtensionProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2024 Christoph Läubrich and others. | ||
* | ||
* This program and the accompanying materials | ||
* are made available under the terms of the Eclipse Public License 2.0 | ||
* which accompanies this distribution, and is available at | ||
* https://www.eclipse.org/legal/epl-2.0/ | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
*******************************************************************************/ | ||
package org.eclipse.m2e.editor.lemminx.bnd; | ||
|
||
import java.io.File; | ||
import java.util.ArrayList; | ||
import java.util.LinkedHashSet; | ||
import java.util.List; | ||
import java.util.Set; | ||
|
||
import org.eclipse.core.runtime.FileLocator; | ||
import org.osgi.framework.Bundle; | ||
import org.osgi.framework.FrameworkUtil; | ||
import org.osgi.framework.wiring.BundleWire; | ||
import org.osgi.framework.wiring.BundleWiring; | ||
|
||
import aQute.bnd.help.Syntax; | ||
|
||
/** | ||
* register additional jars and the extension bundle | ||
*/ | ||
@SuppressWarnings("restriction") | ||
public class BndClasspathExtensionProvider | ||
implements org.eclipse.wildwebdeveloper.xml.LemminxClasspathExtensionProvider { | ||
|
||
@Override | ||
public List<File> get() { | ||
List<File> list = new ArrayList<>(); | ||
Set<Bundle> bundleRequirements = new LinkedHashSet<>(); | ||
bundleRequirements.add((FrameworkUtil.getBundle(getClass()))); | ||
collectBundles(FrameworkUtil.getBundle(Syntax.class), bundleRequirements); | ||
for (Bundle bundle : bundleRequirements) { | ||
FileLocator.getBundleFileLocation(bundle).ifPresent(file -> { | ||
if (file.isDirectory()) { | ||
// For bundles from the workspace launch include the bin folder for classes | ||
File outputFolder = new File(file, "bin"); | ||
if (outputFolder.exists()) { | ||
list.add(outputFolder); | ||
} | ||
} | ||
list.add(file); | ||
}); | ||
} | ||
return list; | ||
} | ||
|
||
private void collectBundles(Bundle bundle, Set<Bundle> bundleRequirements) { | ||
if (isValid(bundle) && bundleRequirements.add(bundle)) { | ||
BundleWiring wiring = bundle.adapt(BundleWiring.class); | ||
List<BundleWire> wires = wiring.getRequiredWires("osgi.wiring.package"); | ||
for (BundleWire bundleWire : wires) { | ||
collectBundles(bundleWire.getProvider().getBundle(), bundleRequirements); | ||
} | ||
} | ||
|
||
} | ||
|
||
private boolean isValid(Bundle bundle) { | ||
if (bundle == null) { | ||
return false; | ||
} | ||
String bsn = bundle.getSymbolicName(); | ||
if ("slf4j.api".equals(bsn)) { | ||
// slf4j is already provided | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
} |
132 changes: 132 additions & 0 deletions
132
...lipse.m2e.editor.lemminx.bnd/src/org/eclipse/m2e/editor/lemminx/bnd/BndLemminxPlugin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2024 Christoph Läubrich and others. | ||
* | ||
* This program and the accompanying materials | ||
* are made available under the terms of the Eclipse Public License 2.0 | ||
* which accompanies this distribution, and is available at | ||
* https://www.eclipse.org/legal/epl-2.0/ | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
*******************************************************************************/ | ||
package org.eclipse.m2e.editor.lemminx.bnd; | ||
|
||
import java.util.function.Function; | ||
import java.util.logging.Level; | ||
import java.util.logging.Logger; | ||
|
||
import org.eclipse.lemminx.dom.DOMDocument; | ||
import org.eclipse.lemminx.dom.DOMNode; | ||
import org.eclipse.lemminx.services.extensions.IXMLExtension; | ||
import org.eclipse.lemminx.services.extensions.XMLExtensionsRegistry; | ||
import org.eclipse.lemminx.services.extensions.completion.ICompletionParticipant; | ||
import org.eclipse.lemminx.services.extensions.completion.ICompletionRequest; | ||
import org.eclipse.lemminx.services.extensions.completion.ICompletionResponse; | ||
import org.eclipse.lemminx.services.extensions.save.ISaveContext; | ||
import org.eclipse.lsp4j.CompletionItem; | ||
import org.eclipse.lsp4j.CompletionItemKind; | ||
import org.eclipse.lsp4j.InitializeParams; | ||
import org.eclipse.lsp4j.InsertTextFormat; | ||
import org.eclipse.lsp4j.jsonrpc.CancelChecker; | ||
|
||
import aQute.bnd.help.Syntax; | ||
|
||
/** | ||
* Extension to provide bnd instruction autocompletion to maven | ||
*/ | ||
public class BndLemminxPlugin implements IXMLExtension { | ||
|
||
@Override | ||
public void start(InitializeParams params, XMLExtensionsRegistry registry) { | ||
Logger logger = Logger.getLogger("bnd"); | ||
logger.log(Level.INFO, "Loading bnd-lemminx extension"); | ||
registry.registerCompletionParticipant(new ICompletionParticipant() { | ||
|
||
@Override | ||
public void onAttributeName(boolean generateValue, ICompletionRequest completionRequest, | ||
ICompletionResponse response, CancelChecker checker) throws Exception { | ||
} | ||
|
||
@Override | ||
public void onAttributeValue(String valuePrefix, ICompletionRequest completionRequest, | ||
ICompletionResponse response, CancelChecker checker) throws Exception { | ||
} | ||
|
||
@Override | ||
public void onDTDSystemId(String valuePrefix, ICompletionRequest completionRequest, | ||
ICompletionResponse response, CancelChecker checker) throws Exception { | ||
} | ||
|
||
@Override | ||
public void onTagOpen(ICompletionRequest completionRequest, ICompletionResponse response, | ||
CancelChecker checker) throws Exception { | ||
} | ||
|
||
@Override | ||
public void onXMLContent(ICompletionRequest completionRequest, ICompletionResponse response, | ||
CancelChecker checker) throws Exception { | ||
try { | ||
DOMDocument xmlDocument = completionRequest.getXMLDocument(); | ||
DOMNode node = xmlDocument.findNodeBefore(completionRequest.getOffset()); | ||
logger.log(Level.INFO, "onXMLContent: " + node); | ||
if (isBndInstructionNode(node)) { | ||
addCompletion(response, syntax -> syntax.getHeader() + ": "); | ||
} else if (isFelixInstructionNode(node)) { | ||
addCompletion(response, syntax -> { | ||
String header = syntax.getHeader(); | ||
if (header.startsWith("-")) { | ||
header = "_" + header.substring(1); | ||
} | ||
return String.format("<%s>${0}</%s>", header, header); | ||
}); | ||
} | ||
} catch (Exception e) { | ||
logger.log(Level.WARNING, "err=" + e); | ||
} | ||
} | ||
|
||
private void addCompletion(ICompletionResponse response, Function<Syntax, String> insert) { | ||
Syntax.HELP.values().stream().forEach(syntax -> { | ||
CompletionItem item = new CompletionItem(); | ||
item.setLabel(syntax.getHeader()); | ||
item.setDocumentation(syntax.getLead()); | ||
item.setDetail(syntax.getExample()); | ||
item.setInsertText(insert.apply(syntax)); | ||
item.setKind(CompletionItemKind.Property); | ||
item.setInsertTextFormat(InsertTextFormat.Snippet); | ||
response.addCompletionItem(item); | ||
}); | ||
} | ||
}); | ||
} | ||
|
||
private static boolean isBndInstructionNode(DOMNode node) { | ||
if (node != null) { | ||
if (node.getNodeName().equals("bnd")) { | ||
return true; | ||
} | ||
return isBndInstructionNode(node.getParentNode()); | ||
} | ||
return false; | ||
} | ||
|
||
private static boolean isFelixInstructionNode(DOMNode node) { | ||
if (node != null) { | ||
if (node.getNodeName().equals("instructions")) { | ||
return true; | ||
} | ||
return isFelixInstructionNode(node.getParentNode()); | ||
} | ||
return false; | ||
} | ||
|
||
@Override | ||
public void stop(XMLExtensionsRegistry registry) { | ||
// nothing special to do... | ||
} | ||
|
||
@Override | ||
public void doSave(ISaveContext context) { | ||
IXMLExtension.super.doSave(context); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters