Loading plugins/org.etsi.mts.tdl.execution.java/META-INF/MANIFEST.MF +6 −1 Original line number Diff line number Diff line Loading @@ -15,5 +15,10 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.emf.ecore, org.etsi.mts.tdl.model, org.etsi.mts.tdl.execution.java.codegen, junit-jupiter-api junit-jupiter-api, org.eclipse.debug.core, org.eclipse.debug.ui, org.eclipse.jdt.core, org.eclipse.jdt.launching, org.eclipse.xtext plugins/org.etsi.mts.tdl.execution.java/plugin.xml +90 −0 Original line number Diff line number Diff line Loading @@ -62,4 +62,94 @@ </page> </extension> <!-- TODO: update ids ═══════════════════════════════════════════════════════════════ 1. Declare the command ═══════════════════════════════════════════════════════════════ --> <extension point="org.eclipse.ui.commands"> <command defaultHandler="org.etsi.mts.tdl.execution.java.eclipse.commands.RunJUnitTestHandler" id="com.example.tdltx.junitrunner.runJUnitTest" name="Run Specific JUnit Test…" description="Select and run a predefined JUnit test for this .tdltx file"> </command> </extension> <!-- ═══════════════════════════════════════════════════════════════ 2. Bind the command to its handler ═══════════════════════════════════════════════════════════════ --> <extension point="org.eclipse.ui.handlers"> <handler commandId="com.example.tdltx.junitrunner.runJUnitTest" class="org.etsi.mts.tdl.execution.java.eclipse.commands.RunJUnitTestHandler"> <!-- Only active when the active editor has a .tdltx file open --> <activeWhen> <with variable="activeEditorInput"> <adapt type="org.eclipse.core.resources.IFile"> <test property="org.eclipse.core.resources.extension" value="tdltx"/> </adapt> </with> </activeWhen> </handler> </extension> <!-- ═══════════════════════════════════════════════════════════════ 3. Add the menu entry to the editor context menu The editorContribution targets *all* editors; the visibility expression restricts it to .tdltx files. ═══════════════════════════════════════════════════════════════ --> <extension point="org.eclipse.ui.menus"> <!-- Context menu that appears when right-clicking inside any editor --> <menuContribution locationURI="popup:#TextEditorContext?after=group.edit"> <!-- TODO: add icon --> <command commandId="com.example.tdltx.junitrunner.runJUnitTest" label="Run Specific Test…" icon="icons/junit_run.png" style="push"> <visibleWhen checkEnabled="false"> <with variable="activeEditorInput"> <adapt type="org.eclipse.core.resources.IFile"> <test property="org.eclipse.core.resources.extension" value="tdltx"/> </adapt> </with> </visibleWhen> </command> </menuContribution> <!-- Also add to the Project Explorer / Package Explorer context menu when a .tdltx file is selected --> <menuContribution locationURI="popup:org.eclipse.ui.navigator.ProjectExplorer#PopupMenu?after=additions"> <separator name="tdltxSeparatorNav" visible="true"/> <command commandId="com.example.tdltx.junitrunner.runJUnitTest" label="Run Specific JUnit Test…" icon="icons/junit_run.png" style="push"> <visibleWhen checkEnabled="false"> <iterate ifEmpty="false"> <adapt type="org.eclipse.core.resources.IFile"> <test property="org.eclipse.core.resources.extension" value="tdltx"/> </adapt> </iterate> </visibleWhen> </command> </menuContribution> </extension> </plugin> plugins/org.etsi.mts.tdl.execution.java/src/org/etsi/mts/tdl/execution/java/eclipse/commands/Activator.java 0 → 100644 +30 −0 Original line number Diff line number Diff line package org.etsi.mts.tdl.execution.java.eclipse.commands; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.BundleContext; /** * Standard OSGi/Eclipse bundle activator. */ public class Activator extends AbstractUIPlugin { public static final String PLUGIN_ID = "com.example.tdltx.junitrunner"; //$NON-NLS-1$ private static Activator plugin; @Override public void start(BundleContext context) throws Exception { super.start(context); plugin = this; } @Override public void stop(BundleContext context) throws Exception { plugin = null; super.stop(context); } public static Activator getDefault() { return plugin; } } No newline at end of file plugins/org.etsi.mts.tdl.execution.java/src/org/etsi/mts/tdl/execution/java/eclipse/commands/JUnitTestDescriptor.java 0 → 100644 +66 −0 Original line number Diff line number Diff line package org.etsi.mts.tdl.execution.java.eclipse.commands; /** * Describes one predefined JUnit test that can be selected and launched. * * <p>Extend {@link PredefinedTests} to add more entries; no other class * needs to change. */ public final class JUnitTestDescriptor { /** Human-readable label shown in the selection dialog. */ private final String label; /** * Fully-qualified class name of the JUnit test class, * e.g. {@code com.example.myapp.tests.MyFeatureTest}. */ private final String testClassName; /** * Optional method name. When {@code null} the whole class is run. * When set, only that single test method is run, * e.g. {@code testParseValidDocument}. */ private final String testMethodName; private final String testObjective; // ----------------------------------------------------------------------- /** * Creates a descriptor for running an entire test class. */ public JUnitTestDescriptor(String label, String testClassName) { this(label, testClassName, null, null); } public JUnitTestDescriptor(String label, String testClassName, String testMethodName) { this(label, testClassName, testMethodName, null); } /** * Creates a descriptor for running a single test method. */ public JUnitTestDescriptor(String label, String testClassName, String testMethodName, String testObjective) { this.label = label; this.testClassName = testClassName; this.testMethodName = testMethodName; this.testObjective = testObjective; } // ----------------------------------------------------------------------- public String getLabel() { return label; } public String getTestClassName() { return testClassName; } public String getTestMethodName() { return testMethodName; } public String getTestObjective() { return testObjective; } /** Returns {@code true} when only a single method should be executed. */ public boolean hasSingleMethod() { return testMethodName != null && !testMethodName.isEmpty(); } public boolean hastestObjective() { return testObjective != null && !testObjective.isEmpty(); } @Override public String toString() { return label; } } No newline at end of file plugins/org.etsi.mts.tdl.execution.java/src/org/etsi/mts/tdl/execution/java/eclipse/commands/RunJUnitTestHandler.java 0 → 100644 +272 −0 Original line number Diff line number Diff line package org.etsi.mts.tdl.execution.java.eclipse.commands; import java.util.List; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.handlers.HandlerUtil; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.xtext.EcoreUtil2; import org.eclipse.xtext.resource.XtextResourceSet; import org.etsi.mts.tdl.Package; import org.etsi.mts.tdl.TestDescription; import com.google.inject.Guice; import com.google.inject.Injector; /** * Handles the "Run Specific JUnit Test…" command. * * <ol> * <li>Determines the {@link IProject} from either the active editor or the * current selection in the Navigator/Package Explorer.</li> * <li>Opens {@link SelectJUnitTestDialog} with the entries from * {@link PredefinedTests}.</li> * <li>Creates (or re-uses) a JUnit launch configuration for the chosen * test and launches it in run mode.</li> * </ol> */ public class RunJUnitTestHandler extends AbstractHandler { /** ID of the JUnit 5 launch config type bundled with org.eclipse.jdt.junit. */ private static final String JUNIT_LAUNCH_CONFIG_TYPE = "org.eclipse.jdt.junit.launchconfig"; //$NON-NLS-1$ // ----------------------------------------------------------------------- @Override public Object execute(ExecutionEvent event) throws ExecutionException { IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event); // ── 1. Resolve the project ────────────────────────────────────────── IProject project = resolveProject(event); if (project == null) { showError(window, "No Project Found", "Could not determine the project for the selected .tdltx file."); return null; } //TODO: this should be extracted as it is duplicated across all handlers.. ISelection selection = HandlerUtil.getCurrentSelection(event); IEditorInput input = HandlerUtil.getActiveEditorInput(event); IFile file = null; if (input != null && input instanceof FileEditorInput) { file = ((FileEditorInput) input).getFile(); } else if (selection !=null && selection instanceof IStructuredSelection) { IStructuredSelection structuredSelection = (IStructuredSelection) selection; Object firstElement = structuredSelection.getFirstElement(); if (firstElement instanceof IFile) { file = (IFile) firstElement; } } if (file == null) { //TODO: error message return null; } URI uri = URI.createPlatformResourceURI(file.getFullPath().toString(), true); Injector injector = Guice.createInjector(); XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class); XtextResourceSet rs = resourceSet; Resource r = rs.getResource(uri, true); EcoreUtil.resolveAll(r); Package p = (Package) r.getContents().get(0); List<TestDescription> tests = EcoreUtil2.getAllContentsOfType(r, TestDescription.class); // ── 2. Open the selection dialog ──────────────────────────────────── List<JUnitTestDescriptor> all = tests.stream() .filter(TestDescription::isIsLocallyOrdered) .map(t -> new JUnitTestDescriptor( t.getName(), //DONE: add test objective? //TODO: why is this specific to mec.testcases? "org.etsi.mts.tdl.tests.mec.testcases." +p.getName().toLowerCase() +"." +t.getName(), "test_"+t.getName(), t.getTestObjective().isEmpty() ? null : t.getTestObjective().getFirst().getDescription()) ) .toList(); //TODO: refine display SelectJUnitTestDialog dialog = new SelectJUnitTestDialog(window.getShell(), all); if (dialog.open() != IDialogConstants.OK_ID) { return null; // user cancelled } JUnitTestDescriptor chosen = dialog.getSelectedTest(); if (chosen == null) { return null; } // ── 3. Launch the chosen test ──────────────────────────────────────── try { launchJUnitTest(project, chosen); } catch (CoreException e) { Activator.getDefault().getLog().log( new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Failed to launch JUnit test: " + chosen.getLabel(), e)); ErrorDialog.openError(window.getShell(), "Launch Failed", "An error occurred while launching the JUnit test.", e.getStatus()); } return null; } // ----------------------------------------------------------------------- // Project resolution helpers // ----------------------------------------------------------------------- /** * Tries to find an {@link IProject} from the active editor input first, * then falls back to the current workbench selection. */ private IProject resolveProject(ExecutionEvent event) { // Try editor input IEditorInput editorInput = HandlerUtil.getActiveEditorInput(event); if (editorInput instanceof IFileEditorInput) { IFile file = ((IFileEditorInput) editorInput).getFile(); if (file != null) { return file.getProject(); } } // Try current selection (Navigator / Package Explorer) ISelection selection = HandlerUtil.getCurrentSelection(event); if (selection instanceof IStructuredSelection) { Object first = ((IStructuredSelection) selection).getFirstElement(); if (first instanceof IFile) { return ((IFile) first).getProject(); } if (first instanceof IProject) { return (IProject) first; } } return null; } // ----------------------------------------------------------------------- // JUnit launch configuration // ----------------------------------------------------------------------- /** * Creates (or reuses an existing) JUnit launch configuration and runs it. * * <p>Configuration names follow the pattern: * {@code <ProjectName> – <TestLabel>} * so multiple predefined tests can coexist without colliding.</p> */ private void launchJUnitTest(IProject project, JUnitTestDescriptor test) throws CoreException { ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); ILaunchConfigurationType type = manager.getLaunchConfigurationType(JUNIT_LAUNCH_CONFIG_TYPE); String configName = project.getName() + " – " + test.getLabel(); // Re-use an existing config with the same name (avoids proliferation) ILaunchConfiguration existing = findExistingConfig(manager, type, configName); ILaunchConfiguration config; if (existing != null) { config = existing; } else { config = createLaunchConfig(type, configName, project, test); } DebugUITools.launch(config, ILaunchManager.RUN_MODE); } private ILaunchConfiguration findExistingConfig( ILaunchManager manager, ILaunchConfigurationType type, String name) throws CoreException { for (ILaunchConfiguration cfg : manager.getLaunchConfigurations(type)) { if (cfg.getName().equals(name)) { return cfg; } } return null; } private ILaunchConfiguration createLaunchConfig( ILaunchConfigurationType type, String name, IProject project, JUnitTestDescriptor test) throws CoreException { ILaunchConfigurationWorkingCopy wc = type.newInstance(null, name); // Project wc.setAttribute( IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, project.getName()); // Test class wc.setAttribute( IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, test.getTestClassName()); // Optional: single test method if (test.hasSingleMethod()) { wc.setAttribute( "org.eclipse.jdt.junit.TESTNAME", //$NON-NLS-1$ test.getTestMethodName()); } // JUnit 5 runner (change to "4" for JUnit 4, or "" for auto-detect) wc.setAttribute("org.eclipse.jdt.junit.TEST_KIND", "org.eclipse.jdt.junit.loader.junit5"); //$NON-NLS-1$ //$NON-NLS-2$ // Keep source locator wc.setAttribute( IJavaLaunchConfigurationConstants.ATTR_SOURCE_PATH_PROVIDER, "org.eclipse.jdt.launching.sourceLocator.JavaSourceLookupDirector"); //$NON-NLS-1$ return wc.doSave(); } // ----------------------------------------------------------------------- // Utility // ----------------------------------------------------------------------- private void showError(IWorkbenchWindow window, String title, String message) { ErrorDialog.openError( window.getShell(), title, message, new Status(IStatus.ERROR, Activator.PLUGIN_ID, message)); } } No newline at end of file Loading
plugins/org.etsi.mts.tdl.execution.java/META-INF/MANIFEST.MF +6 −1 Original line number Diff line number Diff line Loading @@ -15,5 +15,10 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.emf.ecore, org.etsi.mts.tdl.model, org.etsi.mts.tdl.execution.java.codegen, junit-jupiter-api junit-jupiter-api, org.eclipse.debug.core, org.eclipse.debug.ui, org.eclipse.jdt.core, org.eclipse.jdt.launching, org.eclipse.xtext
plugins/org.etsi.mts.tdl.execution.java/plugin.xml +90 −0 Original line number Diff line number Diff line Loading @@ -62,4 +62,94 @@ </page> </extension> <!-- TODO: update ids ═══════════════════════════════════════════════════════════════ 1. Declare the command ═══════════════════════════════════════════════════════════════ --> <extension point="org.eclipse.ui.commands"> <command defaultHandler="org.etsi.mts.tdl.execution.java.eclipse.commands.RunJUnitTestHandler" id="com.example.tdltx.junitrunner.runJUnitTest" name="Run Specific JUnit Test…" description="Select and run a predefined JUnit test for this .tdltx file"> </command> </extension> <!-- ═══════════════════════════════════════════════════════════════ 2. Bind the command to its handler ═══════════════════════════════════════════════════════════════ --> <extension point="org.eclipse.ui.handlers"> <handler commandId="com.example.tdltx.junitrunner.runJUnitTest" class="org.etsi.mts.tdl.execution.java.eclipse.commands.RunJUnitTestHandler"> <!-- Only active when the active editor has a .tdltx file open --> <activeWhen> <with variable="activeEditorInput"> <adapt type="org.eclipse.core.resources.IFile"> <test property="org.eclipse.core.resources.extension" value="tdltx"/> </adapt> </with> </activeWhen> </handler> </extension> <!-- ═══════════════════════════════════════════════════════════════ 3. Add the menu entry to the editor context menu The editorContribution targets *all* editors; the visibility expression restricts it to .tdltx files. ═══════════════════════════════════════════════════════════════ --> <extension point="org.eclipse.ui.menus"> <!-- Context menu that appears when right-clicking inside any editor --> <menuContribution locationURI="popup:#TextEditorContext?after=group.edit"> <!-- TODO: add icon --> <command commandId="com.example.tdltx.junitrunner.runJUnitTest" label="Run Specific Test…" icon="icons/junit_run.png" style="push"> <visibleWhen checkEnabled="false"> <with variable="activeEditorInput"> <adapt type="org.eclipse.core.resources.IFile"> <test property="org.eclipse.core.resources.extension" value="tdltx"/> </adapt> </with> </visibleWhen> </command> </menuContribution> <!-- Also add to the Project Explorer / Package Explorer context menu when a .tdltx file is selected --> <menuContribution locationURI="popup:org.eclipse.ui.navigator.ProjectExplorer#PopupMenu?after=additions"> <separator name="tdltxSeparatorNav" visible="true"/> <command commandId="com.example.tdltx.junitrunner.runJUnitTest" label="Run Specific JUnit Test…" icon="icons/junit_run.png" style="push"> <visibleWhen checkEnabled="false"> <iterate ifEmpty="false"> <adapt type="org.eclipse.core.resources.IFile"> <test property="org.eclipse.core.resources.extension" value="tdltx"/> </adapt> </iterate> </visibleWhen> </command> </menuContribution> </extension> </plugin>
plugins/org.etsi.mts.tdl.execution.java/src/org/etsi/mts/tdl/execution/java/eclipse/commands/Activator.java 0 → 100644 +30 −0 Original line number Diff line number Diff line package org.etsi.mts.tdl.execution.java.eclipse.commands; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.BundleContext; /** * Standard OSGi/Eclipse bundle activator. */ public class Activator extends AbstractUIPlugin { public static final String PLUGIN_ID = "com.example.tdltx.junitrunner"; //$NON-NLS-1$ private static Activator plugin; @Override public void start(BundleContext context) throws Exception { super.start(context); plugin = this; } @Override public void stop(BundleContext context) throws Exception { plugin = null; super.stop(context); } public static Activator getDefault() { return plugin; } } No newline at end of file
plugins/org.etsi.mts.tdl.execution.java/src/org/etsi/mts/tdl/execution/java/eclipse/commands/JUnitTestDescriptor.java 0 → 100644 +66 −0 Original line number Diff line number Diff line package org.etsi.mts.tdl.execution.java.eclipse.commands; /** * Describes one predefined JUnit test that can be selected and launched. * * <p>Extend {@link PredefinedTests} to add more entries; no other class * needs to change. */ public final class JUnitTestDescriptor { /** Human-readable label shown in the selection dialog. */ private final String label; /** * Fully-qualified class name of the JUnit test class, * e.g. {@code com.example.myapp.tests.MyFeatureTest}. */ private final String testClassName; /** * Optional method name. When {@code null} the whole class is run. * When set, only that single test method is run, * e.g. {@code testParseValidDocument}. */ private final String testMethodName; private final String testObjective; // ----------------------------------------------------------------------- /** * Creates a descriptor for running an entire test class. */ public JUnitTestDescriptor(String label, String testClassName) { this(label, testClassName, null, null); } public JUnitTestDescriptor(String label, String testClassName, String testMethodName) { this(label, testClassName, testMethodName, null); } /** * Creates a descriptor for running a single test method. */ public JUnitTestDescriptor(String label, String testClassName, String testMethodName, String testObjective) { this.label = label; this.testClassName = testClassName; this.testMethodName = testMethodName; this.testObjective = testObjective; } // ----------------------------------------------------------------------- public String getLabel() { return label; } public String getTestClassName() { return testClassName; } public String getTestMethodName() { return testMethodName; } public String getTestObjective() { return testObjective; } /** Returns {@code true} when only a single method should be executed. */ public boolean hasSingleMethod() { return testMethodName != null && !testMethodName.isEmpty(); } public boolean hastestObjective() { return testObjective != null && !testObjective.isEmpty(); } @Override public String toString() { return label; } } No newline at end of file
plugins/org.etsi.mts.tdl.execution.java/src/org/etsi/mts/tdl/execution/java/eclipse/commands/RunJUnitTestHandler.java 0 → 100644 +272 −0 Original line number Diff line number Diff line package org.etsi.mts.tdl.execution.java.eclipse.commands; import java.util.List; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.ui.DebugUITools; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.handlers.HandlerUtil; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.xtext.EcoreUtil2; import org.eclipse.xtext.resource.XtextResourceSet; import org.etsi.mts.tdl.Package; import org.etsi.mts.tdl.TestDescription; import com.google.inject.Guice; import com.google.inject.Injector; /** * Handles the "Run Specific JUnit Test…" command. * * <ol> * <li>Determines the {@link IProject} from either the active editor or the * current selection in the Navigator/Package Explorer.</li> * <li>Opens {@link SelectJUnitTestDialog} with the entries from * {@link PredefinedTests}.</li> * <li>Creates (or re-uses) a JUnit launch configuration for the chosen * test and launches it in run mode.</li> * </ol> */ public class RunJUnitTestHandler extends AbstractHandler { /** ID of the JUnit 5 launch config type bundled with org.eclipse.jdt.junit. */ private static final String JUNIT_LAUNCH_CONFIG_TYPE = "org.eclipse.jdt.junit.launchconfig"; //$NON-NLS-1$ // ----------------------------------------------------------------------- @Override public Object execute(ExecutionEvent event) throws ExecutionException { IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindowChecked(event); // ── 1. Resolve the project ────────────────────────────────────────── IProject project = resolveProject(event); if (project == null) { showError(window, "No Project Found", "Could not determine the project for the selected .tdltx file."); return null; } //TODO: this should be extracted as it is duplicated across all handlers.. ISelection selection = HandlerUtil.getCurrentSelection(event); IEditorInput input = HandlerUtil.getActiveEditorInput(event); IFile file = null; if (input != null && input instanceof FileEditorInput) { file = ((FileEditorInput) input).getFile(); } else if (selection !=null && selection instanceof IStructuredSelection) { IStructuredSelection structuredSelection = (IStructuredSelection) selection; Object firstElement = structuredSelection.getFirstElement(); if (firstElement instanceof IFile) { file = (IFile) firstElement; } } if (file == null) { //TODO: error message return null; } URI uri = URI.createPlatformResourceURI(file.getFullPath().toString(), true); Injector injector = Guice.createInjector(); XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class); XtextResourceSet rs = resourceSet; Resource r = rs.getResource(uri, true); EcoreUtil.resolveAll(r); Package p = (Package) r.getContents().get(0); List<TestDescription> tests = EcoreUtil2.getAllContentsOfType(r, TestDescription.class); // ── 2. Open the selection dialog ──────────────────────────────────── List<JUnitTestDescriptor> all = tests.stream() .filter(TestDescription::isIsLocallyOrdered) .map(t -> new JUnitTestDescriptor( t.getName(), //DONE: add test objective? //TODO: why is this specific to mec.testcases? "org.etsi.mts.tdl.tests.mec.testcases." +p.getName().toLowerCase() +"." +t.getName(), "test_"+t.getName(), t.getTestObjective().isEmpty() ? null : t.getTestObjective().getFirst().getDescription()) ) .toList(); //TODO: refine display SelectJUnitTestDialog dialog = new SelectJUnitTestDialog(window.getShell(), all); if (dialog.open() != IDialogConstants.OK_ID) { return null; // user cancelled } JUnitTestDescriptor chosen = dialog.getSelectedTest(); if (chosen == null) { return null; } // ── 3. Launch the chosen test ──────────────────────────────────────── try { launchJUnitTest(project, chosen); } catch (CoreException e) { Activator.getDefault().getLog().log( new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Failed to launch JUnit test: " + chosen.getLabel(), e)); ErrorDialog.openError(window.getShell(), "Launch Failed", "An error occurred while launching the JUnit test.", e.getStatus()); } return null; } // ----------------------------------------------------------------------- // Project resolution helpers // ----------------------------------------------------------------------- /** * Tries to find an {@link IProject} from the active editor input first, * then falls back to the current workbench selection. */ private IProject resolveProject(ExecutionEvent event) { // Try editor input IEditorInput editorInput = HandlerUtil.getActiveEditorInput(event); if (editorInput instanceof IFileEditorInput) { IFile file = ((IFileEditorInput) editorInput).getFile(); if (file != null) { return file.getProject(); } } // Try current selection (Navigator / Package Explorer) ISelection selection = HandlerUtil.getCurrentSelection(event); if (selection instanceof IStructuredSelection) { Object first = ((IStructuredSelection) selection).getFirstElement(); if (first instanceof IFile) { return ((IFile) first).getProject(); } if (first instanceof IProject) { return (IProject) first; } } return null; } // ----------------------------------------------------------------------- // JUnit launch configuration // ----------------------------------------------------------------------- /** * Creates (or reuses an existing) JUnit launch configuration and runs it. * * <p>Configuration names follow the pattern: * {@code <ProjectName> – <TestLabel>} * so multiple predefined tests can coexist without colliding.</p> */ private void launchJUnitTest(IProject project, JUnitTestDescriptor test) throws CoreException { ILaunchManager manager = DebugPlugin.getDefault().getLaunchManager(); ILaunchConfigurationType type = manager.getLaunchConfigurationType(JUNIT_LAUNCH_CONFIG_TYPE); String configName = project.getName() + " – " + test.getLabel(); // Re-use an existing config with the same name (avoids proliferation) ILaunchConfiguration existing = findExistingConfig(manager, type, configName); ILaunchConfiguration config; if (existing != null) { config = existing; } else { config = createLaunchConfig(type, configName, project, test); } DebugUITools.launch(config, ILaunchManager.RUN_MODE); } private ILaunchConfiguration findExistingConfig( ILaunchManager manager, ILaunchConfigurationType type, String name) throws CoreException { for (ILaunchConfiguration cfg : manager.getLaunchConfigurations(type)) { if (cfg.getName().equals(name)) { return cfg; } } return null; } private ILaunchConfiguration createLaunchConfig( ILaunchConfigurationType type, String name, IProject project, JUnitTestDescriptor test) throws CoreException { ILaunchConfigurationWorkingCopy wc = type.newInstance(null, name); // Project wc.setAttribute( IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, project.getName()); // Test class wc.setAttribute( IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, test.getTestClassName()); // Optional: single test method if (test.hasSingleMethod()) { wc.setAttribute( "org.eclipse.jdt.junit.TESTNAME", //$NON-NLS-1$ test.getTestMethodName()); } // JUnit 5 runner (change to "4" for JUnit 4, or "" for auto-detect) wc.setAttribute("org.eclipse.jdt.junit.TEST_KIND", "org.eclipse.jdt.junit.loader.junit5"); //$NON-NLS-1$ //$NON-NLS-2$ // Keep source locator wc.setAttribute( IJavaLaunchConfigurationConstants.ATTR_SOURCE_PATH_PROVIDER, "org.eclipse.jdt.launching.sourceLocator.JavaSourceLookupDirector"); //$NON-NLS-1$ return wc.doSave(); } // ----------------------------------------------------------------------- // Utility // ----------------------------------------------------------------------- private void showError(IWorkbenchWindow window, String title, String message) { ErrorDialog.openError( window.getShell(), title, message, new Status(IStatus.ERROR, Activator.PLUGIN_ID, message)); } } No newline at end of file