diff options
author | Vincent Lorenzo | 2019-11-15 13:36:36 +0000 |
---|---|---|
committer | vincent lorenzo | 2019-11-26 15:20:26 +0000 |
commit | 96d9e273af029deb22d5e2c5424216a6d05bac37 (patch) | |
tree | 8e67f0c0ee33df0652a58cd4e252b75d2884637c | |
parent | be7459bf6df5502217bed267045b9b9b18e8482a (diff) | |
download | org.eclipse.papyrus-96d9e273af029deb22d5e2c5424216a6d05bac37.tar.gz org.eclipse.papyrus-96d9e273af029deb22d5e2c5424216a6d05bac37.tar.xz org.eclipse.papyrus-96d9e273af029deb22d5e2c5424216a6d05bac37.zip |
Bug 553100: [Xtext][API] we must be able to save invalid string directly in the edited field when it is a string field
- create new interface IXtextDirectEditorConfiguration
- create new class AbstractDirectEditorConfiguration
- create new class DefaultXtextParser
- set DefaultXTextDirectEditorConfiguration as deprecated
Change-Id: I6335276c7f0c72dd0369e25cb51469595b1e3475
Signed-off-by: Vincent Lorenzo <vincent.lorenzo@cea.fr>
6 files changed, 399 insertions, 5 deletions
diff --git a/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/META-INF/MANIFEST.MF b/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/META-INF/MANIFEST.MF index e2f2a91e895..13714500c35 100644 --- a/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/META-INF/MANIFEST.MF +++ b/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/META-INF/MANIFEST.MF @@ -10,8 +10,8 @@ Require-Bundle: org.eclipse.xtext.ui;bundle-version="[2.10.0,3.0.0)";visibility: org.eclipse.papyrus.uml.extensionpoints;bundle-version="[1.2.0,2.0.0)", org.eclipse.papyrus.infra.services.validation;bundle-version="[3.0.0,4.0.0)" Bundle-Vendor: Eclipse Modeling Project -Bundle-Version: 2.1.0.qualifier -Bundle-Name: GMF Xtext Integration +Bundle-Version: 2.2.0.qualifier +Bundle-Name: Papyrus GMF Xtext Integration Bundle-Activator: org.eclipse.papyrus.uml.xtext.integration.ui.Activator Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.eclipse.papyrus.uml.xtext.integration.ui;singleton:=true diff --git a/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/pom.xml b/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/pom.xml index 11d2e16d7de..dd447f89ae2 100644 --- a/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/pom.xml +++ b/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/pom.xml @@ -9,6 +9,6 @@ <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>org.eclipse.papyrus.uml.xtext.integration.ui</artifactId> - <version>2.1.0-SNAPSHOT</version> + <version>2.2.0-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> </project>
\ No newline at end of file diff --git a/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/src/org/eclipse/papyrus/uml/xtext/integration/AbstractXtextDirectEditorConfiguration.java b/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/src/org/eclipse/papyrus/uml/xtext/integration/AbstractXtextDirectEditorConfiguration.java new file mode 100755 index 00000000000..de7af26eae0 --- /dev/null +++ b/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/src/org/eclipse/papyrus/uml/xtext/integration/AbstractXtextDirectEditorConfiguration.java @@ -0,0 +1,82 @@ +/***************************************************************************** + * Copyright (c) 2019 CEA LIST. + * + * All rights reserved. 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 + * + * Contributors: + * Vincent Lorenzo (CEA-LIST) vincent.lorenzo@cea.fr - Initial API and implementation + *****************************************************************************/ +package org.eclipse.papyrus.uml.xtext.integration; + +import java.util.List; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource.Diagnostic; +import org.eclipse.gmf.runtime.common.core.command.ICommand; +import org.eclipse.gmf.runtime.common.ui.services.parser.IParser; +import org.eclipse.papyrus.infra.gmfdiag.extensionpoints.editors.configuration.IDirectEditorConfiguration; +import org.eclipse.xtext.parser.IParseResult; +import org.eclipse.xtext.validation.Issue; + +/** + * This class must be implemented to provide Xtext editor configuration + * + * @since 2.2 + */ +public abstract class AbstractXtextDirectEditorConfiguration extends DefaultXtextDirectEditorConfiguration implements IXtextDirectEditorConfiguration { + + + /** + * @param newString + * @param semanticObject + * @param parseResult + * @param errors + * @param issues + * @return + */ + @Override + public ICommand createInvalidStringCommand(final String invalidString, final EObject semanticElement, final IParseResult parseResult, final List<Diagnostic> diagnostics, final List<Issue> issues) { + return super.createInvalidStringCommand(invalidString, semanticElement, parseResult, diagnostics, issues); + } + + /** + * + * @see org.eclipse.papyrus.uml.xtext.integration.DefaultXtextDirectEditorConfiguration#getTextToEditInternal(org.eclipse.emf.ecore.EObject) + * + * @param semanticObject + * @return + */ + @Override + public String getTextToEditInternal(final EObject semanticObject) { + return super.getTextToEditInternal(semanticObject); + } + + /** + * Adapts {@link IDirectEditorConfiguration} to gmfs {@link IParser} interface for reuse in GMF direct editing infrastructure. + * + * @param semanticEObject + * the edited EObject + */ + @Override + public final IParser createParser(final EObject semanticEObject) { + if (objectToEdit == null) { + objectToEdit = semanticEObject; + } + return doCreateParser(semanticEObject); + } + + /** + * @param semanticEObject + * the edited EObject + * + * @return + */ + protected IParser doCreateParser(final EObject semanticEObject) { + return new DefaultXtextParser(this, semanticEObject); + } +} diff --git a/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/src/org/eclipse/papyrus/uml/xtext/integration/DefaultXtextDirectEditorConfiguration.java b/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/src/org/eclipse/papyrus/uml/xtext/integration/DefaultXtextDirectEditorConfiguration.java index 67e3dc9136e..767c77dbe55 100644..100755 --- a/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/src/org/eclipse/papyrus/uml/xtext/integration/DefaultXtextDirectEditorConfiguration.java +++ b/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/src/org/eclipse/papyrus/uml/xtext/integration/DefaultXtextDirectEditorConfiguration.java @@ -80,7 +80,9 @@ import com.google.inject.name.Names; * @author andreas muelder - Initial contribution and API * Ansgar Radermacher - Added possibility to configure context provider * + * @deprecated since 2.2 use {@link AbstractXtextDirectEditorConfiguration} instead */ +@Deprecated public abstract class DefaultXtextDirectEditorConfiguration extends DefaultDirectEditorConfiguration implements ICustomDirectEditorConfiguration { public static final String ANNOTATION_SOURCE = "expression_source"; //$NON-NLS-1$ @@ -231,7 +233,7 @@ public abstract class DefaultXtextDirectEditorConfiguration extends DefaultDirec * @param semanticElement * the edited element * @return - * the command saving the invalid string in a stereotyped comment + * the command saving the invalid string in a stereotyped comment * @deprecated since 2.1 */ @Deprecated @@ -252,7 +254,7 @@ public abstract class DefaultXtextDirectEditorConfiguration extends DefaultDirec * @param issues * the issues found by the resource validator * @return - * the command saving the invalid string in a stereotyped comment. The command result contains contains a {@link XTextStringValidationResult} owning informations about the invalid string + * the command saving the invalid string in a stereotyped comment. The command result contains contains a {@link XTextStringValidationResult} owning informations about the invalid string * @since 2.1 */ protected ICommand createInvalidStringCommand(final String invalidString, final EObject semanticElement, final IParseResult parseResult, final List<Diagnostic> diagnostics, final List<Issue> issues) { diff --git a/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/src/org/eclipse/papyrus/uml/xtext/integration/DefaultXtextParser.java b/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/src/org/eclipse/papyrus/uml/xtext/integration/DefaultXtextParser.java new file mode 100755 index 00000000000..70a23f2c227 --- /dev/null +++ b/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/src/org/eclipse/papyrus/uml/xtext/integration/DefaultXtextParser.java @@ -0,0 +1,224 @@ +/***************************************************************************** + * Copyright (c) 2019 CEA LIST and others. + * + * All rights reserved. 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 + * http://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.xtext.integration; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource.Diagnostic; +import org.eclipse.gmf.runtime.common.core.command.CompositeCommand; +import org.eclipse.gmf.runtime.common.core.command.ICommand; +import org.eclipse.gmf.runtime.common.ui.services.parser.IParser; +import org.eclipse.gmf.runtime.common.ui.services.parser.IParserEditStatus; +import org.eclipse.jface.text.contentassist.IContentAssistProcessor; +import org.eclipse.papyrus.infra.services.validation.commands.AbstractValidateCommand; +import org.eclipse.papyrus.infra.services.validation.commands.AsyncValidateSubtreeCommand; +import org.eclipse.papyrus.uml.xtext.integration.core.ContextElementAdapter; +import org.eclipse.papyrus.uml.xtext.integration.core.ContextElementAdapter.IContextElementProvider; +import org.eclipse.papyrus.uml.xtext.integration.core.ContextElementAdapter.IContextElementProviderWithInit; +import org.eclipse.uml2.uml.OpaqueBehavior; +import org.eclipse.xtext.EcoreUtil2; +import org.eclipse.xtext.parser.IParseResult; +import org.eclipse.xtext.resource.XtextResource; +import org.eclipse.xtext.util.CancelIndicator; +import org.eclipse.xtext.util.StringInputStream; +import org.eclipse.xtext.validation.CheckMode; +import org.eclipse.xtext.validation.IResourceValidator; +import org.eclipse.xtext.validation.Issue; + +/** + * Default implementation for the parser in a Xtext context. + * This parser allows to check the string validity before to save the String. + * When the string is not valid, the string is saved in a UML Comment, stereotype <<TextualRepresentation>> and owned by the edited element. + * The validation of the string can be ignored setting {@link #ignoreValidationStep} to <code>true</code>. + * In this case, the {@link IXtextDirectEditorConfiguration} must be able to save the string when it is invalid. + * A typical usecase is the editing of String feature (like {@link OpaqueBehavior#body}), because with this usecase, + * it is obvious we can save invalid string directly in the edited field. + * + * @since 2.2 + */ +public class DefaultXtextParser implements IParser { + + /** + * the xtext editor configuration + */ + protected final IXtextDirectEditorConfiguration editorConfiguration; + + /** + * the edited semantic EObject + */ + protected final EObject semanticObject; + + /** + * when <code>true</code>, we won't check the validity of the typed string and we save it in the model + * mainly use when the edited string is set in the text field + */ + protected final boolean ignoreValidationStep; + + /** + * + * Constructor. + * + * @param editorConfiguration + * the editor configuration + * @param semanticEObject + * the edited semanticEObject + */ + public DefaultXtextParser(final IXtextDirectEditorConfiguration editorConfiguration, final EObject semanticEObject) { + this(editorConfiguration, semanticEObject, false); + } + + /** + * + * Constructor. + * + * @param editorConfiguration + * the editor configuration + * @param semanticEObject + * the edited semanticEObject + * @param ignoreValidationStep + * when <code>true</code>, we won't check the validity of the typed string and we save it in the model + * mainly use when the edited string is set in the text field + */ + public DefaultXtextParser(final IXtextDirectEditorConfiguration editorConfiguration, final EObject semanticEObject, final boolean ignoreValidationStep) { + this.editorConfiguration = editorConfiguration; + this.semanticObject = semanticEObject; + this.ignoreValidationStep = ignoreValidationStep; + } + + /** + * + * @see org.eclipse.gmf.runtime.common.ui.services.parser.IParser#getEditString(org.eclipse.core.runtime.IAdaptable, int) + * + * @param element + * @param flags + * @return + */ + @Override + public String getEditString(final IAdaptable element, int flags) { + return this.editorConfiguration.getTextToEditInternal(this.semanticObject); + } + + /** + * + * @see org.eclipse.gmf.runtime.common.ui.services.parser.IParser#getParseCommand(org.eclipse.core.runtime.IAdaptable, java.lang.String, int) + * + * @param element + * @param newString + * @param flags + * @return + */ + @Override + public ICommand getParseCommand(IAdaptable element, String newString, int flags) { + CompositeCommand result = new CompositeCommand("validation"); //$NON-NLS-1$ + IContextElementProvider provider = this.editorConfiguration.getContextProvider(); + XtextFakeResourceContext context = new XtextFakeResourceContext(this.editorConfiguration.getInjector()); + final XtextResource xtextResource = context.getFakeResource(); + xtextResource.eAdapters().add(new ContextElementAdapter(provider)); + + try { + xtextResource.load(new StringInputStream(newString), Collections.EMPTY_MAP); + } catch (IOException e) { + org.eclipse.papyrus.uml.xtext.integration.ui.Activator.log.error(e); + } + if (provider instanceof IContextElementProviderWithInit) { + ((IContextElementProviderWithInit) provider).initResource(context.getFakeResource()); + } + EcoreUtil2.resolveLazyCrossReferences(xtextResource, CancelIndicator.NullImpl); + final IParseResult parseResult = xtextResource.getParseResult(); + if (this.ignoreValidationStep) { + EObject xtextObject = parseResult.getRootASTElement(); + ICommand cmd = this.editorConfiguration.getParseCommand(this.semanticObject, xtextObject); + if (cmd != null) { + result.add(cmd); + } + } else { + final IResourceValidator resVal = xtextResource.getResourceServiceProvider().getResourceValidator(); + final List<Issue> issues = resVal.validate(xtextResource, CheckMode.ALL, CancelIndicator.NullImpl); + final List<Diagnostic> errors = context.getFakeResource().getErrors(); + if (!parseResult.hasSyntaxErrors() && errors.size() == 0 && issues.size() == 0) { + EObject xtextObject = parseResult.getRootASTElement(); + ICommand cmd = this.editorConfiguration.getParseCommand(this.semanticObject, xtextObject); + if (cmd != null) { + result.add(cmd); + } + } else { + result.add(this.editorConfiguration.createInvalidStringCommand(newString, this.semanticObject, parseResult, errors, issues)); + } + AbstractValidateCommand validationCommand = new AsyncValidateSubtreeCommand(this.semanticObject); + validationCommand.disableUIFeedback(); + result.add(validationCommand); + } + return result; + } + + /** + * + * @see org.eclipse.gmf.runtime.common.ui.services.parser.IParser#getPrintString(org.eclipse.core.runtime.IAdaptable, int) + * + * @param element + * @param flags + * @return + */ + @Override + public String getPrintString(IAdaptable element, int flags) { + return this.editorConfiguration.getTextToEdit(this.semanticObject); + } + + /** + * + * @see org.eclipse.gmf.runtime.common.ui.services.parser.IParser#isAffectingEvent(java.lang.Object, int) + * + * @param event + * @param flags + * @return + */ + @Override + public boolean isAffectingEvent(Object event, int flags) { + return false; + } + + /** + * + * @see org.eclipse.gmf.runtime.common.ui.services.parser.IParser#getCompletionProcessor(org.eclipse.core.runtime.IAdaptable) + * + * @param element + * @return + */ + @Override + public IContentAssistProcessor getCompletionProcessor(IAdaptable element) { + // Not used + return null; + } + + /** + * + * @see org.eclipse.gmf.runtime.common.ui.services.parser.IParser#isValidEditString(org.eclipse.core.runtime.IAdaptable, java.lang.String) + * + * @param element + * @param editString + * @return + */ + @Override + public IParserEditStatus isValidEditString(IAdaptable element, String editString) { + // Not used + return null; + } + +} diff --git a/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/src/org/eclipse/papyrus/uml/xtext/integration/IXtextDirectEditorConfiguration.java b/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/src/org/eclipse/papyrus/uml/xtext/integration/IXtextDirectEditorConfiguration.java new file mode 100755 index 00000000000..3ea8ccd814b --- /dev/null +++ b/plugins/uml/xtext/org.eclipse.papyrus.uml.xtext.integration.ui/src/org/eclipse/papyrus/uml/xtext/integration/IXtextDirectEditorConfiguration.java @@ -0,0 +1,86 @@ +/***************************************************************************** + * Copyright (c) 2019 CEA LIST and others. + * + * All rights reserved. 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 + * http://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Vincent Lorenzo (CEA LIST) vincent.lorenzo@cea.fr - Initial API and implementation + * + *****************************************************************************/ + +package org.eclipse.papyrus.uml.xtext.integration; + +import java.util.List; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.resource.Resource.Diagnostic; +import org.eclipse.gmf.runtime.common.core.command.ICommand; +import org.eclipse.papyrus.infra.gmfdiag.extensionpoints.editors.configuration.ICustomDirectEditorConfiguration; +import org.eclipse.papyrus.uml.xtext.integration.core.ContextElementAdapter.IContextElementProvider; +import org.eclipse.xtext.parser.IParseResult; +import org.eclipse.xtext.validation.Issue; + +import com.google.inject.Injector; + +/** + * Specific direct editor confirguration for Xtext + * + * @since 2.2 + * + */ +public interface IXtextDirectEditorConfiguration extends ICustomDirectEditorConfiguration { + + /** + * @param semanticObject + * the semantic element + * @return + * the text to edit or the string value owned by the owned comment stereotyped <<TextualRepresentation>> when the previous edition set an invalid string + */ + String getTextToEditInternal(EObject semanticObject); + + /** + * + * Used when the edited object is not equal to the context element + * + * @return + * the context element + */ + IContextElementProvider getContextProvider(); + + /** + * @return + * the injector to use to load the Xtext grammar + */ + Injector getInjector(); + + /** + * @param semanticObject + * @param xtextObject + * to get the string typed by the user, you can do NodeModelUtils.getNode(xtextObject).getText(); + * @return + */ + ICommand getParseCommand(EObject semanticObject, EObject xtextObject); + + /** + * + * @param invalidString + * the invalid string entered by the user + * @param semanticElement + * the edited element + * @param parseResult + * the result of the parsing + * @param diagnostics + * the errors in the resource (provided by the EMF resource + * @param issues + * the list if the {@link Issue} in the invalid string + * @return + * the command to use when the string is invalid + */ + public ICommand createInvalidStringCommand(final String invalidString, final EObject semanticElement, final IParseResult parseResult, final List<Diagnostic> diagnostics, final List<Issue> issues); + +} |