diff --git a/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts b/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts index a8cba2d296bf7..e0b468a677c28 100644 --- a/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts +++ b/src/vs/workbench/contrib/debug/browser/debugEditorContribution.ts @@ -7,6 +7,7 @@ import * as nls from 'vs/nls'; import { RunOnceScheduler } from 'vs/base/common/async'; import * as env from 'vs/base/common/platform'; import { visit } from 'vs/base/common/json'; +import { setProperty } from 'vs/base/common/jsonEdit'; import { Constants } from 'vs/base/common/uint'; import { KeyCode } from 'vs/base/common/keyCodes'; import { IKeyboardEvent } from 'vs/base/browser/keyboardEvent'; @@ -34,6 +35,8 @@ import { DebugHoverWidget } from 'vs/workbench/contrib/debug/browser/debugHover' import { ITextModel } from 'vs/editor/common/model'; import { getHover } from 'vs/editor/contrib/hover/getHover'; import { dispose, IDisposable } from 'vs/base/common/lifecycle'; +import { EditOperation } from 'vs/editor/common/core/editOperation'; +import { basename } from 'vs/base/common/path'; const HOVER_DELAY = 300; const LAUNCH_JSON_REGEX = /\.vscode\/launch\.json$/; @@ -444,35 +447,54 @@ class DebugEditorContribution implements IDebugEditorContribution { "debug/addLaunchConfiguration" : {} */ this.telemetryService.publicLog('debug/addLaunchConfiguration'); - let configurationsArrayPosition: Position | undefined; const model = this.editor.getModel(); if (!model) { return; } - let depthInArray = 0; + let configurationsArrayPosition: Position | undefined; let lastProperty: string; - visit(model.getValue(), { - onObjectProperty: (property, offset, length) => { - lastProperty = property; - }, - onArrayBegin: (offset: number, length: number) => { - if (lastProperty === 'configurations' && depthInArray === 0) { - configurationsArrayPosition = model.getPositionAt(offset + 1); + const getConfigurationPosition = () => { + let depthInArray = 0; + visit(model.getValue(), { + onObjectProperty: (property: string) => { + lastProperty = property; + }, + onArrayBegin: (offset: number) => { + if (lastProperty === 'configurations' && depthInArray === 0) { + configurationsArrayPosition = model.getPositionAt(offset + 1); + } + depthInArray++; + }, + onArrayEnd: () => { + depthInArray--; } - depthInArray++; - }, - onArrayEnd: () => { - depthInArray--; - } - }); + }); + }; + + getConfigurationPosition(); - this.editor.focus(); + if (!configurationsArrayPosition) { + // "configurations" array doesn't exist. Add it here. + const { tabSize, insertSpaces } = model.getOptions(); + const eol = model.getEOL(); + const edit = (basename(model.uri.fsPath) === 'launch.json') ? + setProperty(model.getValue(), ['configurations'], [], { tabSize, insertSpaces, eol })[0] : + setProperty(model.getValue(), ['launch'], { 'configurations': [] }, { tabSize, insertSpaces, eol })[0]; + const startPosition = model.getPositionAt(edit.offset); + const lineNumber = startPosition.lineNumber; + const range = new Range(lineNumber, startPosition.column, lineNumber, model.getLineMaxColumn(lineNumber)); + model.pushEditOperations(null, [EditOperation.replace(range, edit.content)], () => null); + // Go through the file again since we've edited it + getConfigurationPosition(); + } if (!configurationsArrayPosition) { return; } + this.editor.focus(); + const insertLine = (position: Position): Promise => { // Check if there are more characters on a line after a "configurations": [, if yes enter a newline if (model.getLineLastNonWhitespaceColumn(position.lineNumber) > position.column) {