Skip to content

Commit

Permalink
Provide basic experimental formatter which supports invalid XML
Browse files Browse the repository at this point in the history
Fixes eclipse#1195

Signed-off-by: azerr <azerr@redhat.com>
  • Loading branch information
angelozerr committed Apr 20, 2022
1 parent 6113791 commit a950ec2
Show file tree
Hide file tree
Showing 24 changed files with 5,286 additions and 823 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -323,27 +323,17 @@ public CompletableFuture<List<Either<SymbolInformation, DocumentSymbol>>> docume

@Override
public CompletableFuture<List<? extends TextEdit>> formatting(DocumentFormattingParams params) {
return computeAsync((cancelChecker) -> {
String uri = params.getTextDocument().getUri();
TextDocument document = getDocument(uri);
if (document == null) {
return null;
}
return computeDOMAsync(params.getTextDocument(), (cancelChecker, xmlDocument) -> {
CompositeSettings settings = new CompositeSettings(getSharedSettings(), params.getOptions());
return getXMLLanguageService().format(document, null, settings);
return getXMLLanguageService().format(xmlDocument, null, settings);
});
}

@Override
public CompletableFuture<List<? extends TextEdit>> rangeFormatting(DocumentRangeFormattingParams params) {
return computeAsync((cancelChecker) -> {
String uri = params.getTextDocument().getUri();
TextDocument document = getDocument(uri);
if (document == null) {
return null;
}
return computeDOMAsync(params.getTextDocument(), (cancelChecker, xmlDocument) -> {
CompositeSettings settings = new CompositeSettings(getSharedSettings(), params.getOptions());
return getXMLLanguageService().format(document, params.getRange(), settings);
return getXMLLanguageService().format(xmlDocument, params.getRange(), settings);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,12 @@ public String lineText(int lineNumber) throws BadLocationException {
return text.substring(line.offset, line.offset + line.length);
}

public int lineOffsetAt(int position) throws BadLocationException {
ILineTracker lineTracker = getLineTracker();
Line line = lineTracker.getLineInformationOfOffset(position);
return line.offset;
}

public String lineDelimiter(int lineNumber) throws BadLocationException {
ILineTracker lineTracker = getLineTracker();
String lineDelimiter = lineTracker.getLineDelimiter(lineNumber);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
package org.eclipse.lemminx.dom;

import org.eclipse.lemminx.utils.StringUtils;
import org.w3c.dom.DOMException;

/**
Expand Down Expand Up @@ -61,7 +62,8 @@ public String getWholeText() {
*/
@Override
public boolean isElementContentWhitespace() {
throw new UnsupportedOperationException();
String text = getOwnerDocument().getOwnerDocument().getText();
return StringUtils.isWhitespace(text, getStart(), getEnd());
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.eclipse.lemminx.extensions.contentmodel.participants.ContentModelCodeLensParticipant;
import org.eclipse.lemminx.extensions.contentmodel.participants.ContentModelCompletionParticipant;
import org.eclipse.lemminx.extensions.contentmodel.participants.ContentModelDocumentLinkParticipant;
import org.eclipse.lemminx.extensions.contentmodel.participants.ContentModelFormatterParticipant;
import org.eclipse.lemminx.extensions.contentmodel.participants.ContentModelHoverParticipant;
import org.eclipse.lemminx.extensions.contentmodel.participants.ContentModelSymbolsProviderParticipant;
import org.eclipse.lemminx.extensions.contentmodel.participants.ContentModelTypeDefinitionParticipant;
Expand Down Expand Up @@ -85,6 +86,8 @@ public class ContentModelPlugin implements IXMLExtension {

private DocumentTelemetryParticipant documentTelemetryParticipant;

private ContentModelFormatterParticipant formatterParticipant;

public ContentModelPlugin() {
completionParticipant = new ContentModelCompletionParticipant();
hoverParticipant = new ContentModelHoverParticipant();
Expand Down Expand Up @@ -207,7 +210,9 @@ public void start(InitializeParams params, XMLExtensionsRegistry registry) {
documentTelemetryParticipant = new DocumentTelemetryParticipant(registry.getTelemetryManager(),
contentModelManager);
registry.registerDocumentLifecycleParticipant(documentTelemetryParticipant);

formatterParticipant = new ContentModelFormatterParticipant(contentModelManager);
registry.registerFormatterParticipant(formatterParticipant);

// Register custom commands to re-validate XML files
IXMLCommandService commandService = registry.getCommandService();
if (commandService != null) {
Expand Down Expand Up @@ -236,7 +241,8 @@ public void stop(XMLExtensionsRegistry registry) {
registry.unregisterSymbolsProviderParticipant(symbolsProviderParticipant);
registry.unregisterCodeLensParticipant(codeLensParticipant);
registry.unregisterDocumentLifecycleParticipant(documentTelemetryParticipant);

registry.unregisterFormatterParticipant(formatterParticipant);

// Un-register custom commands to re-validate XML files
IXMLCommandService commandService = registry.getCommandService();
if (commandService != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,8 @@ default String getName(String prefix) {
*/
String getDocumentURI();

boolean isStringType();

boolean isMixedContent();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.eclipse.lemminx.extensions.contentmodel.participants;

import java.util.Collection;

import org.eclipse.lemminx.dom.DOMElement;
import org.eclipse.lemminx.extensions.contentmodel.model.CMDocument;
import org.eclipse.lemminx.extensions.contentmodel.model.CMElementDeclaration;
import org.eclipse.lemminx.extensions.contentmodel.model.ContentModelManager;
import org.eclipse.lemminx.services.extensions.format.IFormatterParticipant;
import org.eclipse.lemminx.services.format.FormatElementCategory;
import org.eclipse.lemminx.services.format.XMLFormattingConstraints;
import org.eclipse.lemminx.settings.SharedSettings;

public class ContentModelFormatterParticipant implements IFormatterParticipant {

private static final String GRAMMAR_AWARE_FORMATTING = "grammarAwareFormatting";

private final ContentModelManager contentModelManager;

public ContentModelFormatterParticipant(ContentModelManager contentModelManager) {
this.contentModelManager = contentModelManager;
}

@Override
public FormatElementCategory getFormatElementCategory(DOMElement element,
XMLFormattingConstraints parentConstraints, SharedSettings sharedSettings) {
Boolean enabled = sharedSettings.getFormattingSettings().getBoolean(GRAMMAR_AWARE_FORMATTING);
if (enabled != null && !enabled) {
return null;
}

Collection<CMDocument> cmDocuments = contentModelManager.findCMDocument(element);
for (CMDocument cmDocument : cmDocuments) {
CMElementDeclaration cmElement = cmDocument.findCMElement(element);
if (cmElement != null) {
if (cmElement.isStringType()) {
return FormatElementCategory.PreserveSpace;
}
if (cmElement.isMixedContent()) {
return FormatElementCategory.MixedContent;
}
}
}
return null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,14 @@ public int getIndex() {
public String getDocumentURI() {
return document.getURI();
}

@Override
public boolean isStringType() {
return false;
}

@Override
public boolean isMixedContent() {
return super.type == XMLElementDecl.TYPE_MIXED;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.Map;
import java.util.Vector;

import org.apache.xerces.impl.dv.XSSimpleType;
import org.apache.xerces.impl.dv.xs.XSSimpleTypeDecl;
import org.apache.xerces.impl.xs.SchemaGrammar;
import org.apache.xerces.impl.xs.SubstitutionGroupHandler;
Expand Down Expand Up @@ -202,11 +203,11 @@ public Collection<CMElementDeclaration> getPossibleElements(DOMElement parentEle
/**
* Returns the possible elements declaration if the given declaration is an
* xs:any and null otherwise.
*
*
* @param declaration the element, wildcard declaration.
* @return the possible elements declaration if the given declaration is an
* xs:any and null otherwise.
*
*
*/
private Collection<CMElementDeclaration> getXSAnyElements(Object declaration) {
short processContents = getXSAnyProcessContents(declaration);
Expand All @@ -230,7 +231,7 @@ private Collection<CMElementDeclaration> getXSAnyElements(Object declaration) {
/**
* Returns the value of the xs:any/@processContents if the given element is a
* xs:any and {@link #PC_UNKWOWN} otherwise.
*
*
* @param declaration the element, wildcard declaration.
* @return the value of the xs:any/@processContents if the given element is a
* xs:any and {@link #PC_UNKWOWN} otherwise.
Expand All @@ -248,7 +249,7 @@ private static short getXSAnyProcessContents(Object declaration) {
/**
* Returns list of element (QName) of child elements of the given parent element
* upon the given offset
*
*
* @param parentElement the parent element
* @param offset the offset where child element must be belong to
* @return list of element (QName) of child elements of the given parent element
Expand Down Expand Up @@ -355,7 +356,7 @@ public String getDocumentation(ISharedSettingsRequest request) {
/**
* Returns list of xs:annotation from the element declaration or type
* declaration.
*
*
* @return list of xs:annotation from the element declaration or type
* declaration.
*/
Expand Down Expand Up @@ -490,4 +491,27 @@ public String getDocumentURI() {
SchemaGrammar schemaGrammar = document.getOwnerSchemaGrammar(elementDeclaration);
return CMXSDDocument.getSchemaURI(schemaGrammar);
}

@Override
public boolean isStringType() {
XSTypeDefinition typeDefinition = elementDeclaration.getTypeDefinition();
if (typeDefinition != null) {
XSSimpleTypeDefinition simpleDefinition = null;
if (typeDefinition.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
simpleDefinition = (XSSimpleTypeDefinition) typeDefinition;
} else if (typeDefinition.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
simpleDefinition = ((XSComplexTypeDefinition) typeDefinition).getSimpleType();
}
if (simpleDefinition != null) {
return "string".equals(simpleDefinition.getName());
}
}
return false;
}

@Override
public boolean isMixedContent() {
// TODO Auto-generated method stub
return false;
}
}
Loading

0 comments on commit a950ec2

Please sign in to comment.