Skip to content

Commit

Permalink
Grammar generator from XML
Browse files Browse the repository at this point in the history
Fixes eclipse-lemminx#778

Signed-off-by: azerr <azerr@redhat.com>
  • Loading branch information
angelozerr committed Jun 19, 2020
1 parent ce1a2ad commit 3f40d90
Show file tree
Hide file tree
Showing 41 changed files with 1,860 additions and 155 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

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;

/**
Expand All @@ -24,11 +23,6 @@ public class XMLCatalogPlugin implements IXMLExtension {

private XMLCatalogURIResolverExtension uiResolver;

@Override
public void doSave(ISaveContext context) {

}

@Override
public void start(InitializeParams params, XMLExtensionsRegistry registry) {
uiResolver = new XMLCatalogURIResolverExtension(registry);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ private void registerCodeActionsIfNeeded(SharedSettings sharedSettings) {
return;
}
XMLSyntaxErrorCode.registerCodeActionParticipants(codeActionParticipants);
DTDErrorCode.registerCodeActionParticipants(codeActionParticipants);
DTDErrorCode.registerCodeActionParticipants(codeActionParticipants, sharedSettings);
XMLSchemaErrorCode.registerCodeActionParticipants(codeActionParticipants, sharedSettings);
XSDErrorCode.registerCodeActionParticipants(codeActionParticipants);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,15 @@
import org.eclipse.lemminx.dom.DOMElement;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.ElementDeclUnterminatedCodeAction;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.EntityNotDeclaredCodeAction;
import org.eclipse.lemminx.extensions.contentmodel.participants.codeactions.dtd_not_foundCodeAction;
import org.eclipse.lemminx.services.extensions.ICodeActionParticipant;
import org.eclipse.lemminx.services.extensions.diagnostics.IXMLErrorCode;
import org.eclipse.lemminx.settings.SharedSettings;
import org.eclipse.lemminx.utils.XMLPositionUtility;
import org.eclipse.lemminx.utils.XMLPositionUtility.EntityReferenceRange;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.ResourceOperationKind;

/**
* DTD error code.
Expand Down Expand Up @@ -200,8 +203,12 @@ public static Range toLSPRange(XMLLocator location, DTDErrorCode code, Object[]
return null;
}

public static void registerCodeActionParticipants(Map<String, ICodeActionParticipant> codeActions) {
public static void registerCodeActionParticipants(Map<String, ICodeActionParticipant> codeActions,
SharedSettings sharedSettings) {
codeActions.put(ElementDeclUnterminated.getCode(), new ElementDeclUnterminatedCodeAction());
codeActions.put(EntityNotDeclared.getCode(), new EntityNotDeclaredCodeAction());
if (sharedSettings.getWorkspaceSettings().isResourceOperationSupported(ResourceOperationKind.Create)) {
codeActions.put(dtd_not_found.getCode(), new dtd_not_foundCodeAction());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,7 @@ public static void registerCodeActionParticipants(Map<String, ICodeActionPartici
codeActions.put(cvc_enumeration_valid.getCode(), new cvc_enumeration_validCodeAction());
codeActions.put(cvc_complex_type_2_1.getCode(), new cvc_complex_type_2_1CodeAction());
codeActions.put(TargetNamespace_1.getCode(), new TargetNamespace_1CodeAction());
codeActions.put(TargetNamespace_2.getCode(), new TargetNamespace_2CodeAction());

codeActions.put(TargetNamespace_2.getCode(), new TargetNamespace_2CodeAction());
if (sharedSettings.getWorkspaceSettings().isResourceOperationSupported(ResourceOperationKind.Create)) {
codeActions.put(schema_reference_4.getCode(), new schema_reference_4CodeAction());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*******************************************************************************
* Copyright (c) 2020 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
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.lemminx.extensions.contentmodel.participants.codeactions;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import org.eclipse.lemminx.commons.CodeActionFactory;
import org.eclipse.lemminx.dom.DOMDocument;
import org.eclipse.lemminx.extensions.generators.FileContentGeneratorManager;
import org.eclipse.lemminx.extensions.generators.FileContentGeneratorSettings;
import org.eclipse.lemminx.services.extensions.ICodeActionParticipant;
import org.eclipse.lemminx.services.extensions.IComponentProvider;
import org.eclipse.lemminx.settings.SharedSettings;
import org.eclipse.lemminx.utils.StringUtils;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.Range;

/**
* Code Action which manages missing referenced grammar file (DTD, XSD°
*/
public abstract class AbstractFixMissingGrammarCodeAction implements ICodeActionParticipant {

private static final String FILE_SCHEME = "'file:///";

@Override
public void doCodeAction(Diagnostic diagnostic, Range range, DOMDocument document, List<CodeAction> codeActions,
SharedSettings sharedSettings, IComponentProvider componentProvider) {

String missingFilePath = getPathFromDiagnostic(diagnostic);
if (StringUtils.isEmpty(missingFilePath)) {
return;
}
Path p = Paths.get(missingFilePath);
if (p.toFile().exists()) {
return;
}

// Generate XSD from the DOM doucment
FileContentGeneratorManager generator = componentProvider.getComponent(FileContentGeneratorManager.class);
String schemaTemplate = generator.generate(document, sharedSettings, getFileContentGeneratorSettings());

// Create code action to create the XSD file with the generated XSD content
CodeAction makeSchemaFile = CodeActionFactory.createFile("Generate missing file '" + p.toFile().getName() + "'",
"file:///" + missingFilePath, schemaTemplate, diagnostic);

codeActions.add(makeSchemaFile);
}

/**
* Extract the file to create from the diagnostic. Example diagnostic:
* schema_reference.4: Failed to read schema document
* 'file:///home/dthompson/Documents/TestFiles/potationCoordination.xsd',
* because 1) could not find the document; 2) the document could not be read; 3)
* the root element of the document is not <xsd:schema>.
*/
private String getPathFromDiagnostic(Diagnostic diagnostic) {
String message = diagnostic.getMessage();
int startIndex = message.indexOf(FILE_SCHEME);
if (startIndex != -1) {
int endIndex = message.indexOf("'", startIndex + 1);
return message.substring(startIndex + FILE_SCHEME.length(), endIndex);
}

return null;
}

/**
* Returns the grammar settings used to generate the missing grammar file(XSD,
* DTD).
*
* @return the grammar settings used to generate the missing grammar file(XSD,
* DTD).
*/
protected abstract FileContentGeneratorSettings getFileContentGeneratorSettings();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*******************************************************************************
* Copyright (c) 2020 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
*
* Contributors:
* Red Hat Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.lemminx.extensions.contentmodel.participants.codeactions;

import org.eclipse.lemminx.extensions.generators.FileContentGeneratorSettings;
import org.eclipse.lemminx.extensions.generators.xml2dtd.DTDGeneratorSettings;

/**
* Code Action that creates a DTD file referenced with System ID of DOCTYPE.
*/
public class dtd_not_foundCodeAction extends AbstractFixMissingGrammarCodeAction {

@Override
protected FileContentGeneratorSettings getFileContentGeneratorSettings() {
return new DTDGeneratorSettings();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,65 +9,17 @@
*******************************************************************************/
package org.eclipse.lemminx.extensions.contentmodel.participants.codeactions;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.lemminx.commons.CodeActionFactory;
import org.eclipse.lemminx.dom.DOMDocument;
import org.eclipse.lemminx.services.extensions.ICodeActionParticipant;
import org.eclipse.lemminx.services.extensions.IComponentProvider;
import org.eclipse.lemminx.settings.SharedSettings;
import org.eclipse.lemminx.utils.StringUtils;
import org.eclipse.lsp4j.CodeAction;
import org.eclipse.lsp4j.Diagnostic;
import org.eclipse.lsp4j.Range;
import org.eclipse.lemminx.extensions.generators.FileContentGeneratorSettings;
import org.eclipse.lemminx.extensions.generators.xml2xsd.XMLSchemaGeneratorSettings;

/**
* Code Action that creates a schema file referenced by
* xsi:noNamespaceSchemaLocation if it is missing
*/
public class schema_reference_4CodeAction implements ICodeActionParticipant {

private static final Pattern PATH_FINDING_REGEX = Pattern.compile("[^']+'file:///(.+)',.*");
public class schema_reference_4CodeAction extends AbstractFixMissingGrammarCodeAction {

@Override
public void doCodeAction(Diagnostic diagnostic, Range range, DOMDocument document, List<CodeAction> codeActions,
SharedSettings sharedSettings, IComponentProvider componentProvider) {

String missingFilePath = getPathFromDiagnostic(diagnostic);
if (StringUtils.isEmpty(missingFilePath)) {
return;
}
Path p = Paths.get(missingFilePath);
if (p.toFile().exists()) {
return;
}

// TODO: use the generator
String schemaTemplate = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n\n</xs:schema>";

CodeAction makeSchemaFile = CodeActionFactory.createFile("Generate missing file '" + p.toFile().getName() + "'",
"file:///" + missingFilePath, schemaTemplate, diagnostic);

codeActions.add(makeSchemaFile);
}

/**
* Extract the file to create from the diagnostic. Example diagnostic:
* schema_reference.4: Failed to read schema document
* 'file:///home/dthompson/Documents/TestFiles/potationCoordination.xsd',
* because 1) could not find the document; 2) the document could not be read; 3)
* the root element of the document is not <xsd:schema>.
*/
private String getPathFromDiagnostic(Diagnostic diagnostic) {
Matcher m = PATH_FINDING_REGEX.matcher(diagnostic.getMessage());
if (m.find()) {
return m.group(1);
}
return null;
protected FileContentGeneratorSettings getFileContentGeneratorSettings() {
return new XMLSchemaGeneratorSettings();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import org.eclipse.lemminx.services.extensions.XMLExtensionsRegistry;
import org.eclipse.lemminx.services.extensions.codelens.ICodeLensParticipant;
import org.eclipse.lemminx.services.extensions.diagnostics.IDiagnosticsParticipant;
import org.eclipse.lemminx.services.extensions.save.ISaveContext;
import org.eclipse.lsp4j.InitializeParams;

/**
Expand All @@ -49,11 +48,6 @@ public DTDPlugin() {
codeLensParticipant = new DTDCodeLensParticipant();
}

@Override
public void doSave(ISaveContext context) {

}

@Override
public void start(InitializeParams params, XMLExtensionsRegistry registry) {
// register DTD content model provider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import org.eclipse.lemminx.services.extensions.IHoverParticipant;
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;

/**
Expand Down Expand Up @@ -51,8 +50,4 @@ public void stop(XMLExtensionsRegistry registry) {
registry.unregisterHoverParticipant(hoverParticipant);
}

@Override
public void doSave(ISaveContext context) {

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import org.eclipse.lemminx.extensions.general.completion.FilePathCompletionParticipant;
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;

/**
Expand All @@ -38,10 +37,4 @@ public void stop(XMLExtensionsRegistry registry) {
registry.unregisterCompletionParticipant(completionParticipant);
}

@Override
public void doSave(ISaveContext context) {

}


}
Loading

0 comments on commit 3f40d90

Please sign in to comment.