Eclipse CDT 扩展 AdapterFactory

Eclipse CDT extend AdapterFactory

我尝试覆盖 CDT ResumeAtLine、MoveToLine、RunToLine 的功能。出于这个原因,我创建了一个自定义的 SuspendResumeAdapterFactory 但它没有加载但编译和运行没有错误。我可能也需要自定义 adaptableType 吗?

这是我的plugin.xml的内容。

  <extension point="org.eclipse.core.runtime.adapters">
      <factory 
            class="my.package.CustomSuspendResumeAdapterFactory" 
            adaptableType="org.eclipse.cdt.dsf.ui.viewmodel.IVMContext">
         <adapter type="org.eclipse.debug.core.model.ISuspendResume"/>
      </factory>
   </extension> 

而这里我的CustomSuspendResumeAdapterFactory这个class是从内存中重建的,不能100%确定语法是否正确,但我想应该很清楚我想做什么。

package my.package;

import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.debug.internal.ui.actions.MoveToLine;
import org.eclipse.cdt.dsf.debug.internal.ui.actions.ResumeAtLine;
import org.eclipse.cdt.dsf.debug.internal.ui.actions.RunToLine;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IAdapterFactory;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.ISuspendResume;

public class CustomSuspendResumeAdapterFactory implements IAdapterFactory {

    static class SuspendResume implements ISuspendResume, IAdaptable {

        private final CustomRunToLine fRunToLine;
        private final CustomMoveToLine fMoveToLine;
        private final CustomResumeAtLine fResumeAtLine;

        SuspendResume(IExecutionDMContext execCtx) {
            fRunToLine = new CustomRunToLine(execCtx);
            fMoveToLine = new CustomMoveToLine(execCtx);
            fResumeAtLine = new CustomResumeAtLine(execCtx);
        }

        @SuppressWarnings("unchecked")
        @Override
        public <T> T getAdapter(Class<T> adapter) {
            if (adapter.isInstance(RunToLine.class)) {
                System.out.println("CUSTOM RUNTOLINE");
                return (T)fRunToLine;
            }
            if (adapter.isInstance(MoveToLine.class)) {
                System.out.println("CUSTOM MOVETOLINE");
                return (T)fMoveToLine;
            }
            if (adapter.isInstance(ResumeToLine.class)) {
                System.out.println("CUSTOM RESUMEATLINE");
                return (T)fResumeAtLine;
            }
            return null;
        }

        @Override
        public boolean canResume() { return false; }
        @Override
        public boolean canSuspend() { return false; }
        // This must return true because the platform
        // RunToLineActionDelegate will only enable the
        // action if we are suspended
        @Override
        public boolean isSuspended() { return true; }
        @Override
        public void resume() throws DebugException {}
        @Override
        public void suspend() throws DebugException {}
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T getAdapter(Object adaptableObject, Class<T> adapterType) {
        if (ISuspendResume.class.equals(adapterType)) {
            if (adaptableObject instanceof IDMVMContext) {
                IExecutionDMContext execDmc = DMContexts.getAncestorOfType(
                    ((IDMVMContext)adaptableObject).getDMContext(),
                    IExecutionDMContext.class);
                // It only makes sense to RunToLine, MoveToLine or
                // ResumeAtLine if we are dealing with a thread, not a container
                if (execDmc != null && !(execDmc instanceof IContainerDMContext)) {
                    return (T)new SuspendResume(execDmc);
                }
            }
        }
        return null;
    }

    @Override
    public Class<?>[] getAdapterList() {
        return new Class[] { ISuspendResume.class };
    }
}

为什么你的代码不是运行

您提供了一个新的适配器工厂,可以转换已处理的对象类型。即你的 plugin.xml 说你可以将 IVMContext 转换为 ISuspendResume。但是 DSF 插件已经提供了这样一个适配器工厂。如果您有一个新的目标类型(如 IMySpecialRunToLine),您可以为此安装一个工厂,它需要 IVMContext 并将其转换为 IMySpecialRunToLine)。

虽然过时了,但如果这是一个新概念,Eclipse Corner Article on Adapter Pattern 可能会有用。

如何自定义运行行实现

如果您想提供运行行的不同实现,您需要提供您自己的org.eclipse.cdt.dsf.debug.service.IRunControl2.runToLine(IExecutionDMContext, String, int, boolean, RequestMonitor)版本。 org.eclipse.cdt.dsf.debug.internal.ui.actions.RunToLine class 只是将 UI 特性(例如 buttons/etc 一些直接提供,一些由核心 eclipse 调试)连接到 DSF 后端的胶水。也就是说,如果您查看 RunToLine 的作用,它实际上所做的就是获取 IRunControl2 服务并在其上调用 runToLine

提供您自己的 IRunControl2 实现的方法是覆盖 org.eclipse.cdt.dsf.gdb.service.GdbDebugServicesFactory.createRunControlService(DsfSession) 并通过覆盖 org.eclipse.cdt.dsf.gdb.launching.GdbLaunchDelegate.newServiceFactory(ILaunchConfiguration, String)[=26= 在自定义启动委托中提供您自己的 GdbDebugServicesFactory ]

RunToLine 将在用户从编辑器的弹出菜单中 select 运行 行 时触发,如以下屏幕截图所示: