forked from eclipse-lemminx/lemminx
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support for textDocument/documentColor
Fixes eclipse-lemminx#639 Signed-off-by: azerr <azerr@redhat.com>
- Loading branch information
1 parent
3a25dad
commit 4646146
Showing
20 changed files
with
1,234 additions
and
4 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
98 changes: 98 additions & 0 deletions
98
org.eclipse.lemminx/src/main/java/org/eclipse/lemminx/extensions/colors/XMLColorsPlugin.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,98 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2023 Red Hat Inc. and others. | ||
* All rights reserved. This program and the accompanying materials | ||
* which accompanies this distribution, and is available at | ||
* http://www.eclipse.org/legal/epl-v20.html | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
* | ||
* Contributors: | ||
* Red Hat Inc. - initial API and implementation | ||
*******************************************************************************/ | ||
package org.eclipse.lemminx.extensions.colors; | ||
|
||
import org.eclipse.lemminx.extensions.colors.participants.XMLDocumentColorParticipant; | ||
import org.eclipse.lemminx.extensions.colors.settings.XMLColorsSettings; | ||
import org.eclipse.lemminx.services.extensions.IDocumentColorParticipant; | ||
import org.eclipse.lemminx.services.extensions.IXMLExtension; | ||
import org.eclipse.lemminx.services.extensions.XMLExtensionsRegistry; | ||
import org.eclipse.lemminx.services.extensions.save.ISaveContext; | ||
import org.eclipse.lsp4j.InitializeParams; | ||
|
||
/** | ||
* XML colors plugin. | ||
* | ||
* This plugin provides the capability to support color with 'xml.colors' | ||
* settings. | ||
* | ||
* <code> | ||
"xml.colors": [ | ||
// XML colors applied for text node for android colors.xml files | ||
{ | ||
"pattern": "/res/values/colors.xml", | ||
"expressions": [ | ||
{ | ||
"path": "resources/color/text()" | ||
} | ||
] | ||
}, | ||
// XML colors applied for @color attribute for another files | ||
{ | ||
"pattern": "/my-colors.xml", | ||
"expressions": [ | ||
{ | ||
"path": "@color" | ||
} | ||
] | ||
} | ||
] | ||
* | ||
* </code> | ||
* | ||
* | ||
* @author Angelo ZERR | ||
* | ||
*/ | ||
public class XMLColorsPlugin implements IXMLExtension { | ||
|
||
private final IDocumentColorParticipant documentColorParticipant; | ||
|
||
private XMLColorsSettings colorsSettings; | ||
|
||
public XMLColorsPlugin() { | ||
documentColorParticipant = new XMLDocumentColorParticipant(this); | ||
} | ||
|
||
@Override | ||
public void doSave(ISaveContext context) { | ||
if (context.getType() != ISaveContext.SaveContextType.DOCUMENT) { | ||
// Settings | ||
updateSettings(context); | ||
} | ||
} | ||
|
||
private void updateSettings(ISaveContext saveContext) { | ||
Object initializationOptionsSettings = saveContext.getSettings(); | ||
XMLColorsSettings referencesSettings = XMLColorsSettings | ||
.getXMLColorsSettings(initializationOptionsSettings); | ||
updateSettings(referencesSettings, saveContext); | ||
} | ||
|
||
private void updateSettings(XMLColorsSettings settings, ISaveContext context) { | ||
this.colorsSettings = settings; | ||
} | ||
|
||
@Override | ||
public void start(InitializeParams params, XMLExtensionsRegistry registry) { | ||
registry.registerDocumentColorParticipant(documentColorParticipant); | ||
} | ||
|
||
@Override | ||
public void stop(XMLExtensionsRegistry registry) { | ||
registry.unregisterDocumentColorParticipant(documentColorParticipant); | ||
} | ||
|
||
public XMLColorsSettings getColorsSettings() { | ||
return colorsSettings; | ||
} | ||
} |
177 changes: 177 additions & 0 deletions
177
.../java/org/eclipse/lemminx/extensions/colors/participants/XMLDocumentColorParticipant.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,177 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2023 Red Hat Inc. and others. | ||
* All rights reserved. This program and the accompanying materials | ||
* which accompanies this distribution, and is available at | ||
* http://www.eclipse.org/legal/epl-v20.html | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
* | ||
* Contributors: | ||
* Red Hat Inc. - initial API and implementation | ||
*******************************************************************************/ | ||
package org.eclipse.lemminx.extensions.colors.participants; | ||
|
||
import static org.eclipse.lemminx.extensions.colors.utils.ColorUtils.getColorValue; | ||
import static org.eclipse.lemminx.extensions.colors.utils.ColorUtils.toHexa; | ||
import static org.eclipse.lemminx.extensions.colors.utils.ColorUtils.toRGB; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
import org.eclipse.lemminx.dom.DOMAttr; | ||
import org.eclipse.lemminx.dom.DOMDocument; | ||
import org.eclipse.lemminx.dom.DOMElement; | ||
import org.eclipse.lemminx.dom.DOMNode; | ||
import org.eclipse.lemminx.dom.DOMText; | ||
import org.eclipse.lemminx.extensions.colors.XMLColorsPlugin; | ||
import org.eclipse.lemminx.extensions.colors.settings.XMLColorExpression; | ||
import org.eclipse.lemminx.extensions.colors.settings.XMLColors; | ||
import org.eclipse.lemminx.extensions.colors.settings.XMLColorsSettings; | ||
import org.eclipse.lemminx.services.extensions.IDocumentColorParticipant; | ||
import org.eclipse.lemminx.utils.XMLPositionUtility; | ||
import org.eclipse.lsp4j.Color; | ||
import org.eclipse.lsp4j.ColorInformation; | ||
import org.eclipse.lsp4j.ColorPresentation; | ||
import org.eclipse.lsp4j.ColorPresentationParams; | ||
import org.eclipse.lsp4j.Range; | ||
import org.eclipse.lsp4j.jsonrpc.CancelChecker; | ||
|
||
/** | ||
* XML document color particpant based on the {@link XMLColorsSettings}. | ||
* | ||
* @author Angelo ZERR | ||
* | ||
*/ | ||
public class XMLDocumentColorParticipant implements IDocumentColorParticipant { | ||
|
||
private final XMLColorsPlugin xmlColorsPlugin; | ||
|
||
public XMLDocumentColorParticipant(XMLColorsPlugin xmlColorsPlugin) { | ||
this.xmlColorsPlugin = xmlColorsPlugin; | ||
} | ||
|
||
@Override | ||
public void doDocumentColor(DOMDocument xmlDocument, List<ColorInformation> colors, CancelChecker cancelChecker) { | ||
List<XMLColorExpression> expressions = findColorExpression(xmlDocument); | ||
if (expressions.isEmpty()) { | ||
return; | ||
} | ||
doDocumentColor(xmlDocument, expressions, colors, cancelChecker); | ||
} | ||
|
||
private void doDocumentColor(DOMNode node, List<XMLColorExpression> expressions, List<ColorInformation> colors, | ||
CancelChecker cancelChecker) { | ||
if (node.isElement()) { | ||
DOMElement element = (DOMElement) node; | ||
if (element.hasAttributes()) { | ||
List<DOMAttr> attributes = element.getAttributeNodes(); | ||
for (DOMAttr attr : attributes) { | ||
if (isColorNode(attr, expressions)) { | ||
// The current attribute node matches an XML color expression declared in the | ||
// "xml/colors" | ||
// settings | ||
// ex : | ||
// - xpath="foo/@color" | ||
Color color = getColorValue(attr.getValue()); | ||
if (color != null) { | ||
Range range = XMLPositionUtility.selectAttributeValue(attr, true); | ||
ColorInformation colorInformation = new ColorInformation(range, color); | ||
colors.add(colorInformation); | ||
} | ||
} | ||
} | ||
} | ||
} else if (node.isText()) { | ||
if (isColorNode(node, expressions)) { | ||
// The current text node matches an XML color expression declared in the | ||
// "xml/colors" | ||
// settings | ||
// ex : | ||
// - xpath="resources/color/text()" | ||
DOMText text = (DOMText) node; | ||
Color color = getColorValue(text.getData()); | ||
if (color != null) { | ||
Range range = XMLPositionUtility.selectText(text); | ||
ColorInformation colorInformation = new ColorInformation(range, color); | ||
colors.add(colorInformation); | ||
} | ||
} | ||
} | ||
List<DOMNode> children = node.getChildren(); | ||
for (DOMNode child : children) { | ||
cancelChecker.checkCanceled(); | ||
doDocumentColor(child, expressions, colors, cancelChecker); | ||
} | ||
} | ||
|
||
@Override | ||
public void doColorPresentations(DOMDocument xmlDocument, ColorPresentationParams params, | ||
List<ColorPresentation> presentations, CancelChecker cancelChecker) { | ||
Color color = params.getColor(); | ||
Range replace = params.getRange(); | ||
// RGB color presentation | ||
presentations.add(toRGB(color, replace)); | ||
// Hexa color presentation | ||
presentations.add(toHexa(color, replace)); | ||
} | ||
|
||
/** | ||
* Returns true if the given <code>node>code> matches an XML color expression | ||
* and false otherwise. | ||
* | ||
* @param node the node to match. | ||
* @param expressions XML color expressions. | ||
* | ||
* @return true if the given <code>node>code> matches an XML color expression | ||
* and false otherwise. | ||
*/ | ||
private static boolean isColorNode(DOMNode node, List<XMLColorExpression> expressions) { | ||
if (node.isAttribute()) { | ||
DOMAttr attr = (DOMAttr) node; | ||
if (attr.getValue() == null && attr.getValue().isEmpty()) { | ||
return false; | ||
} | ||
} else if (node.isText()) { | ||
DOMText text = (DOMText) node; | ||
if (!text.hasData()) { | ||
return false; | ||
} | ||
} | ||
for (XMLColorExpression expression : expressions) { | ||
if (expression.match(node)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
/** | ||
* Return the list of {@link XMLColorExpression} for the given document and an | ||
* empty list otherwise. | ||
* | ||
* @param xmlDocument the DOM document | ||
* | ||
* @return the list of {@link XMLColorExpression} for the given document and an | ||
* empty list otherwise. | ||
*/ | ||
private List<XMLColorExpression> findColorExpression(DOMDocument xmlDocument) { | ||
XMLColorsSettings settings = xmlColorsPlugin.getColorsSettings(); | ||
if (settings == null) { | ||
return Collections.emptyList(); | ||
} | ||
|
||
List<XMLColors> colorsDef = settings.getColors(); | ||
if (colorsDef == null) { | ||
return Collections.emptyList(); | ||
} | ||
List<XMLColorExpression> expressions = new ArrayList<>(); | ||
for (XMLColors xmlColors : colorsDef) { | ||
if (xmlColors.matches(xmlDocument.getDocumentURI())) { | ||
expressions.addAll(xmlColors.getExpressions()); | ||
} | ||
} | ||
return expressions; | ||
} | ||
|
||
} |
50 changes: 50 additions & 0 deletions
50
...minx/src/main/java/org/eclipse/lemminx/extensions/colors/settings/XMLColorExpression.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,50 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2023 Red Hat Inc. and others. | ||
* All rights reserved. This program and the accompanying materials | ||
* which accompanies this distribution, and is available at | ||
* http://www.eclipse.org/legal/epl-v20.html | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 | ||
* | ||
* Contributors: | ||
* Red Hat Inc. - initial API and implementation | ||
*******************************************************************************/ | ||
package org.eclipse.lemminx.extensions.colors.settings; | ||
|
||
import org.eclipse.lemminx.xpath.matcher.XPathMatcher; | ||
import org.w3c.dom.Node; | ||
|
||
/** | ||
* XML colors expression | ||
* | ||
* <code> | ||
* { | ||
"xpath": "@color" | ||
} | ||
* </code> | ||
* | ||
* @author Angelo ZERR | ||
* | ||
*/ | ||
public class XMLColorExpression { | ||
|
||
private transient XPathMatcher pathMatcher; | ||
|
||
private String xpath; | ||
|
||
public String getXPath() { | ||
return xpath; | ||
} | ||
|
||
public void setXPath(String xpath) { | ||
this.xpath = xpath; | ||
} | ||
|
||
public boolean match(final Node node) { | ||
if (pathMatcher == null) { | ||
pathMatcher = new XPathMatcher(xpath); | ||
} | ||
return pathMatcher.match(node); | ||
} | ||
|
||
} |
Oops, something went wrong.