You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Xtext 2.27.0中实现since块内元素的自动排序?

Xtext 2.27.0实现保存时自动排序Since块内的功能项

要实现保存文件时自动按字典序排序SinceBlock内的Capability项,有两种可靠方案,具体如下:

方案一:保存前修改模型顺序(直接调整内存中模型的元素顺序)

这种方案会在资源保存前自动对SinceBlock的capabilities列表按功能名称排序,序列化时直接使用排序后的顺序输出。

实现步骤

  1. 创建资源监听器,监听资源保存前的事件,遍历模型中的SinceBlock实例并排序其功能项:
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtext.resource.IResourceListener;
import org.eclipse.xtext.resource.ResourceChangeEvent;

public class CapabilitySortingResourceListener implements IResourceListener {

    @Override
    public void resourceChanged(ResourceChangeEvent event) {
        // 仅处理保存前的事件
        if (event.getType() == ResourceChangeEvent.Type.PRE_SAVE) {
            Resource resource = event.getResource();
            for (EObject eObj : resource.getContents()) {
                if (eObj instanceof SinceBlock) {
                    SinceBlock sinceBlock = (SinceBlock) eObj;
                    EList<Capability> capabilities = sinceBlock.getCapabilities();
                    // 按功能名称忽略大小写字典序排序
                    capabilities.sort((cap1, cap2) -> {
                        String name1 = cap1.getFeature().getName();
                        String name2 = cap2.getFeature().getName();
                        return name1.compareToIgnoreCase(name2);
                    });
                }
            }
        }
    }

    // 以下方法默认空实现即可
    @Override
    public void descriptionChanged(org.eclipse.xtext.resource.IResourceDescription.Delta delta) {}
    @Override
    public void resourceDeleted(Resource resource) {}
    @Override
    public void resourceCreated(Resource resource) {}
}
  1. 在Runtime模块中绑定监听器,让Xtext加载这个自定义监听器:
public class YourDslRuntimeModule extends AbstractYourDslRuntimeModule {
    @Override
    public void configure(Binder binder) {
        super.configure(binder);
        binder.bind(IResourceListener.class).to(CapabilitySortingResourceListener.class);
    }
}

方案二:自定义序列化器(不修改模型,仅在输出时排序)

如果不想改变内存中的模型顺序,仅在序列化输出文件时排序,可以通过自定义语义序列器实现,利用Xtext的序列化机制生成排序后的内容。

实现步骤

  1. 自定义语义序列器,继承生成的默认语义序列器,重写SinceBlock的序列化逻辑:
import java.util.ArrayList;
import java.util.List;
import org.eclipse.xtext.serializer.ISerializationContext;
import org.eclipse.xtext.serializer.sequencer.AbstractDelegatingSemanticSequencer;

public class CustomYourDslSemanticSequencer extends YourDslSemanticSequencer {

    @Override
    public void sequence(ISerializationContext context, EObject semanticObject) {
        if (semanticObject instanceof SinceBlock) {
            sequence_SinceBlock(context, (SinceBlock) semanticObject);
            return;
        }
        super.sequence(context, semanticObject);
    }

    protected void sequence_SinceBlock(ISerializationContext context, SinceBlock semanticObject) {
        // 先对功能项排序
        List<Capability> sortedCapabilities = new ArrayList<>(semanticObject.getCapabilities());
        sortedCapabilities.sort((cap1, cap2) -> {
            String name1 = cap1.getFeature().getName();
            String name2 = cap2.getFeature().getName();
            return name1.compareToIgnoreCase(name2);
        });

        // 按语法规则序列化头部
        sequence_OrderedFeature(context, "since", semanticObject.getVersion());
        sequence_Literal(context, "{");
        
        // 序列化排序后的功能项
        for (Capability cap : sortedCapabilities) {
            sequence_Capability(context, cap);
        }
        
        // 序列化尾部
        sequence_Literal(context, "}");
    }
}
  1. 在Runtime模块中绑定自定义序列器:
public class YourDslRuntimeModule extends AbstractYourDslRuntimeModule {
    @Override
    public Class<? extends org.eclipse.xtext.serializer.ISemanticSequencer> bindISemanticSequencer() {
        return CustomYourDslSemanticSequencer.class;
    }
}

注意事项

  • 排序时需确保跨引用的Feature实例已完成加载,避免空指针异常;若存在未加载的情况,可先触发资源加载再执行排序。
  • 方案一修改模型顺序后,编辑器会自动刷新显示排序后的内容;方案二则仅修改输出文件,内存中的模型顺序保持不变。

内容的提问来源于stack exchange,提问作者mspiller

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 13:36:33