Messages panel wordwrap (#10970)

* Add CodeQL Analysis workflow (#10195)

* Add CodeQL Analysis workflow

* Fix path

* fix word wrap support in the message panel

* fix width on message treee

* fix import

* fix settings editor to reflect the changes in the settings ids

* fix tests

* add configuration upgrader

* make sure to maintian execution order

* make the compiler happy

* add tests for upgrader

Co-authored-by: Justin Hutchings <jhutchings1@users.noreply.github.com>
This commit is contained in:
Anthony Dresser
2020-06-29 16:25:11 -07:00
committed by GitHub
parent 6b8eafbf2e
commit 93a88e38fe
17 changed files with 477 additions and 284 deletions

View File

@@ -0,0 +1,12 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
import { ConfigurationUpgraderContribution } from 'sql/workbench/contrib/configuration/common/configurationUpgrader';
const workbenchContributionsRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
workbenchContributionsRegistry.registerWorkbenchContribution(ConfigurationUpgraderContribution, LifecyclePhase.Starting);

View File

@@ -0,0 +1,66 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { deepFreeze } from 'vs/base/common/objects';
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
const settingsToMove: { [key: string]: string } = deepFreeze({
'sql.saveAsCsv.includeHeaders': 'queryEditor.results.saveAsCsv.includeHeaders', // June 19, 2020
'sql.saveAsCsv.delimiter': 'queryEditor.results.saveAsCsv.delimiter', // June 19, 2020
'sql.saveAsCsv.lineSeperator': 'queryEditor.results.saveAsCsv.lineSeperator', // June 19, 2020
'sql.saveAsCsv.textIdentifier': 'queryEditor.results.saveAsCsv.textIdentifier', // June 19, 2020
'sql.saveAsCsv.encoding': 'queryEditor.results.saveAsCsv.encoding', // June 19, 2020
'sql.results.streaming': 'queryEditor.results.streaming', // June 19, 2020
'sql.saveAsXml.formatted': 'queryEditor.results.saveAsXml.formatted', // June 19, 2020
'sql.saveAsXml.encoding': 'queryEditor.results.saveAsXml.encoding', // June 19, 2020
'sql.copyIncludeHeaders': 'queryEditor.results.copyIncludeHeaders', // June 19, 2020
'sql.copyRemoveNewLine': 'queryEditor.results.copyRemoveNewLine', // June 19, 2020
'sql.showBatchTime': 'queryEditor.messages.showBatchTime', // June 19, 2020
'sql.chart.defaultChartType': 'queryEditor.chart.defaultChartType', // June 19, 2020
'sql.tabColorMode': 'queryEditor.tabColorMode', // June 19, 2020
'sql.showConnectionInfoInTitle': 'queryEditor.showConnectionInfoInTitle', // June 19, 2020
'sql.promptToSaveGeneratedFiles': 'queryEditor.promptToSaveGeneratedFiles', // June 19, 2020
});
export class ConfigurationUpgraderContribution implements IWorkbenchContribution {
private static readonly STORAGE_KEY = 'configurationUpgrader';
private readonly globalStorage: { [key: string]: boolean };
private readonly workspaceStorage: { [key: string]: boolean };
public readonly processingPromise: Promise<void>;
constructor(
@IStorageService private readonly storageService: IStorageService,
@IConfigurationService private readonly configurationService: IConfigurationService
) {
this.globalStorage = JSON.parse(this.storageService.get(ConfigurationUpgraderContribution.STORAGE_KEY, StorageScope.GLOBAL, '{}'));
this.workspaceStorage = JSON.parse(this.storageService.get(ConfigurationUpgraderContribution.STORAGE_KEY, StorageScope.WORKSPACE, '{}'));
this.processingPromise = (async () => {
await this.processSettings();
this.storageService.store(ConfigurationUpgraderContribution.STORAGE_KEY, JSON.stringify(this.globalStorage), StorageScope.GLOBAL);
this.storageService.store(ConfigurationUpgraderContribution.STORAGE_KEY, JSON.stringify(this.workspaceStorage), StorageScope.WORKSPACE);
})();
}
private async processSettings(): Promise<void> {
for (const key in settingsToMove) {
const toKey = settingsToMove[key];
const value = this.configurationService.inspect(key);
if (this.globalStorage[key] !== true && value.userValue) {
await this.configurationService.updateValue(key, undefined, ConfigurationTarget.USER); // writing undefined will result in the key being deleted
await this.configurationService.updateValue(toKey, value.userValue, ConfigurationTarget.USER); // update to new settings key
this.globalStorage[key] = true; // don't proccess again
}
if (this.workspaceStorage[key] !== true && value.workspaceValue) {
await this.configurationService.updateValue(key, undefined, ConfigurationTarget.WORKSPACE); // writing undefined will result in the key being deleted
await this.configurationService.updateValue(toKey, value.workspaceValue, ConfigurationTarget.WORKSPACE); // update to new settings key
this.workspaceStorage[key] = true; // don't proccess again
}
}
}
}

View File

@@ -0,0 +1,45 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { ConfigurationUpgraderContribution } from 'sql/workbench/contrib/configuration/common/configurationUpgrader';
import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
import { TestConfigurationService } from 'sql/platform/connection/test/common/testConfigurationService';
suite('Configuration Upgrader', () => {
test('does upgrade settings in user settings', async () => {
const configurationService = new TestConfigurationService({ user: { 'sql': { 'saveAsCsv': { 'includeHeaders': true } } } });
const configurationUpgrader = new ConfigurationUpgraderContribution(new TestStorageService(), configurationService);
await configurationUpgrader.processingPromise;
assert(configurationService.inspect('sql.saveAsCsv.includeHeaders').userValue === undefined);
assert(configurationService.inspect('queryEditor.results.saveAsCsv.includeHeaders').userValue === true);
});
test('does not change new setting', async () => {
const configurationService = new TestConfigurationService({ user: { 'queryEditor': { 'results': { 'saveAsCsv': { 'includeHeaders': true } } } } });
const configurationUpgrader = new ConfigurationUpgraderContribution(new TestStorageService(), configurationService);
await configurationUpgrader.processingPromise;
assert(configurationService.inspect('sql.saveAsCsv.includeHeaders').userValue === undefined);
assert(configurationService.inspect('queryEditor.results.saveAsCsv.includeHeaders').userValue === true);
});
test('correctly changes multiple settings', async () => {
const configurationService = new TestConfigurationService({ user: { 'sql': { 'saveAsCsv': { 'includeHeaders': true }, 'promptToSaveGeneratedFiles': true } } });
const configurationUpgrader = new ConfigurationUpgraderContribution(new TestStorageService(), configurationService);
await configurationUpgrader.processingPromise;
assert(configurationService.inspect('sql.saveAsCsv.includeHeaders').userValue === undefined);
assert(configurationService.inspect('queryEditor.results.saveAsCsv.includeHeaders').userValue === true);
assert(configurationService.inspect('sql.promptToSaveGeneratedFiles').userValue === undefined);
assert(configurationService.inspect('queryEditor.promptToSaveGeneratedFiles').userValue === true);
});
test('does change workspace settings', async () => {
const configurationService = new TestConfigurationService({ workspace: { 'sql': { 'saveAsCsv': { 'includeHeaders': true } } } });
const configurationUpgrader = new ConfigurationUpgraderContribution(new TestStorageService(), configurationService);
await configurationUpgrader.processingPromise;
assert(configurationService.inspect('sql.saveAsCsv.includeHeaders').workspaceValue === undefined);
assert(configurationService.inspect('queryEditor.results.saveAsCsv.includeHeaders').workspaceValue === true);
});
});

View File

@@ -19,25 +19,15 @@ let sqlTocItems: ITOCEntry[] = [{
settings: ['startup.alwaysShowServersView', 'connection.*', 'serverGroup.*', 'datasource.*']
},
{
id: 'data/query',
label: localize('query', "Query"),
settings: ['sql.query.*', 'resultsGrid.*']
id: 'data/queryEditor',
label: localize('queryEditor', "Query Editor"),
settings: ['queryEditor.*']
},
{
id: 'data/notebook',
label: localize('notebook', "Notebook"),
settings: ['notebook.*']
},
{
id: 'data/sql',
label: localize('sql', "SQL"),
settings: ['sql.*']
},
{
id: 'data/mssql',
label: localize('mssql', "Microsoft SQL Server"),
settings: ['mssql.*']
},
{
id: 'data/dashboard',
label: localize('dashboard', "Dashboard"),

View File

@@ -14,10 +14,9 @@
.message-tree .monaco-tl-contents {
user-select: text;
-webkit-user-select: text;
white-space: pre;
}
.message-tree.word-wrap .monaco-tl-contents {
.message-tree.word-wrap .monaco-tl-contents .message {
/* Wrap words but also do not trim whitespace #6275 */
word-wrap: break-word;
white-space: pre-wrap;
@@ -92,6 +91,7 @@
.message-tree .batch-start,
.message-tree .error-message {
display: inline-block;
width: calc(100% - 100px);
}
.message-tree .batch-start {

View File

@@ -12,10 +12,10 @@ import { generateUuid } from 'vs/base/common/uuid';
import { attachListStyler } from 'vs/platform/theme/common/styler';
import { IThemeService, IColorTheme } from 'vs/platform/theme/common/themeService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { WorkbenchDataTree, horizontalScrollingKey } from 'vs/platform/list/browser/listService';
import { WorkbenchDataTree } from 'vs/platform/list/browser/listService';
import { isArray, isString } from 'vs/base/common/types';
import { Disposable, DisposableStore, dispose } from 'vs/base/common/lifecycle';
import { $, Dimension, createStyleSheet, addStandardDisposableGenericMouseDownListner } from 'vs/base/browser/dom';
import { $, Dimension, createStyleSheet, addStandardDisposableGenericMouseDownListner, toggleClass } from 'vs/base/browser/dom';
import { resultsErrorColor } from 'sql/platform/theme/common/colors';
import { CachedListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list/list';
import { FuzzyScore } from 'vs/base/common/filters';
@@ -33,6 +33,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import { IDataTreeViewState } from 'vs/base/browser/ui/tree/dataTree';
import { IRange } from 'vs/editor/common/core/range';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IQueryEditorConfiguration } from 'sql/platform/query/common/query';
export interface IResultMessageIntern {
id?: string;
@@ -106,7 +107,8 @@ export class MessagePanel extends Disposable {
@IConfigurationService private configurationService: IConfigurationService
) {
super();
const horizontalScrollEnabled = this.configurationService.getValue(horizontalScrollingKey) || false;
const wordWrap = this.configurationService.getValue<IQueryEditorConfiguration>('queryEditor').messages.wordwrap;
toggleClass(this.container, 'word-wrap', wordWrap);
this.tree = <WorkbenchDataTree<Model, IResultMessageIntern, FuzzyScore>>instantiationService.createInstance(
WorkbenchDataTree,
'MessagePanel',
@@ -121,8 +123,9 @@ export class MessagePanel extends Disposable {
{
accessibilityProvider: new AccessibilityProvider(),
mouseSupport: false,
horizontalScrolling: !wordWrap,
setRowLineHeight: false,
supportDynamicHeights: !horizontalScrollEnabled,
supportDynamicHeights: wordWrap,
identityProvider: new IdentityProvider()
});
this._register(this.tree.onContextMenu(e => this.onContextMenu(e)));
@@ -176,7 +179,7 @@ export class MessagePanel extends Disposable {
}
public layout(size: Dimension): void {
this.tree.layout(size.height);
this.tree.layout(size.height, size.width);
this.tree.updateChildren();
}
@@ -313,7 +316,6 @@ class BatchMessageRenderer implements ITreeRenderer<IResultMessageIntern, void,
const timeStamp = $('.time-stamp');
container.append(timeStamp);
const message = $('.batch-start');
message.style.whiteSpace = 'pre';
container.append(message);
return { message, timeStamp, disposable: new DisposableStore() };
}
@@ -346,7 +348,6 @@ class MessageRenderer implements ITreeRenderer<IResultMessageIntern, void, IMess
renderTemplate(container: HTMLElement): IMessageTemplate {
container.append($('.time-stamp'));
const message = $('.message');
message.style.whiteSpace = 'pre';
container.append(message);
return { message };
}

View File

@@ -7,12 +7,11 @@ import { Registry } from 'vs/platform/registry/common/platform';
import { EditorDescriptor, IEditorRegistry, Extensions as EditorExtensions } from 'vs/workbench/browser/editor';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
import { IConfigurationRegistry, Extensions as ConfigExtensions, IConfigurationPropertySchema } from 'vs/platform/configuration/common/configurationRegistry';
import { IConfigurationRegistry, Extensions as ConfigExtensions, IConfigurationNode } from 'vs/platform/configuration/common/configurationRegistry';
import { SyncActionDescriptor, MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
import { KeyMod, KeyCode, KeyChord } from 'vs/base/common/keyCodes';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { ContextKeyExpr, ContextKeyEqualsExpr } from 'vs/platform/contextkey/common/contextkey';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { QueryEditor } from 'sql/workbench/contrib/query/browser/queryEditor';
import { QueryResultsEditor } from 'sql/workbench/contrib/query/browser/queryResultsEditor';
@@ -24,7 +23,6 @@ import {
} from 'sql/workbench/contrib/query/browser/keyboardQueryActions';
import * as gridActions from 'sql/workbench/contrib/editData/browser/gridActions';
import * as gridCommands from 'sql/workbench/contrib/editData/browser/gridCommands';
import * as Constants from 'sql/platform/query/common/constants';
import { localize } from 'vs/nls';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
@@ -42,6 +40,7 @@ import { MssqlNodeContext } from 'sql/workbench/services/objectExplorer/browser/
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
import { ManageActionContext } from 'sql/workbench/browser/actions';
import { ItemContextKey } from 'sql/workbench/contrib/dashboard/browser/widgets/explorer/explorerContext';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
export const QueryEditorVisibleCondition = ContextKeyExpr.has(queryContext.queryEditorVisibleId);
export const ResultsGridFocusCondition = ContextKeyExpr.and(ContextKeyExpr.has(queryContext.resultsVisibleId), ContextKeyExpr.has(queryContext.resultsGridFocussedId));
@@ -305,228 +304,104 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({
handler: gridCommands.goToNextQueryOutputTab
});
export const queryEditorConfigurationBaseNode = Object.freeze<IConfigurationNode>({
id: 'queryEditor',
order: 5,
type: 'object',
title: localize('queryEditorConfigurationTitle', "Query Editor"),
});
// Intellisense and other configuration options
const registryProperties: { [path: string]: IConfigurationPropertySchema; } = {
'sql.saveAsCsv.includeHeaders': {
'type': 'boolean',
'description': localize('sql.saveAsCsv.includeHeaders', "[Optional] When true, column headers are included when saving results as CSV"),
'default': true
},
'sql.saveAsCsv.delimiter': {
'type': 'string',
'description': localize('sql.saveAsCsv.delimiter', "[Optional] The custom delimiter to use between values when saving as CSV"),
'default': ','
},
'sql.saveAsCsv.lineSeperator': {
'type': 'string',
'description': localize('sql.saveAsCsv.lineSeperator', "[Optional] Character(s) used for seperating rows when saving results as CSV"),
'default': null
},
'sql.saveAsCsv.textIdentifier': {
'type': 'string',
'description': localize('sql.saveAsCsv.textIdentifier', "[Optional] Character used for enclosing text fields when saving results as CSV"),
'default': '\"'
},
'sql.saveAsCsv.encoding': {
'type': 'string',
'description': localize('sql.saveAsCsv.encoding', "[Optional] File encoding used when saving results as CSV"),
'default': 'utf-8'
},
'sql.results.streaming': {
'type': 'boolean',
'description': localize('sql.results.streaming', "Enable results streaming; contains few minor visual issues"),
'default': true
},
'sql.saveAsXml.formatted': {
'type': 'string',
'description': localize('sql.saveAsXml.formatted', "[Optional] When true, XML output will be formatted when saving results as XML"),
'default': true
},
'sql.saveAsXml.encoding': {
'type': 'string',
'description': localize('sql.saveAsXml.encoding', "[Optional] File encoding used when saving results as XML"),
'default': 'utf-8'
},
'sql.copyIncludeHeaders': {
'type': 'boolean',
'description': localize('sql.copyIncludeHeaders', "[Optional] Configuration options for copying results from the Results View"),
'default': false
},
'sql.copyRemoveNewLine': {
'type': 'boolean',
'description': localize('sql.copyRemoveNewLine', "[Optional] Configuration options for copying multi-line results from the Results View"),
'default': true
},
'sql.showBatchTime': {
'type': 'boolean',
'description': localize('sql.showBatchTime', "[Optional] Should execution time be shown for individual batches"),
'default': false
},
'sql.chart.defaultChartType': {
'enum': Constants.allChartTypes,
'default': Constants.chartTypeHorizontalBar,
'description': localize('defaultChartType', "[Optional] the default chart type to use when opening Chart Viewer from a Query Results")
},
'sql.tabColorMode': {
'type': 'string',
'enum': [Constants.tabColorModeOff, Constants.tabColorModeBorder, Constants.tabColorModeFill],
'enumDescriptions': [
localize('tabColorMode.off', "Tab coloring will be disabled"),
localize('tabColorMode.border', "The top border of each editor tab will be colored to match the relevant server group"),
localize('tabColorMode.fill', "Each editor tab's background color will match the relevant server group"),
],
'default': Constants.tabColorModeOff,
'description': localize('tabColorMode', "Controls how to color tabs based on the server group of their active connection")
},
'sql.showConnectionInfoInTitle': {
'type': 'boolean',
'description': localize('showConnectionInfoInTitle', "Controls whether to show the connection info for a tab in the title."),
'default': true
},
'sql.promptToSaveGeneratedFiles': {
'type': 'boolean',
'default': false,
'description': localize('sql.promptToSaveGeneratedFiles', "Prompt to save generated SQL files")
},
'mssql.intelliSense.enableIntelliSense': {
'type': 'boolean',
'default': true,
'description': localize('mssql.intelliSense.enableIntelliSense', "Should IntelliSense be enabled")
},
'mssql.intelliSense.enableErrorChecking': {
'type': 'boolean',
'default': true,
'description': localize('mssql.intelliSense.enableErrorChecking', "Should IntelliSense error checking be enabled")
},
'mssql.intelliSense.enableSuggestions': {
'type': 'boolean',
'default': true,
'description': localize('mssql.intelliSense.enableSuggestions', "Should IntelliSense suggestions be enabled")
},
'mssql.intelliSense.enableQuickInfo': {
'type': 'boolean',
'default': true,
'description': localize('mssql.intelliSense.enableQuickInfo', "Should IntelliSense quick info be enabled")
},
'mssql.intelliSense.lowerCaseSuggestions': {
'type': 'boolean',
'default': false,
'description': localize('mssql.intelliSense.lowerCaseSuggestions', "Should IntelliSense suggestions be lowercase")
},
'mssql.query.rowCount': {
'type': 'number',
'default': 0,
'description': localize('mssql.query.setRowCount', "Maximum number of rows to return before the server stops processing your query.")
},
'mssql.query.textSize': {
'type': 'number',
'default': 2147483647,
'description': localize('mssql.query.textSize', "Maximum size of text and ntext data returned from a SELECT statement")
},
'mssql.query.executionTimeout': {
'type': 'number',
'default': 0,
'description': localize('mssql.query.executionTimeout', "An execution time-out of 0 indicates an unlimited wait (no time-out)")
},
'mssql.query.noCount': {
'type': 'boolean',
'default': false,
'description': localize('mssql.query.noCount', "Enable SET NOCOUNT option")
},
'mssql.query.noExec': {
'type': 'boolean',
'default': false,
'description': localize('mssql.query.noExec', "Enable SET NOEXEC option")
},
'mssql.query.parseOnly': {
'type': 'boolean',
'default': false,
'description': localize('mssql.query.parseOnly', "Enable SET PARSEONLY option")
},
'mssql.query.arithAbort': {
'type': 'boolean',
'default': true,
'description': localize('mssql.query.arithAbort', "Enable SET ARITHABORT option")
},
'mssql.query.statisticsTime': {
'type': 'boolean',
'default': false,
'description': localize('mssql.query.statisticsTime', "Enable SET STATISTICS TIME option")
},
'mssql.query.statisticsIO': {
'type': 'boolean',
'default': false,
'description': localize('mssql.query.statisticsIO', "Enable SET STATISTICS IO option")
},
'mssql.query.xactAbortOn': {
'type': 'boolean',
'default': false,
'description': localize('mssql.query.xactAbortOn', "Enable SET XACT_ABORT ON option")
},
'mssql.query.transactionIsolationLevel': {
'enum': ['READ COMMITTED', 'READ UNCOMMITTED', 'REPEATABLE READ', 'SERIALIZABLE'],
'default': 'READ COMMITTED',
'description': localize('mssql.query.transactionIsolationLevel', "Enable SET TRANSACTION ISOLATION LEVEL option")
},
'mssql.query.deadlockPriority': {
'enum': ['Normal', 'Low'],
'default': 'Normal',
'description': localize('mssql.query.deadlockPriority', "Enable SET DEADLOCK_PRIORITY option")
},
'mssql.query.lockTimeout': {
'type': 'number',
'default': -1,
'description': localize('mssql.query.lockTimeout', "Enable SET LOCK TIMEOUT option (in milliseconds)")
},
'mssql.query.queryGovernorCostLimit': {
'type': 'number',
'default': -1,
'description': localize('mssql.query.queryGovernorCostLimit', "Enable SET QUERY_GOVERNOR_COST_LIMIT")
},
'mssql.query.ansiDefaults': {
'type': 'boolean',
'default': false,
'description': localize('mssql.query.ansiDefaults', "Enable SET ANSI_DEFAULTS")
},
'mssql.query.quotedIdentifier': {
'type': 'boolean',
'default': true,
'description': localize('mssql.query.quotedIdentifier', "Enable SET QUOTED_IDENTIFIER")
},
'mssql.query.ansiNullDefaultOn': {
'type': 'boolean',
'default': true,
'description': localize('mssql.query.ansiNullDefaultOn', "Enable SET ANSI_NULL_DFLT_ON")
},
'mssql.query.implicitTransactions': {
'type': 'boolean',
'default': false,
'description': localize('mssql.query.implicitTransactions', "Enable SET IMPLICIT_TRANSACTIONS")
},
'mssql.query.cursorCloseOnCommit': {
'type': 'boolean',
'default': false,
'description': localize('mssql.query.cursorCloseOnCommit', "Enable SET CURSOR_CLOSE_ON_COMMIT")
},
'mssql.query.ansiPadding': {
'type': 'boolean',
'default': true,
'description': localize('mssql.query.ansiPadding', "Enable SET ANSI_PADDING")
},
'mssql.query.ansiWarnings': {
'type': 'boolean',
'default': true,
'description': localize('mssql.query.ansiWarnings', "Enable SET ANSI_WARNINGS")
},
'mssql.query.ansiNulls': {
'type': 'boolean',
'default': true,
'description': localize('mssql.query.ansiNulls', "Enable SET ANSI_NULLS")
},
'mssql.query.alwaysEncryptedParameterization': {
'type': 'boolean',
'default': false,
'description': localize('mssql.query.alwaysEncryptedParameterization', "Enable Parameterization for Always Encrypted")
const queryEditorConfiguration: IConfigurationNode = {
...queryEditorConfigurationBaseNode,
properties: {
'queryEditor.results.saveAsCsv.includeHeaders': {
'type': 'boolean',
'description': localize('queryEditor.results.saveAsCsv.includeHeaders', "When true, column headers are included when saving results as CSV"),
'default': true
},
'queryEditor.results.saveAsCsv.delimiter': {
'type': 'string',
'description': localize('queryEditor.results.saveAsCsv.delimiter', "The custom delimiter to use between values when saving as CSV"),
'default': ','
},
'queryEditor.results.saveAsCsv.lineSeperator': {
'type': 'string',
'description': localize('queryEditor.results.saveAsCsv.lineSeperator', "Character(s) used for seperating rows when saving results as CSV"),
'default': null
},
'queryEditor.results.saveAsCsv.textIdentifier': {
'type': 'string',
'description': localize('queryEditor.results.saveAsCsv.textIdentifier', "Character used for enclosing text fields when saving results as CSV"),
'default': '\"'
},
'queryEditor.results.saveAsCsv.encoding': {
'type': 'string',
'description': localize('queryEditor.results.saveAsCsv.encoding', "File encoding used when saving results as CSV"),
'default': 'utf-8'
},
'queryEditor.results.saveAsXml.formatted': {
'type': 'string',
'description': localize('queryEditor.results.saveAsXml.formatted', "When true, XML output will be formatted when saving results as XML"),
'default': true
},
'queryEditor.results.saveAsXml.encoding': {
'type': 'string',
'description': localize('queryEditor.results.saveAsXml.encoding', "File encoding used when saving results as XML"),
'default': 'utf-8'
},
'queryEditor.results.streaming': {
'type': 'boolean',
'description': localize('queryEditor.results.streaming', "Enable results streaming; contains few minor visual issues"),
'default': true
},
'queryEditor.results.copyIncludeHeaders': {
'type': 'boolean',
'description': localize('queryEditor.results.copyIncludeHeaders', "Configuration options for copying results from the Results View"),
'default': false
},
'queryEditor.results.copyRemoveNewLine': {
'type': 'boolean',
'description': localize('queryEditor.results.copyRemoveNewLine', "Configuration options for copying multi-line results from the Results View"),
'default': true
},
'queryEditor.messages.showBatchTime': {
'type': 'boolean',
'description': localize('queryEditor.messages.showBatchTime', "Should execution time be shown for individual batches"),
'default': false
},
'queryEditor.messages.wordwrap': {
'type': 'boolean',
'description': localize('queryEditor.messages.wordwrap', "Word wrap messages"),
'default': true
},
'queryEditor.chart.defaultChartType': {
'type': 'string',
'enum': ['bar', 'doughnut', 'horizontalBar', 'line', 'pie', 'scatter', 'timeSeries'],
'default': 'horizontalBar',
'description': localize('queryEditor.chart.defaultChartType', "The default chart type to use when opening Chart Viewer from a Query Results")
},
'queryEditor.tabColorMode': {
'type': 'string',
'enum': ['off', 'border', 'fill'],
'enumDescriptions': [
localize('queryEditor.tabColorMode.off', "Tab coloring will be disabled"),
localize('queryEditor.tabColorMode.border', "The top border of each editor tab will be colored to match the relevant server group"),
localize('queryEditor.tabColorMode.fill', "Each editor tab's background color will match the relevant server group"),
],
'default': 'off',
'description': localize('queryEditor.tabColorMode', "Controls how to color tabs based on the server group of their active connection")
},
'queryEditor.showConnectionInfoInTitle': {
'type': 'boolean',
'description': localize('queryEditor.showConnectionInfoInTitle', "Controls whether to show the connection info for a tab in the title."),
'default': true
},
'queryEditor.promptToSaveGeneratedFiles': {
'type': 'boolean',
'default': false,
'description': localize('queryEditor.promptToSaveGeneratedFiles', "Prompt to save generated SQL files")
}
}
};
@@ -538,6 +413,10 @@ const initialShortcuts = [
{ name: 'sp_lock', primary: KeyMod.WinCtrl + KeyMod.Shift + KeyCode.KEY_2 }
];
const shortCutConfiguration: IConfigurationNode = {
...queryEditorConfigurationBaseNode
};
for (let i = 0; i < 9; i++) {
const queryIndex = i + 1;
let settingKey = `sql.query.shortcut${queryIndex}`;
@@ -553,7 +432,7 @@ for (let i = 0; i < 9; i++) {
accessor.get(IInstantiationService).createInstance(RunQueryShortcutAction).run(queryIndex);
}
});
registryProperties[settingKey] = {
shortCutConfiguration[settingKey] = {
'type': 'string',
'default': defaultVal,
'description': localize('queryShortcutDescription',
@@ -564,12 +443,8 @@ for (let i = 0; i < 9; i++) {
// Register the query-related configuration options
const configurationRegistry = <IConfigurationRegistry>Registry.as(ConfigExtensions.Configuration);
configurationRegistry.registerConfiguration({
'id': 'sqlEditor',
'title': 'SQL Editor',
'type': 'object',
'properties': registryProperties
});
configurationRegistry.registerConfiguration(queryEditorConfiguration);
configurationRegistry.registerConfiguration(shortCutConfiguration);
const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);

View File

@@ -22,7 +22,6 @@ import { ConnectionGlobalStatus } from 'sql/workbench/services/connection/browse
import * as TelemetryKeys from 'sql/platform/telemetry/common/telemetryKeys';
import { IResourceProviderService } from 'sql/workbench/services/resourceProvider/common/resourceProviderService';
import { IAngularEventingService, AngularEventType } from 'sql/platform/angularEventing/browser/angularEventingService';
import * as QueryConstants from 'sql/platform/query/common/constants';
import { Deferred } from 'sql/base/common/promise';
import { ConnectionOptionSpecialType } from 'sql/workbench/api/common/sqlExtHostTypes';
import { IAccountManagementService, AzureResource } from 'sql/platform/accounts/common/interfaces';
@@ -52,6 +51,7 @@ import { assign } from 'vs/base/common/objects';
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { IQueryEditorConfiguration } from 'sql/platform/query/common/query';
export class ConnectionManagementService extends Disposable implements IConnectionManagementService {
@@ -1339,7 +1339,7 @@ export class ConnectionManagementService extends Disposable implements IConnecti
}
public getTabColorForUri(uri: string): string {
if (WorkbenchUtils.getSqlConfigValue<string>(this._configurationService, 'tabColorMode') === QueryConstants.tabColorModeOff) {
if (this._configurationService.getValue<IQueryEditorConfiguration>('queryEditor').tabColorMode === 'off') {
return undefined;
}
let connectionProfile = this.getConnectionProfile(uri);

View File

@@ -36,6 +36,7 @@ import { assign } from 'vs/base/common/objects';
import { NullAdsTelemetryService } from 'sql/platform/telemetry/common/adsTelemetryService';
import { TestStorageService } from 'vs/workbench/test/common/workbenchTestServices';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IQueryEditorConfiguration } from 'sql/platform/query/common/query';
suite('SQL ConnectionManagementService tests', () => {
@@ -76,6 +77,10 @@ suite('SQL ConnectionManagementService tests', () => {
let connectionManagementService: ConnectionManagementService;
let configResult: { [key: string]: any } = {};
configResult['defaultEngine'] = 'MSSQL';
let queryEditorConfiguration: Partial<IQueryEditorConfiguration> = {
tabColorMode: 'fill'
};
let handleFirewallRuleResult: IHandleFirewallRuleResult;
let resolveHandleFirewallRuleDialog: boolean;
let isFirewallRuleAdded: boolean;
@@ -142,6 +147,8 @@ suite('SQL ConnectionManagementService tests', () => {
workspaceConfigurationServiceMock = TypeMoq.Mock.ofType(TestConfigurationService);
workspaceConfigurationServiceMock.setup(x => x.getValue(Constants.sqlConfigSectionName))
.returns(() => configResult);
workspaceConfigurationServiceMock.setup(x => x.getValue('queryEditor'))
.returns(() => queryEditorConfiguration);
connectionManagementService = createConnectionManagementService();