TypeFox / xtext2langium

A tool for migrating an Xtext language to Langium
https://www.typefox.io/blog/xtext-to-langium
MIT License
7 stars 1 forks source link

Transitive search for rule overrides #6

Closed dhuebner closed 1 year ago

dhuebner commented 1 year ago

As we can't override super-grammar rules, we need to lookup all the sub-grammars for duplicate rule names and then remove them from the super grammar. Right now only the first level is inspected.

steve-hickman-epistimis commented 1 year ago

I don't think you can just remove the super grammar rules. You have to ensure that the generated types still have an equivalent type hierarchy. Consider the following: This XText grammar (UDDL) contains Taxonomy and LogicalEnumeratedBase, which generate the following interfaces:

/**
 * generated by Xtext 2.32.0
 * Copyright (c) 2022, 2023 Epistimis LLC (http://www.epistimis.com).
 */
package com.epistimis.uddl.uddl;

import org.eclipse.emf.ecore.EObject;

/**
 * <!-- begin-user-doc -->
 * A representation of the model object '<em><b>Taxonomy</b></em>'.
 * <!-- end-user-doc -->
 *
 *
 * @see com.epistimis.uddl.uddl.UddlPackage#getTaxonomy()
 * @model
 * @generated
 */
public interface Taxonomy extends EObject
{
} // Taxonomy

and

/**
 * generated by Xtext 2.32.0
 * Copyright (c) 2022, 2023 Epistimis LLC (http://www.epistimis.com).
 */
package com.epistimis.uddl.uddl;

/**
 * <!-- begin-user-doc -->
 * A representation of the model object '<em><b>Logical Enumerated Base</b></em>'.
 * <!-- end-user-doc -->
 *
 *
 * @see com.epistimis.uddl.uddl.UddlPackage#getLogicalEnumeratedBase()
 * @model
 * @generated
 */
public interface LogicalEnumeratedBase extends LogicalValueType, Taxonomy
{
} // LogicalEnumeratedBase

Another XText grammar in my stack (Privacy) has the following override:

@Override
Taxonomy : //; returns uddl::Taxonomy:
    //LogicalEnumeratedBase
     JurisdictionBase
    | PETBase
    | PurposeBase
    | ProcessingBasisBase
    | RoleBase
    | ExceptionBase
    | InstitutionBase
;

which results in the following generated interfaces:

/**
 * generated by Xtext 2.32.0
 * Copyright (c) 2022, 2023 Epistimis LLC (http://www.epistimis.com).
 */
package com.epistimis.privacy.privacy;

/**
 * <!-- begin-user-doc -->
 * A representation of the model object '<em><b>Institution Base</b></em>'.
 * <!-- end-user-doc -->
 *
 *
 * @see com.epistimis.privacy.privacy.PrivacyPackage#getInstitutionBase()
 * @model
 * @generated
 */
public interface InstitutionBase extends Taxonomy
{
} // InstitutionBase

and

/**
 * generated by Xtext 2.32.0
 * Copyright (c) 2022, 2023 Epistimis LLC (http://www.epistimis.com).
 */
package com.epistimis.privacy.privacy;

/**
 * <!-- begin-user-doc -->
 * A representation of the model object '<em><b>Taxonomy</b></em>'.
 * <!-- end-user-doc -->
 *
 * <p>
 * The following features are supported:
 * </p>
 * <ul>
 *   <li>{@link com.epistimis.privacy.privacy.Taxonomy#getName <em>Name</em>}</li>
 *   <li>{@link com.epistimis.privacy.privacy.Taxonomy#getDescription <em>Description</em>}</li>
 * </ul>
 *
 * @see com.epistimis.privacy.privacy.PrivacyPackage#getTaxonomy()
 * @model
 * @generated
 */
public interface Taxonomy extends com.epistimis.uddl.uddl.Taxonomy
{
  /**
   * Returns the value of the '<em><b>Name</b></em>' attribute.
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @return the value of the '<em>Name</em>' attribute.
   * @see #setName(String)
   * @see com.epistimis.privacy.privacy.PrivacyPackage#getTaxonomy_Name()
   * @model
   * @generated
   */
  String getName();

  /**
   * Sets the value of the '{@link com.epistimis.privacy.privacy.Taxonomy#getName <em>Name</em>}' attribute.
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @param value the new value of the '<em>Name</em>' attribute.
   * @see #getName()
   * @generated
   */
  void setName(String value);

  /**
   * Returns the value of the '<em><b>Description</b></em>' attribute.
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @return the value of the '<em>Description</em>' attribute.
   * @see #setDescription(String)
   * @see com.epistimis.privacy.privacy.PrivacyPackage#getTaxonomy_Description()
   * @model
   * @generated
   */
  String getDescription();

  /**
   * Sets the value of the '{@link com.epistimis.privacy.privacy.Taxonomy#getDescription <em>Description</em>}' attribute.
   * <!-- begin-user-doc -->
   * <!-- end-user-doc -->
   * @param value the new value of the '<em>Description</em>' attribute.
   * @see #getDescription()
   * @generated
   */
  void setDescription(String value);

} // Taxonomy

among others.

Note that everything inherits from com.epistimis.uddl.uddl.Taxonomy. That means that I can have common code (Java Generics in this case) that can process both the taxonomy classes from Uddl and those from Privacy.

If you just remove the super classes, will it break the equivalent capability in TS/JS?

steve-hickman-epistimis commented 1 year ago

In addition, there is the issue of references to the super grammar rule. If you delete the super grammar rule, then anything in the super grammar that had referenced a now deleted rule will now reference .... what?

dhuebner commented 1 year ago

@steve-hickman-epistimis Overwriting rules is not supported in Langium. By default the super Grammar rules are not removed, but can, when enabling removeOverridenRules option. See https://github.com/TypeFox/xtext2langium#fragment-options

Handling rule overwrites is complicated in Xtext and can't be easily translated to Langium. I don't have a good idea how to automatically translate this Xtext feature to Langium. I think at the end it is up to the user to refactor the grammar so that it doesn't need a rule overwrites.