Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refact: restructure plugin.xml #1176

Merged
merged 3 commits into from
Jan 14, 2025
Merged

Conversation

sebthom
Copy link
Contributor

@sebthom sebthom commented Jan 13, 2025

I tried to add some new UI contributions to the plugin.xml and was overwhelmed by its organically grown structure. To address this, I reorganized the file to improve readability and maintainability. I grouped configuration elements by feature, such as outline toolbar contributions, code folding, find references support, and others. This makes it easier to follow the purpose of each section and to contribute new features. For example, adding a new outline toolbar button is now straightforward because all the relevant building blocks are grouped together.

I hope you agree that this refactoring improves the file’s clarity and usability. 🤞


Since the Git diff is not helpful for showing the structural changes, I wrote a small Python script to compare the effective differences between two plugin.xml files. This script allows you to verify that no technical functionality has changed—only the layout has been cleaned up and made more logical.

plugin_xml_diff.py:

/*******************************************************************************
 * Copyright (c) 2025 Sebastian Thomschke and others.
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 * Sebastian Thomschke - initial implementation
 *******************************************************************************/
 import xml.etree.ElementTree as ET

def xml2grepable(xml_file):
    def parse_element(path, element):
        lines = []

        id_attrs = [
            "id", 
            "name", 
            "commandId",      # <handler commandId=... class=... />
            "class", 
            "locationURI",    # <menuContribution locationURI=... allPopups="true" />
            "annotationType"  # <specification annotationType=... />
        ]

        # Determine the identifying attribute
        identifying_attr = ""
        if len(element.attrib) == 1:
            # If there is only one attribute, use it as the ID
            for k, v in element.attrib.items():
                identifying_attr = f"[{k}={v}]"
        else:
            for attr in id_attrs:
                if attr in element.attrib:
                    identifying_attr = f"[{attr}={element.attrib[attr]}]"
                    break

        full_path = f"{path}/{element.tag}{identifying_attr}"

        # Add other non-identifying attributes
        for attr_name, attr_value in element.attrib.items():
            if identifying_attr and attr_name in identifying_attr:
                continue
            lines.append(f"{full_path}[{attr_name}] = {attr_value}")

        # Text
        if element.text and element.text.strip():
            lines.append(f"{full_path}[text()] = '{element.text.strip()}'")

        # Children
        for child in element:
            lines.extend(parse_element(full_path, child))

        return lines

    try:
        tree = ET.parse(xml_file)
        root = tree.getroot()
        root_path = f"/{root.tag}"
        lines = parse_element(root_path, root)

        # Sort and remove duplicates
        sorted_unique_lines = sorted(set(lines))
        return sorted_unique_lines

    except ET.ParseError as e:
        print(f"Error parsing XML: {e}")
        return []

def diff_grepable_xml(xml_file1, xml_file2):
    lines1 = set(xml2grepable(xml_file1))
    lines2 = set(xml2grepable(xml_file2))

    only_in_file1 = lines1 - lines2
    only_in_file2 = lines2 - lines1

    differences = []
    for line in only_in_file1:
        differences.append(f"- {line}")
    for line in only_in_file2:
        differences.append(f"+ {line}")

    # Sort the differences by the actual line content, ignoring the prefix
    return sorted(differences, key=lambda x: x[2:])

if __name__ == "__main__":
    import argparse

    parser = argparse.ArgumentParser(description="Compare two Eclipse Plugin XML files and print their differences in a grepable representation.")
    parser.add_argument("xml_file1", help="Path to the first Eclipse plugin.xml file.")
    parser.add_argument("xml_file2", help="Path to the second Eclipse plugin.xml file.")

    args = parser.parse_args()

    differences = diff_grepable_xml(args.xml_file1, args.xml_file2)

    if differences:
        for line in differences:
            print(line)
    else:
        print("No structural differences found between the two plugin.xml files.")

@sebthom sebthom merged commit e3b9cce into eclipse-lsp4e:main Jan 14, 2025
6 checks passed
@sebthom sebthom deleted the plugin.xml branch January 15, 2025 10:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants