Skip to content
Open
9 changes: 8 additions & 1 deletion extensions/positron-r/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,11 @@
"view": "testing",
"contents": "No testthat tests found.\n[Add a test](command:r.useTest)",
"when": "isRPackage && config.positron.r.testing && testthatIsConfigured && !testthatHasTests"
},
{
"view": "debug",
"contents": "%r.welcome.views.debugger.content%",
"when": "debugStartLanguage == 'r'"
}
],
"taskDefinitions": [
Expand All @@ -678,7 +683,9 @@
"debuggers": [
{
"type": "ark",
"label": "R Debugger"
"label": "R Debugger",
"languages": ["r"],
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change here is what keeps us from prompting folks to install an (incompatible) extension. At the very minimum, we should contribute a language here to avoid that prompt.

"supportsUiLaunch": false
}
],
"notebookRenderer": [
Expand Down
3 changes: 2 additions & 1 deletion extensions/positron-r/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
"r.walkthrough.migrateFromRStudio.workspaces.title": "Projects, folders, and workspaces",
"r.walkthrough.migrateFromRStudio.workspaces.description": " \n[Open an existing folder](command:workbench.action.files.openFolder)",
"r.walkthrough.migrateFromRStudio.formatting.title": "Formatting your R code",
"r.walkthrough.migrateFromRStudio.formatting.description": " \n[Configure Air to format on save](command:r.walkthrough.formatOnSave)"
"r.walkthrough.migrateFromRStudio.formatting.description": " \n[Configure Air to format on save](command:r.walkthrough.formatOnSave)",
"r.welcome.views.debugger.content": "Positron currently provides limited debugging support for R code, but you can use R's native debugging features in Positron.\n[Learn more](https://positron.posit.co/guide-r.html#debugging)"

}
9 changes: 9 additions & 0 deletions src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,15 @@ export class AdapterManager extends Disposable implements IAdapterManager {
.find(a => a.interestedInLanguage(languageId));
}

// --- Start Positron ---
someDebuggerInterestedInLanguageSupportsUiLaunch(languageId: string): boolean {
const interestedDebuggers = this.debuggers
.filter(d => d.enabled && d.interestedInLanguage(languageId));
// Return true if at least one interested debugger supports UI launch
return interestedDebuggers.some(d => d.supportsUiLaunch !== false);
}
// --- End Positron ---

async guessDebugger(gettingConfigurations: boolean): Promise<IGuessedDebugger | undefined> {
const activeTextEditorControl = this.editorService.activeTextEditorControl;
let candidates: Debugger[] = [];
Expand Down
31 changes: 29 additions & 2 deletions src/vs/workbench/contrib/debug/browser/welcomeView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ import { WorkbenchStateContext } from '../../../common/contextkeys.js';
import { Extensions, IViewDescriptorService, IViewsRegistry, ViewContentGroups } from '../../../common/views.js';
import { IEditorService } from '../../../services/editor/common/editorService.js';
import { CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_DEBUG_EXTENSION_AVAILABLE, IDebugService } from '../common/debug.js';
// --- Start Positron ---
// eslint-disable-next-line no-duplicate-imports
import { CONTEXT_DEBUGGER_SUPPORTS_UI_LAUNCH } from '../common/debug.js';
// --- End Positron ---
import { DEBUG_CONFIGURE_COMMAND_ID, DEBUG_START_COMMAND_ID } from './debugCommands.js';

const debugStartLanguageKey = 'debugStartLanguage';
Expand All @@ -38,6 +42,9 @@ export class WelcomeView extends ViewPane {

private debugStartLanguageContext: IContextKey<string | undefined>;
private debuggerInterestedContext: IContextKey<boolean>;
// --- Start Positron ---
private debuggerSupportsUiLaunchContext: IContextKey<boolean>;
// --- End Positron ---

constructor(
options: IViewletViewOptions,
Expand All @@ -58,6 +65,9 @@ export class WelcomeView extends ViewPane {

this.debugStartLanguageContext = CONTEXT_DEBUG_START_LANGUAGE.bindTo(contextKeyService);
this.debuggerInterestedContext = CONTEXT_DEBUGGER_INTERESTED_IN_ACTIVE_EDITOR.bindTo(contextKeyService);
// --- Start Positron ---
this.debuggerSupportsUiLaunchContext = CONTEXT_DEBUGGER_SUPPORTS_UI_LAUNCH.bindTo(contextKeyService);
// --- End Positron ---
const lastSetLanguage = storageSevice.get(debugStartLanguageKey, StorageScope.WORKSPACE);
this.debugStartLanguageContext.set(lastSetLanguage);

Expand All @@ -70,14 +80,25 @@ export class WelcomeView extends ViewPane {
if (isCodeEditor(editorControl)) {
const model = editorControl.getModel();
const language = model ? model.getLanguageId() : undefined;

if (language && this.debugService.getAdapterManager().someDebuggerInterestedInLanguage(language)) {
this.debugStartLanguageContext.set(language);
this.debuggerInterestedContext.set(true);
storageSevice.store(debugStartLanguageKey, language, StorageScope.WORKSPACE, StorageTarget.MACHINE);
// --- Start Positron ---
// Check if any debugger interested in this language supports UI launch
const supportsUiLaunch = this.debugService.getAdapterManager().someDebuggerInterestedInLanguageSupportsUiLaunch(language);
this.debuggerSupportsUiLaunchContext.set(supportsUiLaunch);
// --- End Positron ---
return;
}

}
this.debuggerInterestedContext.set(false);
// --- Start Positron ---
this.debuggerSupportsUiLaunchContext.set(true); // Default to true when no debugger
this.debugStartLanguageContext.reset(); // Clear the language context when no debugger is interested
// --- End Positron ---
};

const disposables = new DisposableStore();
Expand Down Expand Up @@ -133,7 +154,10 @@ viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, {
let debugKeybindingLabel = '';
viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, {
content: `[${localize('runAndDebugAction', "Run and Debug")}${debugKeybindingLabel}](command:${DEBUG_START_COMMAND_ID})`,
when: CONTEXT_DEBUGGERS_AVAILABLE,
// --- Start Positron ---
// when: CONTEXT_DEBUGGERS_AVAILABLE,
when: ContextKeyExpr.and(CONTEXT_DEBUGGERS_AVAILABLE, CONTEXT_DEBUGGER_SUPPORTS_UI_LAUNCH),
// --- End Positron ---
group: ViewContentGroups.Debug,
// Allow inserting more buttons directly after this one (by setting order to 1).
order: 1
Expand All @@ -142,7 +166,10 @@ viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, {
viewsRegistry.registerViewWelcomeContent(WelcomeView.ID, {
content: localize({ key: 'customizeRunAndDebug2', comment: ['{Locked="launch.json"}', '{Locked="["}', '{Locked="]({0})"}'] },
"To customize Run and Debug [create a launch.json file]({0}).", `${createCommandUri(DEBUG_CONFIGURE_COMMAND_ID, { addNew: true }).toString()}`),
when: ContextKeyExpr.and(CONTEXT_DEBUGGERS_AVAILABLE, WorkbenchStateContext.notEqualsTo('empty')),
// --- Start Positron ---
// when: ContextKeyExpr.and(CONTEXT_DEBUGGERS_AVAILABLE, WorkbenchStateContext.notEqualsTo('empty')),
when: ContextKeyExpr.and(CONTEXT_DEBUGGERS_AVAILABLE, WorkbenchStateContext.notEqualsTo('empty'), CONTEXT_DEBUGGER_SUPPORTS_UI_LAUNCH),
// --- End Positron ---
group: ViewContentGroups.Debug
});

Expand Down
11 changes: 11 additions & 0 deletions src/vs/workbench/contrib/debug/common/debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ export const CONTEXT_STEP_INTO_TARGETS_SUPPORTED = new RawContextKey<boolean>('s
export const CONTEXT_BREAKPOINTS_EXIST = new RawContextKey<boolean>('breakpointsExist', false, { type: 'boolean', description: nls.localize('breakpointsExist', "True when at least one breakpoint exists.") });
export const CONTEXT_DEBUGGERS_AVAILABLE = new RawContextKey<boolean>('debuggersAvailable', false, { type: 'boolean', description: nls.localize('debuggersAvailable', "True when there is at least one debug extensions active.") });
export const CONTEXT_DEBUG_EXTENSION_AVAILABLE = new RawContextKey<boolean>('debugExtensionAvailable', true, { type: 'boolean', description: nls.localize('debugExtensionsAvailable', "True when there is at least one debug extension installed and enabled.") });
// --- Start Positron ---
export const CONTEXT_DEBUGGER_SUPPORTS_UI_LAUNCH = new RawContextKey<boolean>('debuggerSupportsUiLaunch', true, { type: 'boolean', description: nls.localize('debuggersupportsUiLaunch', "True when the debugger for the current file supports launching from the Run and Debug UI. Some debuggers (like R) use alternative debugging approaches.") });
// --- End Positron ---
export const CONTEXT_DEBUG_PROTOCOL_VARIABLE_MENU_CONTEXT = new RawContextKey<string>('debugProtocolVariableMenuContext', undefined, { type: 'string', description: nls.localize('debugProtocolVariableMenuContext', "Represents the context the debug adapter sets on the focused variable in the VARIABLES view.") });
export const CONTEXT_SET_VARIABLE_SUPPORTED = new RawContextKey<boolean>('debugSetVariableSupported', false, { type: 'boolean', description: nls.localize('debugSetVariableSupported', "True when the focused session supports 'setVariable' request.") });
export const CONTEXT_SET_DATA_BREAKPOINT_BYTES_SUPPORTED = new RawContextKey<boolean>('debugSetDataBreakpointAddressSupported', false, { type: 'boolean', description: nls.localize('debugSetDataBreakpointAddressSupported', "True when the focused session supports 'getBreakpointInfo' request on an address.") });
Expand Down Expand Up @@ -951,6 +954,11 @@ export interface IDebuggerContribution extends IPlatformSpecificAdapterContribut
// supported languages
languages?: string[];

// --- Start Positron ---
// Whether this debugger supports launching from the Run and Debug UI
supportsUiLaunch?: boolean;
// --- End Positron ---

// debug configuration support
configurationAttributes?: Record<string, IJSONSchema>;
initialConfigurations?: unknown[];
Expand Down Expand Up @@ -1051,6 +1059,9 @@ export interface IAdapterManager {
getDebugAdapterDescriptor(session: IDebugSession): Promise<IAdapterDescriptor | undefined>;
getDebuggerLabel(type: string): string | undefined;
someDebuggerInterestedInLanguage(language: string): boolean;
// --- Start Positron ---
someDebuggerInterestedInLanguageSupportsUiLaunch(language: string): boolean;
// --- End Positron ---
getDebugger(type: string): IDebuggerMetadata | undefined;

activateDebuggers(activationEvent: string, debugType?: string): Promise<void>;
Expand Down
7 changes: 7 additions & 0 deletions src/vs/workbench/contrib/debug/common/debugSchemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ export const debuggersExtPoint = extensionsRegistry.ExtensionsRegistry.registerE
description: nls.localize('vscode.extension.contributes.debuggers.languages', "List of languages for which the debug extension could be considered the \"default debugger\"."),
type: 'array'
},
// --- Start Positron ---
supportsUiLaunch: {
description: nls.localize('positron.extension.contributes.debuggers.supportsUiLaunch', "Whether this debugger supports launching from the Run and Debug UI. Set to false for debuggers that use alternative debugging approaches (e.g., R's browser(), debug(), etc.). Defaults to true."),
type: 'boolean',
default: true
},
// --- End Positron ---
configurationSnippets: {
description: nls.localize('vscode.extension.contributes.debuggers.configurationSnippets', "Snippets for adding new configurations in \'launch.json\'."),
type: 'array'
Expand Down
6 changes: 6 additions & 0 deletions src/vs/workbench/contrib/debug/common/debugger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,12 @@ export class Debugger implements IDebugger, IDebuggerMetadata {
return this.debuggerContribution.languages;
}

// --- Start Positron ---
get supportsUiLaunch(): boolean {
return this.debuggerContribution.supportsUiLaunch !== false; // Defaults to true
}
// --- End Positron ---

get when(): ContextKeyExpression | undefined {
return this.debuggerWhen;
}
Expand Down
Loading