Compare commits

..

3 Commits

Author SHA1 Message Date
Karl Burtram
ebd620bf7b Add auto-update links in release branch 2018-02-14 10:30:51 -08:00
Karl Burtram
79980d95e4 Merge branch 'master' into release/0.26 2018-02-14 10:24:14 -08:00
Karl Burtram
250d84923c Update changelog and readme for February 2018-02-13 13:29:18 -08:00
9964 changed files with 118312 additions and 197627 deletions

9
.vscode/launch.json vendored
View File

@@ -1,6 +1,7 @@
{
"version": "0.1.0",
"configurations": [
{
"type": "node",
"request": "launch",
@@ -8,7 +9,7 @@
"program": "${workspaceFolder}/node_modules/gulp/bin/gulp.js",
"stopOnEntry": true,
"args": [
"hygiene"
"watch-extension:json-client"
],
"cwd": "${workspaceFolder}"
},
@@ -86,11 +87,7 @@
"runtimeArgs": [
"--inspect=5875"
],
"skipFiles": [
"**/winjs*.js"
],
"webRoot": "${workspaceFolder}",
"timeout": 15000
"webRoot": "${workspaceFolder}"
},
{
"type": "node",

View File

@@ -10,9 +10,6 @@
"when": "$(basename).ts"
}
},
"files.associations": {
"OSSREADME.json": "jsonc"
},
"search.exclude": {
"**/node_modules": true,
"**/bower_components": true,
@@ -38,5 +35,6 @@
}
}
],
"typescript.tsdk": "node_modules/typescript/lib"
}
"typescript.tsdk": "node_modules/typescript/lib",
"git.ignoreLimitWarning": true
}

View File

@@ -1,28 +1,6 @@
# Change Log
## Version 0.27.3
* Release date: March 28, 2017
* Release status: Public Preview
## What's new in this version
The March Public Preview release enables some key aspects of the SQL Operations
Studio extensibility story. Here are some highlights in this release.
* Enhance the Manage Dashboard extensibility model to support tabbed Insights and Configuration panes
* Dashboard Insights extensions for `sp_whoisactive` from [whoisactive.com](http://whoisactive.com)
* Extension Manager enables simple acquisition of 1st-party and 3rd-party extensions
* Add additional Extensibility APIs for `connection` and `objectexplorer` management
* Community Localization open for 10 languages
* Continue to fix important customer impacting GitHub issues
## Version 0.26.7
* Release date: February 16, 2017
* Release status: Public Preview Hotfix 1
## What's new in this version
* Bug fix for `#717 Selecting partial query and hitting Cmd or Ctrl+C opens terminal with Error message`
## Version 0.26.6
## Version 0.26.4
* Release date: February 15, 2017
* Release status: Public Preview
@@ -33,15 +11,16 @@ Here's some of the highlights in the February release.
* Support Auto-Update installation on Windows and macOS
* Publish RPM and DEB packages to offical Microsoft repos
* Fix `#6 Keep connection and selected database when opening new query tabs`
* Fix `#22 'Server Name' and 'Database Name' - Can these be drop downs instead of text` boxes?
* Fix #6 Keep connection and selected database when opening new query tabs
* Fix #22 'Server Name' and 'Database Name' - Can these be drop downs instead of text boxes?
* Fix #549 Silent/Very Silent Install results in application opening after installation
* Fix #481 Add "Check for updates" option.
* SQL Editor colorization and auto-completion fixes
* `#584 Keyword "FULL" not highlighted by IntelliSense`
* `#345 Colorize SQL functions within the editor`
* `#300 [#tempData] latest "]" will display green color`
* `#225 Keyword color mismatch`
* `#60 invalid sql syntax color highlighting when using temporary table in from clause`
* #584 Keyword "FULL" not highlighted by IntelliSense
* #345 Colorize SQL functions within the editor
* #300 [#tempData] latest "]" will display green color
* #225 Keyword color mismatch
* #60 invalid sql syntax color highlighting when using temporary table in from clause
* Introduce Connection extensibility API
* VS Code Editor 1.19 integration
* Update JustinPealing/html-query-plan component to pick-up several Query Plan viewer improvements

View File

@@ -1,19 +1,17 @@
# SQL Operations Studio
[![Join the chat at https://gitter.im/Microsoft/sqlopsstudio](https://badges.gitter.im/Microsoft/sqlopsstudio.svg)](https://gitter.im/Microsoft/sqlopsstudio?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
SQL Operations Studio is a data management tool that enables you to work with SQL Server, Azure SQL DB and SQL DW from Windows, macOS and Linux.
**Download SQL Operations Studio March Public Preview**
**Download SQL Operations Studio February Public Preview**
Platform | Link
-- | --
Windows Setup Installer | https://go.microsoft.com/fwlink/?linkid=870837
Windows ZIP | https://go.microsoft.com/fwlink/?linkid=870838
macOS ZIP | https://go.microsoft.com/fwlink/?linkid=870839
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=870840
Linux DEB | https://go.microsoft.com/fwlink/?linkid=870842
Linux RPM | https://go.microsoft.com/fwlink/?linkid=870841
Windows Setup Installer | https://go.microsoft.com/fwlink/?linkid=866480
Windows ZIP | https://go.microsoft.com/fwlink/?linkid=866479
macOS ZIP | https://go.microsoft.com/fwlink/?linkid=866481
Linux TAR.GZ | https://go.microsoft.com/fwlink/?linkid=866482
Linux DEB | https://go.microsoft.com/fwlink/?linkid=866484
Linux RPM | https://go.microsoft.com/fwlink/?linkid=866483
Go to our [download page](https://aka.ms/sqlopsstudio) for more specific instructions.
@@ -21,14 +19,6 @@ Try out the latest insiders build from `master` at https://github.com/Microsoft/
See the [change log](https://github.com/Microsoft/sqlopsstudio/blob/master/CHANGELOG.md) for additional details of what's in this release.
**Design Discussions**
The SQL Operations Studio team would like to incorporate community feedback earlier in the development process. To facilitate this, we'd like to share our designs while features are actively being built.
We're currently collecting input on the **SQL Agent** experience and enhancements to the Manage Dashboard that we're calling **"Command Center"**. We'll add additional design feedback requests below as we start work in new feature areas. Please leave comments on these issues to help us understand your requirements and shape feature development.
* [#750 Seeking community feedback on SQL Agent UX prototype](https://github.com/Microsoft/sqlopsstudio/issues/750)
**Feature Highlights**
- Cross-Platform DB management for Windows, macOS and Linux with simple XCopy deployment
@@ -58,33 +48,23 @@ please see the document [How to Contribute](https://github.com/Microsoft/sqlopss
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
## Localization
SQL Operations Studio localization is now open for community contributions. You can contribute to localization for both software and docs. https://aka.ms/SQLOpsStudioLoc
Localization is now opened for 10 languages: French, Italian, German, Spanish, Simplified Chinese, Traditional Chinese, Japanese, Korean, Russian, and Portuguese (Brazil). Help us make SQL Operations Studio available in your language!
## Privacy Statement
The [Microsoft Enterprise and Developer Privacy Statement](https://privacy.microsoft.com/en-us/privacystatement) describes the privacy statement of this software.
## Contributions and "thank you"
We would like to thank all our users who raised issues, and in particular the following users who helped contribute fixes:
* westerncj for `Removed duplicate contribution from README.md (#753)`
* ntovas for `Fix for duplicate extensions shown in "Save File" dialog. (#779)`
* SebastianPfliegel for `Add cursor snippet (#475)`
* mikaoelitiana for fix: `revert README and CONTRIBUTING after last VSCode merge (#574)`
* alextercete for `Reinstate menu item to install from VSIX (#682)`
* alextercete for `Fix "No extension gallery service configured" error (#427)`
* SebastianPfliegel for `Add cursor snippet (#475)`
* mwiedemeyer for `Fix #58: Default sort order for DB size widget (#111)`
* AlexTroshkin for `Show disconnect in context menu only when connectionProfile connected (#150)`
* AlexTroshkin for `Fix #138: Invalid syntax color highlighting (identity not highlighting) (#140))`
* stebet for `Fix #153: Fixing sql snippets that failed on a DB with case-sensitive collation. (#152)`
* SebastianPfliegel `Remove sqlExtensionHelp (#312)`
* olljanat for `Implemented npm version check (#314)`
* Adam Mechanic for helping with the `whoisactive` extension
* All community localization contributors *(will get list of individuals next month)*
And of course we'd like to thank the authors of all upstream dependencies. Please see a full list in the [ThirdPartyNotices.txt](https://raw.githubusercontent.com/Microsoft/sqlopsstudio/master/ThirdPartyNotices.txt)
## License

View File

@@ -11,7 +11,6 @@ install:
build_script:
- yarn
- .\node_modules\.bin\gulp electron
- .\node_modules\.bin\tsc -p .\src\tsconfig.monaco.json --noEmit
- npm run compile
test_script:

View File

@@ -1,12 +0,0 @@
[
{
"name": "ms-vscode.node-debug",
"version": "1.21.8",
"repo": "https://github.com/Microsoft/vscode-node-debug"
},
{
"name": "ms-vscode.node-debug2",
"version": "1.21.2",
"repo": "https://github.com/Microsoft/vscode-node-debug2"
}
]

View File

@@ -1,20 +0,0 @@
{
"env": {
"node": true,
"es6": true,
"browser": true
},
"rules": {
"no-console": 0,
"no-cond-assign": 0,
"no-unused-vars": 1,
"no-extra-semi": "warn",
"semi": "warn"
},
"extends": "eslint:recommended",
"parserOptions": {
"ecmaFeatures": {
"experimentalObjectRestSpread": true
}
}
}

View File

@@ -1,126 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const fs = require('fs');
const path = require('path');
const os = require('os');
// @ts-ignore review
const { remote } = require('electron');
const dialog = remote.dialog;
const builtInExtensionsPath = path.join(__dirname, '..', 'builtInExtensions.json');
const controlFilePath = path.join(os.homedir(), '.vscode-oss-dev', 'extensions', 'control.json');
function readJson(filePath) {
return JSON.parse(fs.readFileSync(filePath, { encoding: 'utf8' }));
}
function writeJson(filePath, obj) {
fs.writeFileSync(filePath, JSON.stringify(obj, null, 2));
}
function renderOption(form, id, title, value, checked) {
const input = document.createElement('input');
input.type = 'radio';
input.id = id;
input.name = 'choice';
input.value = value;
input.checked = !!checked;
form.appendChild(input);
const label = document.createElement('label');
label.setAttribute('for', id);
label.textContent = title;
form.appendChild(label);
return input;
}
function render(el, state) {
function setState(state) {
try {
writeJson(controlFilePath, state.control);
} catch (err) {
console.error(err);
}
el.innerHTML = '';
render(el, state);
}
const ul = document.createElement('ul');
const { builtin, control } = state;
for (const ext of builtin) {
const controlState = control[ext.name] || 'marketplace';
const li = document.createElement('li');
ul.appendChild(li);
const name = document.createElement('code');
name.textContent = ext.name;
li.appendChild(name);
const form = document.createElement('form');
li.appendChild(form);
const marketplaceInput = renderOption(form, `marketplace-${ext.name}`, 'Marketplace', 'marketplace', controlState === 'marketplace');
marketplaceInput.onchange = function () {
control[ext.name] = 'marketplace';
setState({ builtin, control });
};
const disabledInput = renderOption(form, `disabled-${ext.name}`, 'Disabled', 'disabled', controlState === 'disabled');
disabledInput.onchange = function () {
control[ext.name] = 'disabled';
setState({ builtin, control });
};
let local = undefined;
if (controlState !== 'marketplace' && controlState !== 'disabled') {
local = controlState;
}
const localInput = renderOption(form, `local-${ext.name}`, 'Local', 'local', !!local);
localInput.onchange = function () {
const result = dialog.showOpenDialog(remote.getCurrentWindow(), {
title: 'Choose Folder',
properties: ['openDirectory']
});
if (result && result.length >= 1) {
control[ext.name] = result[0];
}
setState({ builtin, control });
};
if (local) {
const localSpan = document.createElement('code');
localSpan.className = 'local';
localSpan.textContent = local;
form.appendChild(localSpan);
}
}
el.appendChild(ul);
}
function main() {
const el = document.getElementById('extensions');
const builtin = readJson(builtInExtensionsPath);
let control;
try {
control = readJson(controlFilePath);
} catch (err) {
control = {};
}
render(el, { builtin, control });
}
window.onload = main;

View File

@@ -1,46 +0,0 @@
<!-- Copyright (C) Microsoft Corporation. All rights reserved. -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Manage Built-in Extensions</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="browser-main.js"></script>
<style>
body {
font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
font-size: 10pt;
}
code {
font-family: 'Menlo', 'Courier New', 'Courier', monospace;
}
ul {
padding-left: 1em;
}
li {
list-style: none;
padding: 0.3em 0;
}
label {
margin-right: 1em;
}
form {
padding: 0.3em 0 0.3em 0.3em;
}
</style>
</head>
<body>
<h1>Built-in Extensions</h1>
<div id="extensions"></div>
</body>
</html>

View File

@@ -1,20 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const { app, BrowserWindow } = require('electron');
const url = require('url');
const path = require('path');
let window = null;
app.once('ready', () => {
window = new BrowserWindow({ width: 800, height: 600 });
window.setMenuBarVisibility(false);
window.loadURL(url.format({ pathname: path.join(__dirname, 'index.html'), protocol: 'file:', slashes: true }));
// window.webContents.openDevTools();
window.once('closed', () => window = null);
});
app.on('window-all-closed', () => app.quit());

View File

@@ -1,5 +0,0 @@
{
"name": "builtin",
"version": "0.1.0",
"main": "main.js"
}

View File

@@ -12,7 +12,6 @@ var File = require('vinyl');
var root = path.dirname(__dirname);
var sha1 = util.getVersion(root);
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
var semver = require('./monaco/package.json').version;
var headerVersion = semver + '(' + sha1 + ')';
@@ -22,14 +21,14 @@ var editorEntryPoints = [
{
name: 'vs/editor/editor.main',
include: [],
exclude: ['vs/css', 'vs/nls'],
prepend: ['out-build/vs/css.js', 'out-build/vs/nls.js'],
exclude: [ 'vs/css', 'vs/nls' ],
prepend: [ 'out-build/vs/css.js', 'out-build/vs/nls.js' ],
},
{
name: 'vs/base/common/worker/simpleWorker',
include: ['vs/editor/common/services/editorSimpleWorker'],
prepend: ['vs/loader.js'],
append: ['vs/base/worker/workerMain'],
include: [ 'vs/editor/common/services/editorSimpleWorker' ],
prepend: [ 'vs/loader.js' ],
append: [ 'vs/base/worker/workerMain' ],
dest: 'vs/base/worker/workerMain.js'
}
];
@@ -80,15 +79,14 @@ gulp.task('optimize-editor', ['clean-optimized-editor', 'compile-client-build'],
bundleLoader: false,
header: BUNDLED_FILE_HEADER,
bundleInfo: true,
out: 'out-editor',
languages: undefined
out: 'out-editor'
}));
gulp.task('clean-minified-editor', util.rimraf('out-editor-min'));
gulp.task('minify-editor', ['clean-minified-editor', 'optimize-editor'], common.minifyTask('out-editor'));
gulp.task('clean-editor-distro', util.rimraf('out-monaco-editor-core'));
gulp.task('editor-distro', ['clean-editor-distro', 'minify-editor', 'optimize-editor'], function () {
gulp.task('editor-distro', ['clean-editor-distro', 'minify-editor', 'optimize-editor'], function() {
return es.merge(
// other assets
es.merge(
@@ -99,17 +97,17 @@ gulp.task('editor-distro', ['clean-editor-distro', 'minify-editor', 'optimize-ed
// package.json
gulp.src('build/monaco/package.json')
.pipe(es.through(function (data) {
.pipe(es.through(function(data) {
var json = JSON.parse(data.contents.toString());
json.private = false;
data.contents = Buffer.from(JSON.stringify(json, null, ' '));
data.contents = new Buffer(JSON.stringify(json, null, ' '));
this.emit('data', data);
}))
.pipe(gulp.dest('out-monaco-editor-core')),
// README.md
gulp.src('build/monaco/README-npm.md')
.pipe(es.through(function (data) {
.pipe(es.through(function(data) {
this.emit('data', new File({
path: data.path.replace(/README-npm\.md/, 'README.md'),
base: data.base,
@@ -126,10 +124,10 @@ gulp.task('editor-distro', ['clean-editor-distro', 'minify-editor', 'optimize-ed
// min folder
es.merge(
gulp.src('out-editor-min/**/*')
).pipe(filterStream(function (path) {
).pipe(filterStream(function(path) {
// no map files
return !/(\.js\.map$)|(nls\.metadata\.json$)|(bundleInfo\.json$)/.test(path);
})).pipe(es.through(function (data) {
})).pipe(es.through(function(data) {
// tweak the sourceMappingURL
if (!/\.js$/.test(data.path)) {
this.emit('data', data);
@@ -142,50 +140,49 @@ gulp.task('editor-distro', ['clean-editor-distro', 'minify-editor', 'optimize-ed
var newStr = '//# sourceMappingURL=' + relativePathToMap.replace(/\\/g, '/');
strContents = strContents.replace(/\/\/\# sourceMappingURL=[^ ]+$/, newStr);
data.contents = Buffer.from(strContents);
data.contents = new Buffer(strContents);
this.emit('data', data);
})).pipe(gulp.dest('out-monaco-editor-core/min')),
// min-maps folder
es.merge(
gulp.src('out-editor-min/**/*')
).pipe(filterStream(function (path) {
).pipe(filterStream(function(path) {
// no map files
return /\.js\.map$/.test(path);
})).pipe(gulp.dest('out-monaco-editor-core/min-maps'))
);
});
gulp.task('analyze-editor-distro', function () {
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
gulp.task('analyze-editor-distro', function() {
var bundleInfo = require('../out-editor/bundleInfo.json');
var graph = bundleInfo.graph;
var bundles = bundleInfo.bundles;
var inverseGraph = {};
Object.keys(graph).forEach(function (module) {
Object.keys(graph).forEach(function(module) {
var dependencies = graph[module];
dependencies.forEach(function (dep) {
dependencies.forEach(function(dep) {
inverseGraph[dep] = inverseGraph[dep] || [];
inverseGraph[dep].push(module);
});
});
var detailed = {};
Object.keys(bundles).forEach(function (entryPoint) {
Object.keys(bundles).forEach(function(entryPoint) {
var included = bundles[entryPoint];
var includedMap = {};
included.forEach(function (included) {
included.forEach(function(included) {
includedMap[included] = true;
});
var explanation = [];
included.map(function (included) {
included.map(function(included) {
if (included.indexOf('!') >= 0) {
return;
}
var reason = (inverseGraph[included] || []).filter(function (mod) {
var reason = (inverseGraph[included]||[]).filter(function(mod) {
return !!includedMap[mod];
});
explanation.push({
@@ -201,7 +198,7 @@ gulp.task('analyze-editor-distro', function () {
});
function filterStream(testFunc) {
return es.through(function (data) {
return es.through(function(data) {
if (!testFunc(data.relative)) {
return;
}

View File

@@ -20,7 +20,6 @@ const sourcemaps = require('gulp-sourcemaps');
const nlsDev = require('vscode-nls-dev');
const root = path.dirname(__dirname);
const commit = util.getVersion(root);
const i18n = require('./lib/i18n');
const extensionsPath = path.join(path.dirname(__dirname), 'extensions');
@@ -30,8 +29,7 @@ const compilations = glob.sync('**/tsconfig.json', {
});
const getBaseUrl = out => `https://ticino.blob.core.windows.net/sourcemaps/${commit}/${out}`;
const languages = i18n.defaultLanguages.concat(process.env.VSCODE_QUALITY !== 'stable' ? i18n.extraLanguages : []);
const languages = ['chs', 'cht', 'jpn', 'kor', 'deu', 'fra', 'esn', 'rus', 'ita'];
const tasks = compilations.map(function (tsconfigFile) {
const absolutePath = path.join(extensionsPath, tsconfigFile);
@@ -57,19 +55,9 @@ const tasks = compilations.map(function (tsconfigFile) {
const srcBase = path.join(root, 'src');
const src = path.join(srcBase, '**');
const out = path.join(root, 'out');
const i18nPath = path.join(__dirname, '..', 'i18n');
const i18n = path.join(__dirname, '..', 'i18n');
const baseUrl = getBaseUrl(out);
let headerId, headerOut;
let index = relativeDirname.indexOf('/');
if (index < 0) {
headerId = 'vscode.' + relativeDirname;
headerOut = 'out';
} else {
headerId = 'vscode.' + relativeDirname.substr(0, index);
headerOut = relativeDirname.substr(index + 1) + '/out';
}
function createPipeline(build, emitError) {
const reporter = createReporter();
@@ -94,9 +82,7 @@ const tasks = compilations.map(function (tsconfigFile) {
sourceRoot: '../src'
}))
.pipe(tsFilter.restore)
.pipe(build ? nlsDev.createAdditionalLanguageFiles(languages, i18nPath, out) : es.through())
.pipe(build ? nlsDev.bundleMetaDataFiles(headerId, headerOut) : es.through())
.pipe(build ? nlsDev.bundleLanguageFiles() : es.through())
.pipe(build ? nlsDev.createAdditionalLanguageFiles(languages, i18n, out) : es.through())
.pipe(reporter.end(emitError));
return es.duplex(input, output);
@@ -143,7 +129,7 @@ const tasks = compilations.map(function (tsconfigFile) {
const watchInput = watcher(src, srcOpts);
return watchInput
.pipe(util.incremental(() => pipeline(), input))
.pipe(util.incremental(() => pipeline(true), input))
.pipe(gulp.dest(out));
});

View File

@@ -12,11 +12,7 @@ const gulptslint = require('gulp-tslint');
const gulpeslint = require('gulp-eslint');
const tsfmt = require('typescript-formatter');
const tslint = require('tslint');
const VinylFile = require('vinyl');
const vfs = require('vinyl-fs');
const path = require('path');
const fs = require('fs');
const pall = require('p-all');
/**
* Hygiene works by creating cascading subsets of all our files and
@@ -33,56 +29,55 @@ const all = [
'extensions/**/*',
'scripts/**/*',
'src/**/*',
'test/**/*',
'!**/node_modules/**'
'test/**/*'
];
const eolFilter = [
'**',
'!ThirdPartyNotices.txt',
'!LICENSE.txt',
'!extensions/**/out/**',
'!test/smoke/out/**',
'!**/node_modules/**',
'!**/fixtures/**',
'!**/*.{svg,exe,png,bmp,scpt,bat,cmd,cur,ttf,woff,eot}',
'!build/{lib,tslintRules}/**/*.js',
'!build/monaco/**',
'!build/win32/**',
'!build/**/*.sh',
'!build/tfs/**/*.js',
'!**/Dockerfile'
];
const indentationFilter = [
'**',
// except specific files
'!ThirdPartyNotices.txt',
'!LICENSE.txt',
'!src/vs/nls.js',
'!src/vs/css.js',
'!src/vs/loader.js',
'!src/vs/base/common/marked/raw.marked.js',
'!src/vs/base/common/winjs.base.raw.js',
'!src/vs/base/node/terminateProcess.sh',
'!src/vs/base/node/ps-win.ps1',
'!test/assert.js',
// except specific folders
'!test/smoke/out/**',
'!extensions/vscode-api-tests/testWorkspace/**',
'!extensions/vscode-api-tests/testWorkspace2/**',
'!build/monaco/**',
'!build/win32/**',
// except multiple specific files
'!**/package.json',
'!**/*.md',
'!**/*.ps1',
'!**/*.template',
'!**/*.yaml',
'!**/*.yml',
'!**/yarn.lock',
// except multiple specific folders
'!**/octicons/**',
'!**/fixtures/**',
'!**/lib/**',
'!extensions/**/out/**',
'!extensions/**/*.d.ts',
'!src/typings/**/*.d.ts',
'!src/vs/*/**/*.d.ts',
'!**/*.d.ts.recipe',
'!test/assert.js',
'!**/package.json',
'!**/octicons/**',
'!**/vs/base/common/marked/raw.marked.js',
'!**/vs/base/common/winjs.base.raw.js',
'!**/vs/base/node/terminateProcess.sh',
'!**/vs/base/node/ps-win.ps1',
'!**/vs/nls.js',
'!**/vs/css.js',
'!**/vs/loader.js',
'!extensions/**/snippets/**',
'!extensions/**/syntaxes/**',
'!extensions/**/themes/**',
'!extensions/**/colorize-fixtures/**',
// except specific file types
'!src/vs/*/**/*.d.ts',
'!src/typings/**/*.d.ts',
'!extensions/**/*.d.ts',
'!**/*.{svg,exe,png,bmp,scpt,bat,cmd,cur,ttf,woff,eot,md,ps1,template,yaml,yml,d.ts.recipe}',
'!build/{lib,tslintRules}/**/*.js',
'!build/**/*.sh',
'!build/tfs/**/*.js',
'!**/Dockerfile',
'!extensions/markdown/media/*.js'
'!extensions/vscode-api-tests/testWorkspace/**'
];
const copyrightFilter = [
@@ -100,7 +95,6 @@ const copyrightFilter = [
'!**/*.xpm',
'!**/*.opts',
'!**/*.disabled',
'!**/*.code-workspace',
'!build/**/*.init',
'!resources/linux/snap/snapcraft.yaml',
'!resources/win32/bin/code.js',
@@ -130,7 +124,6 @@ const tslintFilter = [
'!**/node_modules/**',
'!extensions/typescript/test/colorize-fixtures/**',
'!extensions/vscode-api-tests/testWorkspace/**',
'!extensions/vscode-api-tests/testWorkspace2/**',
'!extensions/**/*.test.ts',
'!extensions/html/server/lib/jquery.d.ts'
];
@@ -151,23 +144,31 @@ gulp.task('eslint', () => {
});
gulp.task('tslint', () => {
// {{SQL CARBON EDIT}}
const options = { emitError: false };
return vfs.src(all, { base: '.', follow: true, allowEmpty: true })
.pipe(filter(tslintFilter))
.pipe(gulptslint.default({ rulesDirectory: 'build/lib/tslint' }))
.pipe(gulptslint.default.report(options));
.pipe(gulptslint({ rulesDirectory: 'build/lib/tslint' }))
.pipe(gulptslint.report(options));
});
function hygiene(some) {
const hygiene = exports.hygiene = (some, options) => {
options = options || {};
let errorCount = 0;
const indentation = es.through(function (file) {
const lines = file.contents.toString('utf8').split(/\r\n|\r|\n/);
file.__lines = lines;
const eol = es.through(function (file) {
if (/\r\n?/g.test(file.contents.toString('utf8'))) {
console.error(file.relative + ': Bad EOL found');
errorCount++;
}
lines
this.emit('data', file);
});
const indentation = es.through(function (file) {
file.contents
.toString('utf8')
.split(/\r\n|\r|\n/)
.forEach((line, i) => {
if (/^\s*$/.test(line)) {
// empty or whitespace lines are OK
@@ -185,14 +186,9 @@ function hygiene(some) {
});
const copyrights = es.through(function (file) {
const lines = file.__lines;
for (let i = 0; i < copyrightHeaderLines.length; i++) {
if (lines[i] !== copyrightHeaderLines[i]) {
console.error(file.relative + ': Missing or bad copyright statement');
errorCount++;
break;
}
if (file.contents.toString('utf8').indexOf(copyrightHeader) !== 0) {
console.error(file.relative + ': Missing or bad copyright statement');
errorCount++;
}
this.emit('data', file);
@@ -200,20 +196,12 @@ function hygiene(some) {
const formatting = es.map(function (file, cb) {
tsfmt.processString(file.path, file.contents.toString('utf8'), {
verify: false,
verify: true,
tsfmt: true,
// verbose: true
// keep checkJS happy
editorconfig: undefined,
replace: undefined,
tsconfig: undefined,
tslint: undefined
}).then(result => {
let original = result.src.replace(/\r\n/gm, '\n');
let formatted = result.dest.replace(/\r\n/gm, '\n');
if (original !== formatted) {
console.error('File not formatted:', file.relative);
if (result.error) {
console.error(result.message);
errorCount++;
}
cb(null, file);
@@ -223,31 +211,43 @@ function hygiene(some) {
});
});
const tslintConfiguration = tslint.Configuration.findConfiguration('tslint.json', '.');
const tslintOptions = { fix: false, formatter: 'json' };
const tsLinter = new tslint.Linter(tslintOptions);
function reportFailures(failures) {
failures.forEach(failure => {
const name = failure.name || failure.fileName;
const position = failure.startPosition;
const line = position.lineAndCharacter ? position.lineAndCharacter.line : position.line;
const character = position.lineAndCharacter ? position.lineAndCharacter.character : position.character;
// console.error(`${name}:${line + 1}:${character + 1}:${failure.failure}`);
});
}
const tsl = es.through(function (file) {
const configuration = tslint.Configuration.findConfiguration(null, '.');
const options = { formatter: 'json', rulesDirectory: 'build/lib/tslint' };
const contents = file.contents.toString('utf8');
tsLinter.lint(file.relative, contents, tslintConfiguration.results);
const linter = new tslint.Linter(options);
linter.lint(file.relative, contents, configuration.results);
const result = linter.getResult();
if (result.failures.length > 0) {
reportFailures(result.failures);
errorCount += result.failures.length;
}
this.emit('data', file);
});
let input;
if (Array.isArray(some) || typeof some === 'string' || !some) {
input = vfs.src(some || all, { base: '.', follow: true, allowEmpty: true });
} else {
input = some;
}
const result = input
const result = vfs.src(some || all, { base: '.', follow: true, allowEmpty: true })
.pipe(filter(f => !f.stat.isDirectory()))
.pipe(filter(eolFilter))
// {{SQL CARBON EDIT}}
//.pipe(options.skipEOL ? es.through() : eol)
.pipe(filter(indentationFilter))
.pipe(indentation)
.pipe(filter(copyrightFilter));
.pipe(filter(copyrightFilter))
// {{SQL CARBON EDIT}}
// .pipe(copyrights);
//.pipe(copyrights);
const typescript = result
.pipe(filter(tslintFilter))
@@ -257,52 +257,23 @@ function hygiene(some) {
const javascript = result
.pipe(filter(eslintFilter))
.pipe(gulpeslint('src/.eslintrc'))
.pipe(gulpeslint.formatEach('compact'));
// {{SQL CARBON EDIT}}
.pipe(gulpeslint.formatEach('compact'))
// {{SQL CARBON EDIT}}
// .pipe(gulpeslint.failAfterError());
let count = 0;
return es.merge(typescript, javascript)
.pipe(es.through(function (data) {
// {{SQL CARBON EDIT}}
this.emit('end');
}));
}
return es.merge(typescript, javascript)
.pipe(es.through(null, function () {
// {{SQL CARBON EDIT}}
// if (errorCount > 0) {
// this.emit('error', 'Hygiene failed with ' + errorCount + ' errors. Check \'build/gulpfile.hygiene.js\'.');
// } else {
// this.emit('end');
// }
this.emit('end');
}));
};
function createGitIndexVinyls(paths) {
const cp = require('child_process');
const repositoryPath = process.cwd();
const fns = paths.map(relativePath => () => new Promise((c, e) => {
const fullPath = path.join(repositoryPath, relativePath);
fs.stat(fullPath, (err, stat) => {
if (err && err.code === 'ENOENT') { // ignore deletions
return c(null);
} else if (err) {
return e(err);
}
cp.exec(`git show :${relativePath}`, { maxBuffer: 2000 * 1024, encoding: 'buffer' }, (err, out) => {
if (err) {
return e(err);
}
c(new VinylFile({
path: fullPath,
base: repositoryPath,
contents: out,
stat
}));
});
});
}));
return pall(fns, { concurrency: 4 })
.then(r => r.filter(p => !!p));
}
gulp.task('hygiene', () => hygiene());
gulp.task('hygiene', () => hygiene(''));
// this allows us to run hygiene as a git pre-commit hook
if (require.main === module) {
@@ -313,19 +284,22 @@ if (require.main === module) {
process.exit(1);
});
if (process.argv.length > 2) {
hygiene(process.argv.slice(2)).on('error', err => {
console.error();
console.error(err);
process.exit(1);
});
} else {
cp.exec('git config core.autocrlf', (err, out) => {
const skipEOL = out.trim() === 'true';
if (process.argv.length > 2) {
return hygiene(process.argv.slice(2), { skipEOL: skipEOL }).on('error', err => {
console.error();
console.error(err);
process.exit(1);
});
}
cp.exec('git diff --cached --name-only', { maxBuffer: 2000 * 1024 }, (err, out) => {
if (err) {
console.error();
console.error(err);
process.exit(1);
return;
}
const some = out
@@ -333,18 +307,12 @@ if (require.main === module) {
.filter(l => !!l);
if (some.length > 0) {
console.log('Reading git index versions...');
createGitIndexVinyls(some)
.then(vinyls => new Promise((c, e) => hygiene(es.readArray(vinyls))
.on('end', () => c())
.on('error', e)))
.catch(err => {
console.error();
console.error(err);
process.exit(1);
});
hygiene(some, { skipEOL: skipEOL }).on('error', err => {
console.error();
console.error(err);
process.exit(1);
});
}
});
}
});
}

View File

@@ -6,21 +6,9 @@
'use strict';
const gulp = require('gulp');
const json = require('gulp-json-editor');
const buffer = require('gulp-buffer');
const filter = require('gulp-filter');
const es = require('event-stream');
const util = require('./lib/util');
const remote = require('gulp-remote-src');
const zip = require('gulp-vinyl-zip');
const assign = require('object-assign');
// {{SQL CARBON EDIT}}
const jeditor = require('gulp-json-editor');
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const pkg = require('../package.json');
gulp.task('mixin', function () {
// {{SQL CARBON EDIT}}
const updateUrl = process.env['SQLOPS_UPDATEURL'];
@@ -36,17 +24,10 @@ gulp.task('mixin', function () {
return;
}
// {{SQL CARBON EDIT}}
let serviceUrl = 'https://sqlopsextensions.blob.core.windows.net/marketplace/v1/extensionsGallery.json';
if (quality === 'insider') {
serviceUrl = `https://sqlopsextensions.blob.core.windows.net/marketplace/v1/extensionsGallery-${quality}.json`;
}
// {{SQL CARBON EDIT}}
let newValues = {
"updateUrl": updateUrl,
"quality": quality,
"extensionsGallery": {
"serviceUrl": serviceUrl
}
"quality": quality
};
return gulp.src('./product.json')

View File

@@ -13,6 +13,14 @@ const filter = require('gulp-filter');
gulp.task('clean-mssql-extension', util.rimraf('extensions/mssql/node_modules'));
gulp.task('clean-credentials-extension', util.rimraf('extensions/credentials/node_modules'));
gulp.task('clean-extensions-modules', util.rimraf('extensions-modules/node_modules'));
gulp.task('clean-protocol', ['clean-extensions-modules', 'clean-mssql-extension', 'clean-credentials-extension', 'clean-client', 'clean-jsonrpc', 'clean-server', 'clean-types']);
// Tasks to clean extensions modules
gulp.task('clean-mssql-ext-mod', util.rimraf('extensions/mssql/node_modules/extensions-modules'));
gulp.task('clean-credentials-ext-mod', util.rimraf('extensions/credentials/node_modules/extensions-modules'));
gulp.task('clean-build-ext-mod', util.rimraf('build/node_modules/extensions-modules'));
gulp.task('clean-ext-mod', ['clean-mssql-ext-mod', 'clean-credentials-ext-mod', 'clean-build-ext-mod', 'clean-extensions-modules']);
gulp.task('fmt', () => formatStagedFiles());
const formatFiles = (some) => {

View File

@@ -27,22 +27,17 @@ const common = require('./lib/optimize');
const nlsDev = require('vscode-nls-dev');
const root = path.dirname(__dirname);
const commit = util.getVersion(root);
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const packageJson = require('../package.json');
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const product = require('../product.json');
const crypto = require('crypto');
const i18n = require('./lib/i18n');
// {{SQL CARBON EDIT}}
const serviceDownloader = require('service-downloader').ServiceDownloadProvider;
const platformInfo = require('service-downloader/out/platform').PlatformInformation;
const serviceInstaller = require('../extensions-modules/lib/languageservice/serviceInstallerUtil');
const glob = require('glob');
const deps = require('./dependencies');
const getElectronVersion = require('./lib/electron').getElectronVersion;
const createAsar = require('./lib/asar').createAsar;
const productionDependencies = deps.getProductionDependencies(path.dirname(__dirname));
// @ts-ignore
// {{SQL CARBON EDIT}}
var del = require('del');
const extensionsRoot = path.join(root, 'extensions');
@@ -60,24 +55,16 @@ const nodeModules = [
.concat(_.uniq(productionDependencies.map(d => d.name)))
.concat(baseModules);
// Build
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const builtInExtensions = require('./builtInExtensions.json');
const builtInExtensions = [
{ name: 'ms-vscode.node-debug', version: '1.19.8' },
{ name: 'ms-vscode.node-debug2', version: '1.19.4' }
];
const excludedExtensions = [
'vscode-api-tests',
'vscode-colorize-tests',
'ms-vscode.node-debug',
'ms-vscode.node-debug2',
];
// {{SQL CARBON EDIT}}
const vsce = require('vsce');
const sqlBuiltInExtensions = [
// Add SQL built-in extensions here.
// the extension will be excluded from SQLOps package and will have separate vsix packages
'agent'
'vscode-colorize-tests'
];
const vscodeEntryPoints = _.flatten([
@@ -108,8 +95,7 @@ const vscodeResources = [
'out-build/vs/workbench/parts/welcome/walkThrough/**/*.md',
'out-build/vs/workbench/services/files/**/*.exe',
'out-build/vs/workbench/services/files/**/*.md',
'out-build/vs/code/electron-browser/sharedProcess/sharedProcess.js',
'out-build/vs/code/electron-browser/issue/issueReporter.js',
'out-build/vs/code/electron-browser/sharedProcess.js',
// {{SQL CARBON EDIT}}
'out-build/sql/workbench/electron-browser/splashscreen/*',
'out-build/sql/**/*.{svg,png,cur,html}',
@@ -127,7 +113,6 @@ const vscodeResources = [
'out-build/sql/parts/grid/views/**/*.html',
'out-build/sql/parts/tasks/**/*.html',
'out-build/sql/parts/taskHistory/viewlet/media/**',
'out-build/sql/parts/jobManagement/common/media/*.svg',
'out-build/sql/media/objectTypes/*.svg',
'out-build/sql/media/icons/*.svg',
'!**/test/**'
@@ -139,7 +124,10 @@ const BUNDLED_FILE_HEADER = [
' *--------------------------------------------------------*/'
].join('\n');
const languages = i18n.defaultLanguages.concat([]); // i18n.defaultLanguages.concat(process.env.VSCODE_QUALITY !== 'stable' ? i18n.extraLanguages : []);
var languages = ['chs', 'cht', 'jpn', 'kor', 'deu', 'fra', 'esn', 'rus', 'ita'];
if (process.env.VSCODE_QUALITY !== 'stable') {
languages = languages.concat(['ptb', 'hun', 'trk']); // Add languages requested by the community to non-stable builds
}
gulp.task('clean-optimized-vscode', util.rimraf('out-vscode'));
gulp.task('optimize-vscode', ['clean-optimized-vscode', 'compile-build', 'compile-extensions-build'], common.optimizeTask({
@@ -149,8 +137,7 @@ gulp.task('optimize-vscode', ['clean-optimized-vscode', 'compile-build', 'compil
loaderConfig: common.loaderConfig(nodeModules),
header: BUNDLED_FILE_HEADER,
out: 'out-vscode',
languages: languages,
bundleInfo: undefined
languages: languages
}));
@@ -172,7 +159,7 @@ const config = {
version: getElectronVersion(),
productAppName: product.nameLong,
companyName: 'Microsoft Corporation',
copyright: 'Copyright (C) 2018 Microsoft. All rights reserved',
copyright: 'Copyright (C) 2017 Microsoft. All rights reserved',
darwinIcon: 'resources/darwin/code.icns',
darwinBundleIdentifier: product.darwinBundleIdentifier,
darwinApplicationCategoryType: 'public.app-category.developer-tools',
@@ -191,7 +178,7 @@ const config = {
name: product.nameLong,
urlSchemes: [product.urlProtocol]
}],
darwinCredits: darwinCreditsTemplate ? Buffer.from(darwinCreditsTemplate({ commit: commit, date: new Date().toISOString() })) : void 0,
darwinCredits: darwinCreditsTemplate ? new Buffer(darwinCreditsTemplate({ commit: commit, date: new Date().toISOString() })) : void 0,
linuxExecutableName: product.applicationName,
winIcon: 'resources/win32/code.ico',
token: process.env['VSCODE_MIXIN_PASSWORD'] || process.env['GITHUB_TOKEN'] || void 0,
@@ -255,26 +242,6 @@ function computeChecksum(filename) {
return hash;
}
function packageBuiltInExtensions() {
const sqlBuiltInLocalExtensionDescriptions = glob.sync('extensions/*/package.json')
.map(manifestPath => {
const extensionPath = path.dirname(path.join(root, manifestPath));
const extensionName = path.basename(extensionPath);
return { name: extensionName, path: extensionPath };
})
.filter(({ name }) => excludedExtensions.indexOf(name) === -1)
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
.filter(({ name }) => sqlBuiltInExtensions.indexOf(name) >= 0);
sqlBuiltInLocalExtensionDescriptions.forEach(element => {
const packagePath = path.join(path.dirname(root), element.name + '.vsix');
console.info('Creating vsix for ' + element.path + ' result:' + packagePath);
vsce.createVSIX({
cwd: element.path,
packagePath: packagePath
});
});
}
function packageTask(platform, arch, opts) {
opts = opts || {};
@@ -304,10 +271,7 @@ function packageTask(platform, arch, opts) {
return { name: extensionName, path: extensionPath };
})
.filter(({ name }) => excludedExtensions.indexOf(name) === -1)
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
// {{SQL CARBON EDIT}}
.filter(({ name }) => sqlBuiltInExtensions.indexOf(name) === -1);
packageBuiltInExtensions();
.filter(({ name }) => builtInExtensions.every(b => b.name !== name));
const localExtensions = es.merge(...localExtensionDescriptions.map(extension => {
const nlsFilter = filter('**/*.nls.json', { restore: true });
@@ -329,12 +293,16 @@ function packageTask(platform, arch, opts) {
const localExtensionDependencies = gulp.src(extensionDepsSrc, { base: '.', dot: true })
.pipe(filter(['**', '!**/package-lock.json']))
.pipe(util.cleanNodeModule('account-provider-azure', ['node_modules/date-utils/doc/**', 'node_modules/adal_node/node_modules/**'], undefined))
.pipe(util.cleanNodeModule('dataprotocol-client', ['node_modules/**', 'src/*.js'], undefined))
.pipe(util.cleanNodeModule('extensions-modules', ['node_modules/**', 'src/*.js'], undefined))
.pipe(util.cleanNodeModule('typescript', ['**/**'], undefined));
const sources = es.merge(src, localExtensions, localExtensionDependencies)
.pipe(util.setExecutableBit(['**/*.sh']))
.pipe(filter(['**', '!**/*.js.map']));
.pipe(filter(['**',
'!**/*.js.map',
'!extensions/**/node_modules/**/{test, tests}/**',
'!extensions/**/node_modules/**/test.js']));
let version = packageJson.version;
const quality = product.quality;
@@ -358,7 +326,7 @@ function packageTask(platform, arch, opts) {
// TODO the API should be copied to `out` during compile, not here
const api = gulp.src('src/vs/vscode.d.ts').pipe(rename('out/vs/vscode.d.ts'));
// {{SQL CARBON EDIT}}
// {{SQL CARBON EDIT}}
const dataApi = gulp.src('src/vs/data.d.ts').pipe(rename('out/sql/data.d.ts'));
const depsSrc = [
@@ -372,7 +340,6 @@ function packageTask(platform, arch, opts) {
.pipe(util.cleanNodeModule('oniguruma', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node', 'src/*.js']))
.pipe(util.cleanNodeModule('windows-mutex', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('native-keymap', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('native-is-elevated', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('native-watchdog', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('spdlog', ['binding.gyp', 'build/**', 'deps/**', 'src/**', 'test/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('jschardet', ['dist/**']))
@@ -380,27 +347,18 @@ function packageTask(platform, arch, opts) {
.pipe(util.cleanNodeModule('windows-process-tree', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('gc-signals', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node', 'src/index.js']))
.pipe(util.cleanNodeModule('keytar', ['binding.gyp', 'build/**', 'src/**', 'script/**', 'node_modules/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('node-pty', ['binding.gyp', 'build/**', 'src/**', 'tools/**'], ['build/Release/*.exe', 'build/Release/*.dll', 'build/Release/*.node']))
// {{SQL CARBON EDIT}}
.pipe(util.cleanNodeModule('node-pty', ['binding.gyp', 'build/**', 'src/**', 'tools/**'], ['build/Release/*.node', 'build/Release/*.dll', 'build/Release/*.exe']))
.pipe(util.cleanNodeModule('chart.js', ['node_modules/**'], undefined))
.pipe(util.cleanNodeModule('emmet', ['node_modules/**'], undefined))
.pipe(util.cleanNodeModule('pty.js', ['build/**'], ['build/Release/**']))
.pipe(util.cleanNodeModule('jquery-ui', ['external/**', 'demos/**'], undefined))
.pipe(util.cleanNodeModule('core-js', ['**/**'], undefined))
.pipe(util.cleanNodeModule('slickgrid', ['node_modules/**', 'examples/**'], undefined))
.pipe(util.cleanNodeModule('nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['**/*.node', '**/*.a']))
.pipe(util.cleanNodeModule('vsda', ['binding.gyp', 'README.md', 'build/**', '*.bat', '*.sh', '*.cpp', '*.h'], ['build/Release/vsda.node']))
.pipe(createAsar(path.join(process.cwd(), 'node_modules'), ['**/*.node', '**/vscode-ripgrep/bin/*', '**/node-pty/build/Release/*'], 'app/node_modules.asar'));
// {{SQL CARBON EDIT}}
let copiedModules = gulp.src([
'node_modules/jquery/**/*.*',
'node_modules/reflect-metadata/**/*.*',
'node_modules/slickgrid/**/*.*',
'node_modules/underscore/**/*.*',
'node_modules/zone.js/**/*.*',
'node_modules/chart.js/**/*.*'
], { base: '.', dot: true });
.pipe(util.cleanNodeModule('nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['**/*.node', '**/*.a']))
.pipe(util.cleanNodeModule('vsda', ['binding.gyp', 'README.md', 'build/**', '*.bat', '*.sh', '*.cpp', '*.h'], ['build/Release/vsda.node']));
let all = es.merge(
packageJsonStream,
@@ -408,8 +366,7 @@ function packageTask(platform, arch, opts) {
license,
watermark,
api,
// {{SQL CARBON EDIT}}
copiedModules,
// {{SQL CARBON EDIT}}
dataApi,
sources,
deps
@@ -480,21 +437,25 @@ gulp.task('vscode-linux-x64-min', ['minify-vscode', 'clean-vscode-linux-x64'], p
gulp.task('vscode-linux-arm-min', ['minify-vscode', 'clean-vscode-linux-arm'], packageTask('linux', 'arm', { minified: true }));
// Transifex Localizations
const innoSetupConfig = {
'zh-cn': { codePage: 'CP936', defaultInfo: { name: 'Simplified Chinese', id: '$0804', } },
'zh-tw': { codePage: 'CP950', defaultInfo: { name: 'Traditional Chinese', id: '$0404' } },
'ko': { codePage: 'CP949', defaultInfo: { name: 'Korean', id: '$0412' } },
'ja': { codePage: 'CP932' },
'de': { codePage: 'CP1252' },
'fr': { codePage: 'CP1252' },
'es': { codePage: 'CP1252' },
'ru': { codePage: 'CP1251' },
'it': { codePage: 'CP1252' },
'pt-br': { codePage: 'CP1252' },
'hu': { codePage: 'CP1250' },
'tr': { codePage: 'CP1254' }
};
const vscodeLanguages = [
'zh-hans',
'zh-hant',
'ja',
'ko',
'de',
'fr',
'es',
'ru',
'it',
'pt-br',
'hu',
'tr'
];
const setupDefaultLanguages = [
'zh-hans',
'zh-hant',
'ko'
];
const apiHostname = process.env.TRANSIFEX_API_URL;
const apiName = process.env.TRANSIFEX_API_NAME;
@@ -502,48 +463,27 @@ const apiToken = process.env.TRANSIFEX_API_TOKEN;
gulp.task('vscode-translations-push', ['optimize-vscode'], function () {
const pathToMetadata = './out-vscode/nls.metadata.json';
const pathToExtensions = './extensions/*';
const pathToExtensions = './extensions/**/*.nls.json';
const pathToSetup = 'build/win32/**/{Default.isl,messages.en.isl}';
return es.merge(
gulp.src(pathToMetadata).pipe(i18n.createXlfFilesForCoreBundle()),
gulp.src(pathToSetup).pipe(i18n.createXlfFilesForIsl()),
gulp.src(pathToExtensions).pipe(i18n.createXlfFilesForExtensions())
).pipe(i18n.findObsoleteResources(apiHostname, apiName, apiToken)
gulp.src(pathToMetadata).pipe(i18n.prepareXlfFiles()),
gulp.src(pathToSetup).pipe(i18n.prepareXlfFiles()),
gulp.src(pathToExtensions).pipe(i18n.prepareXlfFiles('vscode-extensions'))
).pipe(i18n.pushXlfFiles(apiHostname, apiName, apiToken));
});
gulp.task('vscode-translations-push-test', ['optimize-vscode'], function () {
const pathToMetadata = './out-vscode/nls.metadata.json';
const pathToExtensions = './extensions/*';
const pathToSetup = 'build/win32/**/{Default.isl,messages.en.isl}';
return es.merge(
gulp.src(pathToMetadata).pipe(i18n.createXlfFilesForCoreBundle()),
gulp.src(pathToSetup).pipe(i18n.createXlfFilesForIsl()),
gulp.src(pathToExtensions).pipe(i18n.createXlfFilesForExtensions())
).pipe(i18n.findObsoleteResources(apiHostname, apiName, apiToken)
).pipe(vfs.dest('../vscode-transifex-input'));
});
gulp.task('vscode-translations-pull', function () {
[...i18n.defaultLanguages, ...i18n.extraLanguages].forEach(language => {
i18n.pullCoreAndExtensionsXlfFiles(apiHostname, apiName, apiToken, language).pipe(vfs.dest(`../vscode-localization/${language.id}/build`));
let includeDefault = !!innoSetupConfig[language.id].defaultInfo;
i18n.pullSetupXlfFiles(apiHostname, apiName, apiToken, language, includeDefault).pipe(vfs.dest(`../vscode-localization/${language.id}/setup`));
});
return es.merge(
i18n.pullXlfFiles('vscode-editor', apiHostname, apiName, apiToken, vscodeLanguages),
i18n.pullXlfFiles('vscode-workbench', apiHostname, apiName, apiToken, vscodeLanguages),
i18n.pullXlfFiles('vscode-extensions', apiHostname, apiName, apiToken, vscodeLanguages),
i18n.pullXlfFiles('vscode-setup', apiHostname, apiName, apiToken, setupDefaultLanguages)
).pipe(vfs.dest('../vscode-localization'));
});
gulp.task('vscode-translations-import', function () {
[...i18n.defaultLanguages, ...i18n.extraLanguages].forEach(language => {
gulp.src(`../vscode-localization/${language.id}/build/*/*.xlf`)
.pipe(i18n.prepareI18nFiles())
.pipe(vfs.dest(`./i18n/${language.folderName}`));
gulp.src(`../vscode-localization/${language.id}/setup/*/*.xlf`)
.pipe(i18n.prepareIslFiles(language, innoSetupConfig[language.id]))
.pipe(vfs.dest(`./build/win32/i18n`));
});
return gulp.src('../vscode-localization/**/*.xlf').pipe(i18n.prepareJsonFiles()).pipe(vfs.dest('./i18n'));
});
// Sourcemaps
@@ -569,8 +509,7 @@ gulp.task('upload-vscode-sourcemaps', ['minify-vscode'], () => {
const allConfigDetailsPath = path.join(os.tmpdir(), 'configuration.json');
gulp.task('upload-vscode-configuration', ['generate-vscode-configuration'], () => {
const branch = process.env.BUILD_SOURCEBRANCH;
if (!/\/master$/.test(branch) && branch.indexOf('/release/') < 0) {
if (!branch.endsWith('/master') && branch.indexOf('/release/') < 0) {
console.log(`Only runs on master and release branches, not ${branch}`);
return;
}
@@ -665,7 +604,6 @@ function versionStringToNumber(versionStr) {
return parseInt(match[1], 10) * 1e4 + parseInt(match[2], 10) * 1e2 + parseInt(match[3], 10);
}
// This task is only run for the MacOS build
gulp.task('generate-vscode-configuration', () => {
return new Promise((resolve, reject) => {
const buildDir = process.env['AGENT_BUILDDIRECTORY'];
@@ -675,8 +613,7 @@ gulp.task('generate-vscode-configuration', () => {
const userDataDir = path.join(os.tmpdir(), 'tmpuserdata');
const extensionsDir = path.join(os.tmpdir(), 'tmpextdir');
const appName = process.env.VSCODE_QUALITY === 'insider' ? 'Visual\\ Studio\\ Code\\ -\\ Insiders.app' : 'Visual\\ Studio\\ Code.app';
const appPath = path.join(buildDir, `VSCode-darwin/${appName}/Contents/Resources/app/bin/code`);
const appPath = path.join(buildDir, 'VSCode-darwin/Visual\\ Studio\\ Code\\ -\\ Insiders.app/Contents/Resources/app/bin/code');
const codeProc = cp.exec(`${appPath} --export-default-configuration='${allConfigDetailsPath}' --wait --user-data-dir='${userDataDir}' --extensions-dir='${extensionsDir}'`);
const timer = setTimeout(() => {
@@ -705,25 +642,27 @@ gulp.task('generate-vscode-configuration', () => {
// {{SQL CARBON EDIT}}
// Install service locally before building carbon
function installService() {
let config = require('../extensions/mssql/src/config.json');
return platformInfo.getCurrent().then(p => {
let runtime = p.runtimeId;
// fix path since it won't be correct
config.installDirectory = path.join(__dirname, '../extensions/mssql/src', config.installDirectory);
var installer = new serviceDownloader(config);
let serviceInstallFolder = installer.getInstallDirectory(runtime);
console.log('Cleaning up the install folder: ' + serviceInstallFolder);
return del(serviceInstallFolder + '/*').then(() => {
console.log('Installing the service. Install folder: ' + serviceInstallFolder);
return installer.installService(runtime);
}, delError => {
console.log('failed to delete the install folder error: ' + delError);
});
function installService(extObj, path) {
var installer = new serviceInstaller.ServiceInstaller(extObj, path);
installer.getServiceInstallDirectoryRoot().then(serviceInstallFolder => {
console.log('Cleaning up the install folder: ' + serviceInstallFolder);
del(serviceInstallFolder + '/*').then(() => {
console.log('Installing the service. Install folder: ' + serviceInstallFolder);
installer.installService();
}, delError => {
console.log('failed to delete the install folder error: ' + delError);
});
}, getFolderPathError => {
console.log('failed to call getServiceInstallDirectoryRoot error: ' + getFolderPathError);
});
}
gulp.task('install-sqltoolsservice', () => {
return installService();
var mssqlExt = require('../extensions/mssql/client/out/models/constants');
var extObj = new mssqlExt.Constants();
var path = '../extensions/mssql/client/out/config.json';
return installService(extObj, path);
});

View File

@@ -12,12 +12,9 @@ const shell = require('gulp-shell');
const es = require('event-stream');
const vfs = require('vinyl-fs');
const util = require('./lib/util');
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const packageJson = require('../package.json');
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const product = require('../product.json');
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const rpmDependencies = require('../resources/linux/rpm/dependencies.json');
const rpmDependencies = require('../resources/linux/rpm/dependencies');
const linuxPackageRevision = Math.floor(new Date().getTime() / 1000);
@@ -114,7 +111,8 @@ function buildDebPackage(arch) {
return shell.task([
'chmod 755 ' + product.applicationName + '-' + debArch + '/DEBIAN/postinst ' + product.applicationName + '-' + debArch + '/DEBIAN/prerm ' + product.applicationName + '-' + debArch + '/DEBIAN/postrm',
'mkdir -p deb',
'fakeroot dpkg-deb -b ' + product.applicationName + '-' + debArch + ' deb'
'fakeroot dpkg-deb -b ' + product.applicationName + '-' + debArch + ' deb',
'dpkg-scanpackages deb /dev/null > Packages'
], { cwd: '.build/linux/deb/' + debArch });
}
@@ -222,10 +220,10 @@ function prepareSnapPackage(arch) {
function buildSnapPackage(arch) {
const snapBuildPath = getSnapBuildPath(arch);
const snapFilename = `${product.applicationName}-${packageJson.version}-${linuxPackageRevision}-${arch}.snap`;
return shell.task([
`chmod +x ${snapBuildPath}/electron-launch`,
`cd ${snapBuildPath} && snapcraft snap --output ../${snapFilename}`
`cd ${snapBuildPath} && snapcraft snap`
]);
}

View File

@@ -11,11 +11,8 @@ const assert = require('assert');
const cp = require('child_process');
const _7z = require('7zip')['7z'];
const util = require('./lib/util');
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const pkg = require('../package.json');
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const product = require('../product.json');
const vfs = require('vinyl-fs');
const repoPath = path.dirname(__dirname);
// {{SQL CARBON EDIT}}
@@ -94,13 +91,3 @@ gulp.task('vscode-win32-ia32-archive', ['clean-vscode-win32-ia32-archive'], arch
gulp.task('clean-vscode-win32-x64-archive', util.rimraf(zipDir('x64')));
gulp.task('vscode-win32-x64-archive', ['clean-vscode-win32-x64-archive'], archiveWin32Setup('x64'));
function copyInnoUpdater(arch) {
return () => {
return gulp.src('build/win32/{inno_updater.exe,vcruntime140.dll}', { base: 'build/win32' })
.pipe(vfs.dest(path.join(buildPath(arch), 'tools')));
};
}
gulp.task('vscode-win32-ia32-copy-inno-updater', copyInnoUpdater('ia32'));
gulp.task('vscode-win32-x64-copy-inno-updater', copyInnoUpdater('x64'));

View File

@@ -1,118 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
var path = require("path");
var es = require("event-stream");
var pickle = require("chromium-pickle-js");
var Filesystem = require("asar/lib/filesystem");
var VinylFile = require("vinyl");
var minimatch = require("minimatch");
function createAsar(folderPath, unpackGlobs, destFilename) {
var shouldUnpackFile = function (file) {
for (var i = 0; i < unpackGlobs.length; i++) {
if (minimatch(file.relative, unpackGlobs[i])) {
return true;
}
}
return false;
};
var filesystem = new Filesystem(folderPath);
var out = [];
// Keep track of pending inserts
var pendingInserts = 0;
var onFileInserted = function () { pendingInserts--; };
// Do not insert twice the same directory
var seenDir = {};
var insertDirectoryRecursive = function (dir) {
if (seenDir[dir]) {
return;
}
var lastSlash = dir.lastIndexOf('/');
if (lastSlash === -1) {
lastSlash = dir.lastIndexOf('\\');
}
if (lastSlash !== -1) {
insertDirectoryRecursive(dir.substring(0, lastSlash));
}
seenDir[dir] = true;
filesystem.insertDirectory(dir);
};
var insertDirectoryForFile = function (file) {
var lastSlash = file.lastIndexOf('/');
if (lastSlash === -1) {
lastSlash = file.lastIndexOf('\\');
}
if (lastSlash !== -1) {
insertDirectoryRecursive(file.substring(0, lastSlash));
}
};
var insertFile = function (relativePath, stat, shouldUnpack) {
insertDirectoryForFile(relativePath);
pendingInserts++;
filesystem.insertFile(relativePath, shouldUnpack, { stat: stat }, {}, onFileInserted);
};
return es.through(function (file) {
if (file.stat.isDirectory()) {
return;
}
if (!file.stat.isFile()) {
throw new Error("unknown item in stream!");
}
var shouldUnpack = shouldUnpackFile(file);
insertFile(file.relative, { size: file.contents.length, mode: file.stat.mode }, shouldUnpack);
if (shouldUnpack) {
// The file goes outside of xx.asar, in a folder xx.asar.unpacked
var relative = path.relative(folderPath, file.path);
this.queue(new VinylFile({
cwd: folderPath,
base: folderPath,
path: path.join(destFilename + '.unpacked', relative),
stat: file.stat,
contents: file.contents
}));
}
else {
// The file goes inside of xx.asar
out.push(file.contents);
}
}, function () {
var _this = this;
var finish = function () {
{
var headerPickle = pickle.createEmpty();
headerPickle.writeString(JSON.stringify(filesystem.header));
var headerBuf = headerPickle.toBuffer();
var sizePickle = pickle.createEmpty();
sizePickle.writeUInt32(headerBuf.length);
var sizeBuf = sizePickle.toBuffer();
out.unshift(headerBuf);
out.unshift(sizeBuf);
}
var contents = Buffer.concat(out);
out.length = 0;
_this.queue(new VinylFile({
cwd: folderPath,
base: folderPath,
path: destFilename,
contents: contents
}));
_this.queue(null);
};
// Call finish() only when all file inserts have finished...
if (pendingInserts === 0) {
finish();
}
else {
onFileInserted = function () {
pendingInserts--;
if (pendingInserts === 0) {
finish();
}
};
}
});
}
exports.createAsar = createAsar;

View File

@@ -1,131 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as path from 'path';
import * as es from 'event-stream';
import * as pickle from 'chromium-pickle-js';
import * as Filesystem from 'asar/lib/filesystem';
import * as VinylFile from 'vinyl';
import * as minimatch from 'minimatch';
export function createAsar(folderPath: string, unpackGlobs: string[], destFilename: string): NodeJS.ReadWriteStream {
const shouldUnpackFile = (file: VinylFile): boolean => {
for (let i = 0; i < unpackGlobs.length; i++) {
if (minimatch(file.relative, unpackGlobs[i])) {
return true;
}
}
return false;
};
const filesystem = new Filesystem(folderPath);
const out: Buffer[] = [];
// Keep track of pending inserts
let pendingInserts = 0;
let onFileInserted = () => { pendingInserts--; };
// Do not insert twice the same directory
const seenDir: { [key: string]: boolean; } = {};
const insertDirectoryRecursive = (dir: string) => {
if (seenDir[dir]) {
return;
}
let lastSlash = dir.lastIndexOf('/');
if (lastSlash === -1) {
lastSlash = dir.lastIndexOf('\\');
}
if (lastSlash !== -1) {
insertDirectoryRecursive(dir.substring(0, lastSlash));
}
seenDir[dir] = true;
filesystem.insertDirectory(dir);
};
const insertDirectoryForFile = (file: string) => {
let lastSlash = file.lastIndexOf('/');
if (lastSlash === -1) {
lastSlash = file.lastIndexOf('\\');
}
if (lastSlash !== -1) {
insertDirectoryRecursive(file.substring(0, lastSlash));
}
};
const insertFile = (relativePath: string, stat: { size: number; mode: number; }, shouldUnpack: boolean) => {
insertDirectoryForFile(relativePath);
pendingInserts++;
filesystem.insertFile(relativePath, shouldUnpack, { stat: stat }, {}, onFileInserted);
};
return es.through(function (file) {
if (file.stat.isDirectory()) {
return;
}
if (!file.stat.isFile()) {
throw new Error(`unknown item in stream!`);
}
const shouldUnpack = shouldUnpackFile(file);
insertFile(file.relative, { size: file.contents.length, mode: file.stat.mode }, shouldUnpack);
if (shouldUnpack) {
// The file goes outside of xx.asar, in a folder xx.asar.unpacked
const relative = path.relative(folderPath, file.path);
this.queue(new VinylFile({
cwd: folderPath,
base: folderPath,
path: path.join(destFilename + '.unpacked', relative),
stat: file.stat,
contents: file.contents
}));
} else {
// The file goes inside of xx.asar
out.push(file.contents);
}
}, function () {
let finish = () => {
{
const headerPickle = pickle.createEmpty();
headerPickle.writeString(JSON.stringify(filesystem.header));
const headerBuf = headerPickle.toBuffer();
const sizePickle = pickle.createEmpty();
sizePickle.writeUInt32(headerBuf.length);
const sizeBuf = sizePickle.toBuffer();
out.unshift(headerBuf);
out.unshift(sizeBuf);
}
const contents = Buffer.concat(out);
out.length = 0;
this.queue(new VinylFile({
cwd: folderPath,
base: folderPath,
path: destFilename,
contents: contents
}));
this.queue(null);
};
// Call finish() only when all file inserts have finished...
if (pendingInserts === 0) {
finish();
} else {
onFileInserted = () => {
pendingInserts--;
if (pendingInserts === 0) {
finish();
}
};
}
});
}

View File

@@ -1,122 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
const fs = require('fs');
const path = require('path');
const os = require('os');
const mkdirp = require('mkdirp');
const rimraf = require('rimraf');
const es = require('event-stream');
const rename = require('gulp-rename');
const vfs = require('vinyl-fs');
const ext = require('./extensions');
const util = require('gulp-util');
const root = path.dirname(path.dirname(__dirname));
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const builtInExtensions = require('../builtInExtensions.json');
const controlFilePath = path.join(os.homedir(), '.vscode-oss-dev', 'extensions', 'control.json');
function getExtensionPath(extension) {
return path.join(root, '.build', 'builtInExtensions', extension.name);
}
function isUpToDate(extension) {
const packagePath = path.join(getExtensionPath(extension), 'package.json');
if (!fs.existsSync(packagePath)) {
return false;
}
const packageContents = fs.readFileSync(packagePath, { encoding: 'utf8' });
try {
const diskVersion = JSON.parse(packageContents).version;
return (diskVersion === extension.version);
} catch (err) {
return false;
}
}
function syncMarketplaceExtension(extension) {
if (isUpToDate(extension)) {
util.log(util.colors.blue('[marketplace]'), `${extension.name}@${extension.version}`, util.colors.green('✔︎'));
return es.readArray([]);
}
rimraf.sync(getExtensionPath(extension));
return ext.fromMarketplace(extension.name, extension.version)
.pipe(rename(p => p.dirname = `${extension.name}/${p.dirname}`))
.pipe(vfs.dest('.build/builtInExtensions'))
.on('end', () => util.log(util.colors.blue('[marketplace]'), extension.name, util.colors.green('✔︎')));
}
function syncExtension(extension, controlState) {
switch (controlState) {
case 'disabled':
util.log(util.colors.blue('[disabled]'), util.colors.gray(extension.name));
return es.readArray([]);
case 'marketplace':
return syncMarketplaceExtension(extension);
default:
if (!fs.existsSync(controlState)) {
util.log(util.colors.red(`Error: Built-in extension '${extension.name}' is configured to run from '${controlState}' but that path does not exist.`));
return es.readArray([]);
} else if (!fs.existsSync(path.join(controlState, 'package.json'))) {
util.log(util.colors.red(`Error: Built-in extension '${extension.name}' is configured to run from '${controlState}' but there is no 'package.json' file in that directory.`));
return es.readArray([]);
}
util.log(util.colors.blue('[local]'), `${extension.name}: ${util.colors.cyan(controlState)}`, util.colors.green('✔︎'));
return es.readArray([]);
}
}
function readControlFile() {
try {
return JSON.parse(fs.readFileSync(controlFilePath, 'utf8'));
} catch (err) {
return {};
}
}
function writeControlFile(control) {
mkdirp.sync(path.dirname(controlFilePath));
fs.writeFileSync(controlFilePath, JSON.stringify(control, null, 2));
}
function main() {
util.log('Syncronizing built-in extensions...');
util.log(`You can manage built-in extensions with the ${util.colors.cyan('--builtin')} flag`);
const control = readControlFile();
const streams = [];
for (const extension of builtInExtensions) {
let controlState = control[extension.name] || 'marketplace';
control[extension.name] = controlState;
streams.push(syncExtension(extension, controlState));
}
writeControlFile(control);
es.merge(streams)
.on('error', err => {
console.error(err);
process.exit(1);
})
.on('end', () => {
process.exit(0);
});
}
main();

View File

@@ -217,7 +217,6 @@ function removeDuplicateTSBoilerplate(destFiles) {
{ start: /^var __metadata/, end: /^};$/ },
{ start: /^var __param/, end: /^};$/ },
{ start: /^var __awaiter/, end: /^};$/ },
{ start: /^var __generator/, end: /^};$/ },
];
destFiles.forEach(function (destFile) {
var SEEN_BOILERPLATE = [];

View File

@@ -44,11 +44,11 @@ interface ILoaderPluginReqFunc {
export interface IEntryPoint {
name: string;
include?: string[];
exclude?: string[];
include: string[];
exclude: string[];
prepend: string[];
append?: string[];
dest?: string;
append: string[];
dest: string;
}
interface IEntryPointMap {
@@ -339,7 +339,6 @@ function removeDuplicateTSBoilerplate(destFiles: IConcatFile[]): IConcatFile[] {
{ start: /^var __metadata/, end: /^};$/ },
{ start: /^var __param/, end: /^};$/ },
{ start: /^var __awaiter/, end: /^};$/ },
{ start: /^var __generator/, end: /^};$/ },
];
destFiles.forEach((destFile) => {

View File

@@ -22,9 +22,6 @@ var rootDir = path.join(__dirname, '../../src');
var options = require('../../src/tsconfig.json').compilerOptions;
options.verbose = false;
options.sourceMap = true;
if (process.env['VSCODE_NO_SOURCEMAP']) {
options.sourceMap = false;
}
options.rootDir = rootDir;
options.sourceRoot = util.toFileUri(rootDir);
function createCompile(build, emitError) {
@@ -61,13 +58,9 @@ function compileTask(out, build) {
return function () {
var compile = createCompile(build, true);
var src = es.merge(gulp.src('src/**', { base: 'src' }), gulp.src('node_modules/typescript/lib/lib.d.ts'));
// Do not write .d.ts files to disk, as they are not needed there.
var dtsFilter = util.filter(function (data) { return !/\.d\.ts$/.test(data.path); });
return src
.pipe(compile())
.pipe(dtsFilter)
.pipe(gulp.dest(out))
.pipe(dtsFilter.restore)
.pipe(monacodtsTask(out, false));
};
}
@@ -77,19 +70,54 @@ function watchTask(out, build) {
var compile = createCompile(build);
var src = es.merge(gulp.src('src/**', { base: 'src' }), gulp.src('node_modules/typescript/lib/lib.d.ts'));
var watchSrc = watch('src/**', { base: 'src' });
// Do not write .d.ts files to disk, as they are not needed there.
var dtsFilter = util.filter(function (data) { return !/\.d\.ts$/.test(data.path); });
return watchSrc
.pipe(util.incremental(compile, src, true))
.pipe(dtsFilter)
.pipe(gulp.dest(out))
.pipe(dtsFilter.restore)
.pipe(monacodtsTask(out, true));
};
}
exports.watchTask = watchTask;
function reloadTypeScriptNodeModule() {
var util = require('gulp-util');
function log(message) {
var rest = [];
for (var _i = 1; _i < arguments.length; _i++) {
rest[_i - 1] = arguments[_i];
}
util.log.apply(util, [util.colors.cyan('[memory watch dog]'), message].concat(rest));
}
function heapUsed() {
return (process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2) + ' MB';
}
return es.through(function (data) {
this.emit('data', data);
}, function () {
log('memory usage after compilation finished: ' + heapUsed());
// It appears we are running into some variant of
// https://bugs.chromium.org/p/v8/issues/detail?id=2073
//
// Even though all references are dropped, some
// optimized methods in the TS compiler end up holding references
// to the entire TypeScript language host (>600MB)
//
// The idea is to force v8 to drop references to these
// optimized methods, by "reloading" the typescript node module
log('Reloading typescript node module...');
var resolvedName = require.resolve('typescript');
var originalModule = require.cache[resolvedName];
delete require.cache[resolvedName];
var newExports = require('typescript');
require.cache[resolvedName] = originalModule;
for (var prop in newExports) {
if (newExports.hasOwnProperty(prop)) {
originalModule.exports[prop] = newExports[prop];
}
}
log('typescript node module reloaded.');
this.emit('end');
});
}
function monacodtsTask(out, isWatch) {
var basePath = path.resolve(process.cwd(), out);
var neededFiles = {};
monacodts.getFilesToWatch(out).forEach(function (filePath) {
filePath = path.normalize(filePath);
@@ -132,7 +160,7 @@ function monacodtsTask(out, isWatch) {
}));
}
resultStream = es.through(function (data) {
var filePath = path.normalize(path.resolve(basePath, data.relative));
var filePath = path.normalize(data.path);
if (neededFiles[filePath]) {
setInputFile(filePath, data.contents.toString());
}

View File

@@ -25,9 +25,6 @@ const rootDir = path.join(__dirname, '../../src');
const options = require('../../src/tsconfig.json').compilerOptions;
options.verbose = false;
options.sourceMap = true;
if (process.env['VSCODE_NO_SOURCEMAP']) { // To be used by developers in a hurry
options.sourceMap = false;
}
options.rootDir = rootDir;
options.sourceRoot = util.toFileUri(rootDir);
@@ -52,6 +49,7 @@ function createCompile(build: boolean, emitError?: boolean): (token?: util.ICanc
.pipe(tsFilter)
.pipe(util.loadSourcemaps())
.pipe(ts(token))
// .pipe(build ? reloadTypeScriptNodeModule() : es.through())
.pipe(noDeclarationsFilter)
.pipe(build ? nls() : es.through())
.pipe(noDeclarationsFilter.restore)
@@ -77,14 +75,9 @@ export function compileTask(out: string, build: boolean): () => NodeJS.ReadWrite
gulp.src('node_modules/typescript/lib/lib.d.ts'),
);
// Do not write .d.ts files to disk, as they are not needed there.
const dtsFilter = util.filter(data => !/\.d\.ts$/.test(data.path));
return src
.pipe(compile())
.pipe(dtsFilter)
.pipe(gulp.dest(out))
.pipe(dtsFilter.restore)
.pipe(monacodtsTask(out, false));
};
}
@@ -100,21 +93,61 @@ export function watchTask(out: string, build: boolean): () => NodeJS.ReadWriteSt
);
const watchSrc = watch('src/**', { base: 'src' });
// Do not write .d.ts files to disk, as they are not needed there.
const dtsFilter = util.filter(data => !/\.d\.ts$/.test(data.path));
return watchSrc
.pipe(util.incremental(compile, src, true))
.pipe(dtsFilter)
.pipe(gulp.dest(out))
.pipe(dtsFilter.restore)
.pipe(monacodtsTask(out, true));
};
}
function monacodtsTask(out: string, isWatch: boolean): NodeJS.ReadWriteStream {
function reloadTypeScriptNodeModule(): NodeJS.ReadWriteStream {
var util = require('gulp-util');
function log(message: any, ...rest: any[]): void {
util.log(util.colors.cyan('[memory watch dog]'), message, ...rest);
}
const basePath = path.resolve(process.cwd(), out);
function heapUsed(): string {
return (process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2) + ' MB';
}
return es.through(function (data) {
this.emit('data', data);
}, function () {
log('memory usage after compilation finished: ' + heapUsed());
// It appears we are running into some variant of
// https://bugs.chromium.org/p/v8/issues/detail?id=2073
//
// Even though all references are dropped, some
// optimized methods in the TS compiler end up holding references
// to the entire TypeScript language host (>600MB)
//
// The idea is to force v8 to drop references to these
// optimized methods, by "reloading" the typescript node module
log('Reloading typescript node module...');
var resolvedName = require.resolve('typescript');
var originalModule = require.cache[resolvedName];
delete require.cache[resolvedName];
var newExports = require('typescript');
require.cache[resolvedName] = originalModule;
for (var prop in newExports) {
if (newExports.hasOwnProperty(prop)) {
originalModule.exports[prop] = newExports[prop];
}
}
log('typescript node module reloaded.');
this.emit('end');
});
}
function monacodtsTask(out: string, isWatch: boolean): NodeJS.ReadWriteStream {
const neededFiles: { [file: string]: boolean; } = {};
monacodts.getFilesToWatch(out).forEach(function (filePath) {
@@ -163,7 +196,7 @@ function monacodtsTask(out: string, isWatch: boolean): NodeJS.ReadWriteStream {
}
resultStream = es.through(function (data) {
const filePath = path.normalize(path.resolve(basePath, data.relative));
const filePath = path.normalize(data.path);
if (neededFiles[filePath]) {
setInputFile(filePath, data.contents.toString());
}

File diff suppressed because it is too large Load Diff

View File

@@ -46,6 +46,10 @@
"name": "vs/workbench/parts/execution",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/parts/explorers",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/parts/extensions",
"project": "vscode-workbench"
@@ -67,11 +71,7 @@
"project": "vscode-workbench"
},
{
"name": "vs/workbench/parts/localizations",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/parts/logs",
"name": "vs/workbench/parts/nps",
"project": "vscode-workbench"
},
{
@@ -138,10 +138,6 @@
"name": "vs/workbench/parts/welcome",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/actions",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/configuration",
"project": "vscode-workbench"
@@ -150,10 +146,6 @@
"name": "vs/workbench/services/crashReporter",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/dialogs",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/editor",
"project": "vscode-workbench"
@@ -162,10 +154,6 @@
"name": "vs/workbench/services/extensions",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/jsonschemas",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/files",
"project": "vscode-workbench"
@@ -174,6 +162,10 @@
"name": "vs/workbench/services/keybinding",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/message",
"project": "vscode-workbench"
},
{
"name": "vs/workbench/services/mode",
"project": "vscode-workbench"
@@ -201,6 +193,10 @@
{
"name": "vs/workbench/services/decorations",
"project": "vscode-workbench"
},
{
"name": "setup_messages",
"project": "vscode-workbench"
}
]
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -79,7 +79,7 @@ function isImportNode(node) {
function fileFrom(file, contents, path) {
if (path === void 0) { path = file.path; }
return new File({
contents: Buffer.from(contents),
contents: new Buffer(contents),
base: file.base,
cwd: file.cwd,
path: path

View File

@@ -131,7 +131,7 @@ module nls {
export function fileFrom(file: File, contents: string, path: string = file.path) {
return new File({
contents: Buffer.from(contents),
contents: new Buffer(contents),
base: file.base,
cwd: file.cwd,
path: path

View File

@@ -59,7 +59,7 @@ function loader(bundledFileHeader, bundleLoader) {
this.emit('data', new VinylFile({
path: 'fake',
base: '',
contents: Buffer.from(bundledFileHeader)
contents: new Buffer(bundledFileHeader)
}));
this.emit('data', data);
}
@@ -98,7 +98,7 @@ function toConcatStream(bundledFileHeader, sources, dest) {
return new VinylFile({
path: source.path ? root + '/' + source.path.replace(/\\/g, '/') : 'fake',
base: base,
contents: Buffer.from(source.contents)
contents: new Buffer(source.contents)
});
});
return es.readArray(treatedSources)
@@ -141,7 +141,7 @@ function optimizeTask(opts) {
bundleInfoArray.push(new VinylFile({
path: 'bundleInfo.json',
base: '.',
contents: Buffer.from(JSON.stringify(result.bundleData, null, '\t'))
contents: new Buffer(JSON.stringify(result.bundleData, null, '\t'))
}));
}
es.readArray(bundleInfoArray).pipe(bundleInfoStream);
@@ -174,6 +174,7 @@ function optimizeTask(opts) {
};
}
exports.optimizeTask = optimizeTask;
;
/**
* Wrap around uglify and allow the preserveComments function
* to have a file "context" to include our copyright only once per file.
@@ -236,3 +237,4 @@ function minifyTask(src, sourceMapBaseUrl) {
};
}
exports.minifyTask = minifyTask;
;

View File

@@ -31,7 +31,7 @@ function log(prefix: string, message: string): void {
}
// {{SQL CARBON EDIT}}
export function loaderConfig(emptyPaths?: string[]) {
export function loaderConfig(emptyPaths: string[]) {
const result = {
paths: {
'vs': 'out-build/vs',
@@ -73,7 +73,7 @@ function loader(bundledFileHeader: string, bundleLoader: boolean): NodeJS.ReadWr
this.emit('data', new VinylFile({
path: 'fake',
base: '',
contents: Buffer.from(bundledFileHeader)
contents: new Buffer(bundledFileHeader)
}));
this.emit('data', data);
} else {
@@ -117,7 +117,7 @@ function toConcatStream(bundledFileHeader: string, sources: bundle.IFile[], dest
return new VinylFile({
path: source.path ? root + '/' + source.path.replace(/\\/g, '/') : 'fake',
base: base,
contents: Buffer.from(source.contents)
contents: new Buffer(source.contents)
});
});
@@ -165,7 +165,7 @@ export interface IOptimizeTaskOpts {
/**
* (languages to process)
*/
languages: i18n.Language[];
languages: string[];
}
export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStream {
const entryPoints = opts.entryPoints;
@@ -201,7 +201,7 @@ export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStr
bundleInfoArray.push(new VinylFile({
path: 'bundleInfo.json',
base: '.',
contents: Buffer.from(JSON.stringify(result.bundleData, null, '\t'))
contents: new Buffer(JSON.stringify(result.bundleData, null, '\t'))
}));
}
es.readArray(bundleInfoArray).pipe(bundleInfoStream);
@@ -241,7 +241,7 @@ export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStr
}))
.pipe(gulp.dest(out));
};
}
};
declare class FileWithCopyright extends VinylFile {
public __hasOurCopyright: boolean;
@@ -295,7 +295,7 @@ function uglifyWithCopyrights(): NodeJS.ReadWriteStream {
return es.duplex(input, output);
}
export function minifyTask(src: string, sourceMapBaseUrl?: string): (cb: any) => void {
export function minifyTask(src: string, sourceMapBaseUrl: string): (cb: any) => void {
const sourceMappingURL = sourceMapBaseUrl && (f => `${sourceMapBaseUrl}/${f.relative}.map`);
return cb => {
@@ -326,4 +326,4 @@ export function minifyTask(src: string, sourceMapBaseUrl?: string): (cb: any) =>
cb(err);
});
};
}
};

View File

@@ -1,14 +1,7 @@
declare module "event-stream" {
import { Stream } from 'stream';
import { ThroughStream as _ThroughStream} from 'through';
import { ThroughStream } from 'through';
import { MapStream } from 'map-stream';
import * as File from 'vinyl';
export interface ThroughStream extends _ThroughStream {
queue(data: File | null);
push(data: File | null);
paused: boolean;
}
function merge(streams: Stream[]): ThroughStream;
function merge(...streams: Stream[]): ThroughStream;

View File

@@ -143,7 +143,7 @@ function loadSourcemaps() {
cb(null, f);
return;
}
f.contents = Buffer.from(contents.replace(/\/\/# sourceMappingURL=(.*)$/g, ''), 'utf8');
f.contents = new Buffer(contents.replace(/\/\/# sourceMappingURL=(.*)$/g, ''), 'utf8');
fs.readFile(path.join(path.dirname(f.path), lastMatch[1]), 'utf8', function (err, contents) {
if (err) {
return cb(err);
@@ -160,7 +160,7 @@ function stripSourceMappingURL() {
var output = input
.pipe(es.mapSync(function (f) {
var contents = f.contents.toString('utf8');
f.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, ''), 'utf8');
f.contents = new Buffer(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, ''), 'utf8');
return f;
}));
return es.duplex(input, output);
@@ -173,6 +173,7 @@ function rimraf(dir) {
if (!err) {
return cb();
}
;
if (err.code === 'ENOTEMPTY' && ++retries < 5) {
return setTimeout(function () { return retry(cb); }, 10);
}

View File

@@ -28,7 +28,7 @@ export interface IStreamProvider {
(cancellationToken?: ICancellationToken): NodeJS.ReadWriteStream;
}
export function incremental(streamProvider: IStreamProvider, initial: NodeJS.ReadWriteStream, supportsCancellation?: boolean): NodeJS.ReadWriteStream {
export function incremental(streamProvider: IStreamProvider, initial: NodeJS.ReadWriteStream, supportsCancellation: boolean): NodeJS.ReadWriteStream {
const input = es.through();
const output = es.through();
let state = 'idle';
@@ -129,7 +129,7 @@ export function skipDirectories(): NodeJS.ReadWriteStream {
});
}
export function cleanNodeModule(name: string, excludes: string[], includes?: string[]): NodeJS.ReadWriteStream {
export function cleanNodeModule(name: string, excludes: string[], includes: string[]): NodeJS.ReadWriteStream {
const toGlob = (path: string) => '**/node_modules/' + name + (path ? '/' + path : '');
const negate = (str: string) => '!' + str;
@@ -190,7 +190,7 @@ export function loadSourcemaps(): NodeJS.ReadWriteStream {
return;
}
f.contents = Buffer.from(contents.replace(/\/\/# sourceMappingURL=(.*)$/g, ''), 'utf8');
f.contents = new Buffer(contents.replace(/\/\/# sourceMappingURL=(.*)$/g, ''), 'utf8');
fs.readFile(path.join(path.dirname(f.path), lastMatch[1]), 'utf8', (err, contents) => {
if (err) { return cb(err); }
@@ -209,7 +209,7 @@ export function stripSourceMappingURL(): NodeJS.ReadWriteStream {
const output = input
.pipe(es.mapSync<VinylFile, VinylFile>(f => {
const contents = (<Buffer>f.contents).toString('utf8');
f.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, ''), 'utf8');
f.contents = new Buffer(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, ''), 'utf8');
return f;
}));
@@ -223,7 +223,7 @@ export function rimraf(dir: string): (cb: any) => void {
_rimraf(dir, { maxBusyTries: 1 }, (err: any) => {
if (!err) {
return cb();
}
};
if (err.code === 'ENOTEMPTY' && ++retries < 5) {
return setTimeout(() => retry(cb), 10);

View File

@@ -9,7 +9,7 @@ const es = require('event-stream');
function handleDeletions() {
return es.mapSync(f => {
if (/\.ts$/.test(f.relative) && !f.contents) {
f.contents = Buffer.from('');
f.contents = new Buffer('');
f.stat = { mtime: new Date() };
}

View File

@@ -30,12 +30,12 @@ function watch(root) {
path: path,
base: root
});
//@ts-ignore
file.event = type;
result.emit('data', file);
}
nsfw(root, function (events) {
nsfw(root, function(events) {
for (var i = 0; i < events.length; i++) {
var e = events[i];
var changeType = e.action;
@@ -47,16 +47,16 @@ function watch(root) {
handleEvent(path.join(e.directory, e.file), toChangeType(changeType));
}
}
}).then(function (watcher) {
}).then(function(watcher) {
watcher.start();
});
});
return result;
return result;
}
var cache = Object.create(null);
module.exports = function (pattern, options) {
module.exports = function(pattern, options) {
options = options || {};
var cwd = path.normalize(options.cwd || process.cwd());
@@ -66,7 +66,7 @@ module.exports = function (pattern, options) {
watcher = cache[cwd] = watch(cwd);
}
var rebase = !options.base ? es.through() : es.mapSync(function (f) {
var rebase = !options.base ? es.through() : es.mapSync(function(f) {
f.base = options.base;
return f;
});
@@ -74,13 +74,13 @@ module.exports = function (pattern, options) {
return watcher
.pipe(filter(['**', '!.git{,/**}'])) // ignore all things git
.pipe(filter(pattern))
.pipe(es.map(function (file, cb) {
fs.stat(file.path, function (err, stat) {
.pipe(es.map(function(file, cb) {
fs.stat(file.path, function(err, stat) {
if (err && err.code === 'ENOENT') { return cb(null, file); }
if (err) { return cb(); }
if (!stat.isFile()) { return cb(); }
fs.readFile(file.path, function (err, contents) {
fs.readFile(file.path, function(err, contents) {
if (err && err.code === 'ENOENT') { return cb(null, file); }
if (err) { return cb(); }

View File

@@ -24,8 +24,7 @@ function watch(root) {
var result = es.through();
var child = cp.spawn(watcherPath, [root]);
child.stdout.on('data', function (data) {
// @ts-ignore
child.stdout.on('data', function(data) {
var lines = data.toString('utf8').split('\n');
for (var i = 0; i < lines.length; i++) {
var line = lines[i].trim();
@@ -47,17 +46,17 @@ function watch(root) {
path: changePathFull,
base: root
});
//@ts-ignore
file.event = toChangeType(changeType);
result.emit('data', file);
}
});
child.stderr.on('data', function (data) {
child.stderr.on('data', function(data) {
result.emit('error', data);
});
child.on('exit', function (code) {
child.on('exit', function(code) {
result.emit('error', 'Watcher died with code ' + code);
child = null;
});
@@ -71,7 +70,7 @@ function watch(root) {
var cache = Object.create(null);
module.exports = function (pattern, options) {
module.exports = function(pattern, options) {
options = options || {};
var cwd = path.normalize(options.cwd || process.cwd());

View File

@@ -1,21 +1 @@
The Source EULA
Copyright (c) 2016 Microsoft Corporation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
See project root directory

View File

@@ -32,7 +32,7 @@ END OF winjs NOTICES AND INFORMATION
%% string_scorer version 0.1.20 (https://github.com/joshaven/string_score)
=========================================
This software is released under the Source EULA:
This software is released under the MIT license:
Copyright (c) Joshaven Potter
@@ -60,7 +60,7 @@ END OF string_scorer NOTICES AND INFORMATION
%% chjj-marked NOTICES AND INFORMATION BEGIN HERE
=========================================
The Source EULA
The MIT License (MIT)
Copyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/)

View File

@@ -62,24 +62,19 @@ export interface ICommandHandler {
#include(vs/editor/standalone/browser/colorizer): IColorizerOptions, IColorizerElementOptions
#include(vs/base/common/scrollable): ScrollbarVisibility
#include(vs/platform/theme/common/themeService): ThemeColor
#includeAll(vs/editor/common/model;LanguageIdentifier=>languages.LanguageIdentifier): IScrollEvent
#includeAll(vs/editor/common/editorCommon;editorOptions.=>): IScrollEvent
#includeAll(vs/editor/common/editorCommon;IMode=>languages.IMode;LanguageIdentifier=>languages.LanguageIdentifier;editorOptions.=>): ISelection, IScrollEvent
#includeAll(vs/editor/common/model/textModelEvents):
#includeAll(vs/editor/common/controller/cursorEvents):
#includeAll(vs/editor/common/config/editorOptions):
#includeAll(vs/editor/browser/editorBrowser;editorCommon.=>;editorOptions.=>):
#include(vs/editor/common/config/fontInfo): FontInfo, BareFontInfo
//compatibility:
export type IReadOnlyModel = ITextModel;
export type IModel = ITextModel;
}
declare module monaco.languages {
#includeAll(vs/editor/standalone/browser/standaloneLanguages;modes.=>;editorCommon.=>editor.;model.=>editor.;IMarkerData=>editor.IMarkerData):
#includeAll(vs/editor/standalone/browser/standaloneLanguages;modes.=>;editorCommon.=>editor.;IMarkerData=>editor.IMarkerData):
#includeAll(vs/editor/common/modes/languageConfiguration):
#includeAll(vs/editor/common/modes;editorCommon.IRange=>IRange;editorCommon.IPosition=>IPosition;editorCommon.=>editor.;IMarkerData=>editor.IMarkerData;model.=>editor.):
#includeAll(vs/editor/common/modes;editorCommon.IRange=>IRange;editorCommon.IPosition=>IPosition;editorCommon.=>editor.;IMarkerData=>editor.IMarkerData):
#include(vs/editor/common/services/modeService): ILanguageExtensionPoint
#includeAll(vs/editor/standalone/common/monarch/monarchTypes):

View File

@@ -21,21 +21,21 @@ function yarnInstall(location, opts) {
}
// {{SQL CARBON EDIT}}
yarnInstall('dataprotocol-client');
yarnInstall('extensions-modules');
yarnInstall('extensions'); // node modules shared by all extensions
const extensions = [
'vscode-colorize-tests',
'json',
'mssql',
'mssql',
'configuration-editing',
'extension-editing',
'markdown',
'markdown-basics',
'git',
'merge-conflict',
'insights-default',
'account-provider-azure',
'agent'
'account-provider-azure'
];
extensions.forEach(extension => yarnInstall(`extensions/${extension}`));
@@ -43,7 +43,6 @@ extensions.forEach(extension => yarnInstall(`extensions/${extension}`));
function yarnInstallBuildDependencies() {
// make sure we install the deps of build/lib/watch for the system installed
// node, since that is the driver of gulp
//@ts-ignore
const env = Object.assign({}, process.env);
const watchPath = path.join(path.dirname(__dirname), 'lib', 'watch');
const yarnrcPath = path.join(watchPath, '.yarnrc');
@@ -61,5 +60,4 @@ runtime "${runtime}"`;
}
yarnInstall(`build`); // node modules required for build
yarnInstall('test/smoke'); // node modules required for smoketest
yarnInstallBuildDependencies(); // node modules for watching, specific to host node version, not electron

View File

@@ -4,11 +4,9 @@
*--------------------------------------------------------------------------------------------*/
const cp = require('child_process');
const fs = require('fs');
const path = require('path');
const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
function updateGrammar(location) {
const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
const result = cp.spawnSync(npm, ['run', 'update-grammar'], {
cwd: location,
stdio: 'inherit'
@@ -19,17 +17,50 @@ function updateGrammar(location) {
}
}
const allExtensionFolders = fs.readdirSync('extensions');
const extensions = allExtensionFolders.filter(e => {
try {
let packageJSON = JSON.parse(fs.readFileSync(path.join('extensions', e, 'package.json')).toString());
return packageJSON && packageJSON.scripts && packageJSON.scripts['update-grammar'];
} catch (e) {
return false;
}
});
console.log(`Updating ${extensions.length} grammars...`);
const extensions = [
'bat',
'clojure',
'coffeescript',
'cpp',
'csharp',
'css',
'diff',
'docker',
'fsharp',
'gitsyntax',
'go',
'groovy',
'handlebars',
'hlsl',
'html',
'ini',
'java',
// 'javascript', updated through JavaScript
'json',
'less',
'lua',
'make',
'markdown',
'objective-c',
'perl',
'php',
// 'powershell', grammar not ready yet, @daviwil will ping when ready
'pug',
'python',
'r',
'razor',
'ruby',
'rust',
'scss',
'shaderlab',
'shellscript',
'sql',
'swift',
'typescript',
'vb',
'xml',
'yaml'
];
extensions.forEach(extension => updateGrammar(`extensions/${extension}`));
@@ -39,5 +70,4 @@ if (process.platform === 'win32') {
cp.spawn('.\scripts\test-integration.bat', [], { env: process.env, stdio: 'inherit' });
} else {
cp.spawn('/bin/bash', ['./scripts/test-integration.sh'], { env: process.env, stdio: 'inherit' });
}
}

View File

@@ -14,19 +14,14 @@ var url = require('url');
function getOptions(urlString) {
var _url = url.parse(urlString);
var headers = {
'User-Agent': 'VSCode'
};
var token = process.env['GITHUB_TOKEN'];
if (token) {
headers['Authorization'] = 'token ' + token
}
return {
protocol: _url.protocol,
host: _url.host,
port: _url.port,
path: _url.path,
headers: headers
headers: {
'User-Agent': 'NodeJS'
}
};
}
@@ -37,16 +32,12 @@ function download(url, redirectCount) {
response.on('data', function (data) {
content += data.toString();
}).on('end', function () {
if (response.statusCode === 403 && response.headers['x-ratelimit-remaining'] === '0') {
e('GitHub API rate exceeded. Set GITHUB_TOKEN environment variable to increase rate limit.');
return;
}
let count = redirectCount || 0;
if (count < 5 && response.statusCode >= 300 && response.statusCode <= 303 || response.statusCode === 307) {
let location = response.headers['location'];
if (location) {
console.log("Redirected " + url + " to " + location);
download(location, count + 1).then(c, e);
download(location, count+1).then(c, e);
return;
}
}
@@ -68,13 +59,17 @@ function getCommitSha(repoId, repoPath) {
commitDate: lastCommit.commit.author.date
});
} catch (e) {
return Promise.reject(new Error("Failed extracting the SHA: " + content));
console.error("Failed extracting the SHA: " + content);
return Promise.resolve(null);
}
}, function () {
console.error('Failed loading ' + commitInfo);
return Promise.resolve(null);
});
}
exports.update = function (repoId, repoPath, dest, modifyGrammar, version = 'master') {
var contentPath = 'https://raw.githubusercontent.com/' + repoId + `/${version}/` + repoPath;
exports.update = function (repoId, repoPath, dest, modifyGrammar) {
var contentPath = 'https://raw.githubusercontent.com/' + repoId + '/master/' + repoPath;
console.log('Reading from ' + contentPath);
return download(contentPath).then(function (content) {
var ext = path.extname(repoPath);
@@ -86,7 +81,8 @@ exports.update = function (repoId, repoPath, dest, modifyGrammar, version = 'mas
} else if (ext === '.json') {
grammar = JSON.parse(content);
} else {
return Promise.reject(new Error('Unknown file extension: ' + ext));
console.error('Unknown file extension: ' + ext);
return;
}
if (modifyGrammar) {
modifyGrammar(grammar);
@@ -103,10 +99,8 @@ exports.update = function (repoId, repoPath, dest, modifyGrammar, version = 'mas
if (info) {
result.version = 'https://github.com/' + repoId + '/commit/' + info.commitSha;
}
let keys = ['name', 'scopeName', 'comment', 'injections', 'patterns', 'repository'];
for (let key of keys) {
if (grammar.hasOwnProperty(key)) {
for (let key in grammar) {
if (!result.hasOwnProperty(key)) {
result[key] = grammar[key];
}
}
@@ -119,14 +113,11 @@ exports.update = function (repoId, repoPath, dest, modifyGrammar, version = 'mas
console.log('Updated ' + path.basename(dest));
}
} catch (e) {
return Promise.reject(e);
console.error(e);
}
});
}, console.error).catch(e => {
console.error(e);
process.exit(1);
});
}, console.error);
};
if (path.basename(process.argv[1]) === 'update-grammar.js') {

View File

@@ -1,69 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
let i18n = require("../lib/i18n");
let fs = require("fs");
let path = require("path");
let vfs = require("vinyl-fs");
let rimraf = require('rimraf');
function update(idOrPath) {
if (!idOrPath) {
throw new Error('Argument must be the location of the localization extension.');
}
let locExtFolder = idOrPath;
if (/^\w{2}(-\w+)?$/.test(idOrPath)) {
locExtFolder = '../vscode-language-pack-' + idOrPath;
}
let locExtStat = fs.statSync(locExtFolder);
if (!locExtStat || !locExtStat.isDirectory) {
throw new Error('No directory found at ' + idOrPath);
}
let packageJSON = JSON.parse(fs.readFileSync(path.join(locExtFolder, 'package.json')).toString());
let contributes = packageJSON['contributes'];
if (!contributes) {
throw new Error('The extension must define a "localizations" contribution in the "package.json"');
}
let localizations = contributes['localizations'];
if (!localizations) {
throw new Error('The extension must define a "localizations" contribution of type array in the "package.json"');
}
localizations.forEach(function (localization) {
if (!localization.languageId || !localization.languageName || !localization.localizedLanguageName) {
throw new Error('Each localization contribution must define "languageId", "languageName" and "localizedLanguageName" properties.');
}
let server = localization.server || 'www.transifex.com';
let userName = localization.userName || 'api';
let apiToken = process.env.TRANSIFEX_API_TOKEN;
let languageId = localization.transifexId || localization.languageId;
let translationDataFolder = path.join(locExtFolder, 'translations');
if (fs.existsSync(translationDataFolder) && fs.existsSync(path.join(translationDataFolder, 'main.i18n.json'))) {
console.log('Clearing \'' + translationDataFolder + '\'...');
rimraf.sync(translationDataFolder);
}
console.log('Downloading translations for \'' + languageId + '\' to \'' + translationDataFolder + '\'...');
const translationPaths = [];
i18n.pullI18nPackFiles(server, userName, apiToken, { id: languageId }, translationPaths)
.pipe(vfs.dest(translationDataFolder)).on('end', function () {
localization.translations = [];
for (let tp of translationPaths) {
localization.translations.push({ id: tp.id, path: `./translations/${tp.resourceName}`});
}
fs.writeFileSync(path.join(locExtFolder, 'package.json'), JSON.stringify(packageJSON, null, '\t'));
});
});
}
if (path.basename(process.argv[1]) === 'update-localization-extension.js') {
update(process.argv[2]);
}

View File

@@ -12,18 +12,17 @@
"azure-storage": "^2.1.0",
"decompress": "^4.2.0",
"documentdb": "1.13.0",
"service-downloader": "github:anthonydresser/service-downloader#0.1.2",
"extensions-modules": "file:../extensions-modules",
"fs-extra-promise": "^1.0.1",
"mime": "^1.3.4",
"minimist": "^1.2.0",
"typescript": "2.6.1",
"vscode": "^1.0.1",
"vscode": "^1.0.1",
"xml2js": "^0.4.17"
},
"scripts": {
"compile": "tsc -p tsconfig.build.json",
"watch": "tsc -p tsconfig.build.json --watch",
"postinstall": "npm run compile",
"npmCheckJs": "tsc --noEmit"
"compile": "tsc",
"watch": "tsc --watch",
"postinstall": "npm run compile"
}
}

View File

@@ -4,9 +4,9 @@ set -e
# setup nvm
if [[ "$OSTYPE" == "darwin"* ]]; then
export NVM_DIR=~/.nvm
source $(brew --prefix nvm)/nvm.sh --no-use
source $(brew --prefix nvm)/nvm.sh
else
source $NVM_DIR/nvm.sh --no-use
source $NVM_DIR/nvm.sh
fi
# install node

View File

@@ -70,7 +70,6 @@ interface Asset {
hash: string;
sha256hash: string;
size: number;
supportsFastUpdate?: boolean;
}
function createOrUpdate(commit: string, quality: string, platform: string, type: string, release: NewDocument, asset: Asset, isUpdate: boolean): Promise<void> {
@@ -204,30 +203,17 @@ async function publish(commit: string, quality: string, platform: string, type:
// mooncake is fussy and far away, this is needed!
mooncakeBlobService.defaultClientRequestTimeoutInMs = 10 * 60 * 1000;
await Promise.all([
assertContainer(blobService, quality),
assertContainer(mooncakeBlobService, quality)
]);
await assertContainer(mooncakeBlobService, quality);
const [blobExists, moooncakeBlobExists] = await Promise.all([
doesAssetExist(blobService, quality, blobName),
doesAssetExist(mooncakeBlobService, quality, blobName)
]);
const mooncakeBlobExists = await doesAssetExist(mooncakeBlobService, quality, blobName);
const promises = [];
if (!blobExists) {
promises.push(uploadBlob(blobService, quality, blobName, file));
}
if (!moooncakeBlobExists) {
if (!mooncakeBlobExists) {
promises.push(uploadBlob(mooncakeBlobService, quality, blobName, file));
}
} else {
console.log('Skipping Mooncake publishing.');
}
if (promises.length === 0) {
console.log(`Blob ${quality}, ${blobName} already exists, not publishing again.`);
return;
@@ -254,13 +240,6 @@ async function publish(commit: string, quality: string, platform: string, type:
size
};
// Remove this if we ever need to rollback fast updates for windows
if (/win32/.test(platform)) {
asset.supportsFastUpdate = true;
}
console.log('Asset:', JSON.stringify(asset, null, ' '));
const release = {
id: commit,
timestamp: (new Date()).getTime(),

View File

@@ -19,9 +19,6 @@ step "Install dependencies" \
step "Hygiene" \
npm run gulp -- hygiene
step "Monaco Editor Check" \
./node_modules/.bin/tsc -p ./src/tsconfig.monaco.json --noEmit
step "Mix in repository from vscode-distro" \
npm run gulp -- mixin

View File

@@ -22,9 +22,6 @@ step "Install dependencies" \
step "Hygiene" \
npm run gulp -- hygiene
step "Monaco Editor Check" \
./node_modules/.bin/tsc -p ./src/tsconfig.monaco.json --noEmit
step "Mix in repository from vscode-distro" \
npm run gulp -- mixin

View File

@@ -24,10 +24,6 @@ step "Hygiene" {
exec { & npm run gulp -- hygiene }
}
step "Monaco Editor Check" {
exec { & .\node_modules\.bin\tsc -p .\src\tsconfig.monaco.json --noEmit }
}
$env:VSCODE_MIXIN_PASSWORD = $mixinPassword
step "Mix in repository from vscode-distro" {
exec { & npm run gulp -- mixin }
@@ -45,10 +41,6 @@ step "Build minified" {
exec { & npm run gulp -- "vscode-win32-$global:arch-min" }
}
step "Copy Inno updater" {
exec { & npm run gulp -- "vscode-win32-$global:arch-copy-inno-updater" }
}
# step "Create loader snapshot" {
# exec { & node build\lib\snapshotLoader.js --arch=$global:arch }
# }

View File

@@ -1,7 +1,7 @@
# install node
$env:Path = $env:NVM_HOME + ";" + $env:NVM_SYMLINK + ";" + $env:Path
$NodeVersion = "8.9.1"
# nvm install $NodeVersion
# nvm use $NodeVersion
# npm install -g yarn
nvm install $NodeVersion
nvm use $NodeVersion
npm install -g yarn
$env:Path = $env:NVM_HOME + "\v" + $NodeVersion + ";" + $env:Path

View File

@@ -1,7 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"allowJs": false,
"checkJs": false
}
}

View File

@@ -7,12 +7,7 @@
"preserveConstEnums": true,
"sourceMap": false,
"experimentalDecorators": true,
"newLine": "LF",
// enable JavaScript type checking for the language service
// use the tsconfig.build.json for compiling wich disable JavaScript
// type checking so that JavaScript file are not transpiled
"allowJs": true,
"checkJs": true
"newLine": "LF"
},
"exclude": [
"node_modules/**"

View File

@@ -9,6 +9,5 @@
"always"
],
"triple-equals": true
},
"defaultSeverity": "warning"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,7 @@ OutputDir={#OutputDir}
OutputBaseFilename=SqlOpsStudioSetup
Compression=lzma
SolidCompression=yes
AppMutex={code:GetAppMutex}
AppMutex={#AppMutex}
SetupMutex={#AppMutex}setup
WizardImageFile={#RepoDir}\resources\win32\inno-big.bmp
WizardSmallImageFile={#RepoDir}\resources\win32\inno-small.bmp
@@ -52,13 +52,8 @@ Type: filesandordirs; Name: "{app}\resources\app\out"; Check: IsNotUpdate
Type: filesandordirs; Name: "{app}\resources\app\plugins"; Check: IsNotUpdate
Type: filesandordirs; Name: "{app}\resources\app\extensions"; Check: IsNotUpdate
Type: filesandordirs; Name: "{app}\resources\app\node_modules"; Check: IsNotUpdate
Type: filesandordirs; Name: "{app}\resources\app\node_modules.asar.unpacked"; Check: IsNotUpdate
Type: files; Name: "{app}\resources\app\node_modules.asar"; Check: IsNotUpdate
Type: files; Name: "{app}\resources\app\Credits_45.0.2454.85.html"; Check: IsNotUpdate
[UninstallDelete]
Type: filesandordirs; Name: "{app}\_"
[Tasks]
Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1
Name: "addtopath"; Description: "{cm:AddToPath}"; GroupDescription: "{cm:Other}"
@@ -143,48 +138,6 @@ begin
Result := True;
end;
function GetAppMutex(Value: string): string;
begin
if IsBackgroundUpdate() then
Result := ''
else
Result := '{#AppMutex}';
end;
function GetDestDir(Value: string): string;
begin
if IsBackgroundUpdate() then
Result := ExpandConstant('{app}\_')
else
Result := ExpandConstant('{app}');
end;
function BoolToStr(Value: Boolean): String;
begin
if Value then
Result := 'true'
else
Result := 'false';
end;
procedure CurStepChanged(CurStep: TSetupStep);
var
UpdateResultCode: Integer;
begin
if IsBackgroundUpdate() and (CurStep = ssPostInstall) then
begin
CreateMutex('{#AppMutex}-ready');
while (CheckForMutexes('{#AppMutex}')) do
begin
Log('Application is still running, waiting');
Sleep(1000);
end;
Exec(ExpandConstant('{app}\tools\inno_updater.exe'), ExpandConstant('"{app}\{#ExeBasename}.exe" ' + BoolToStr(LockFileExists())), '', SW_SHOW, ewWaitUntilTerminated, UpdateResultCode);
end;
end;
// http://stackoverflow.com/a/23838239/261019
procedure Explode(var Dest: TArrayOfString; Text: String; Separator: String);
var

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

3
dataprotocol-client/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
lib
node_modules
npm-debug.log

View File

@@ -0,0 +1,3 @@
src
.gitignore
tsfmt.json

View File

@@ -0,0 +1,25 @@
{
"name": "dataprotocol-client",
"version": "1.0.0",
"description": "SQL Operations Studio studio implementation of vscode-language-client",
"main": "lib/main.js",
"typings": "./lib/main",
"scripts": {
"prepare": "node ./node_modules/vscode/bin/install && tsc -p ./src",
"compile": "tsc -p ./src",
"watch": "tsc -w -p ./src",
"update-vscode": "node ./node_modules/vscode/bin/install"
},
"author": "Microsoft",
"license": "ISC",
"dependencies": {
"typescript": "2.6.2",
"vscode-languageclient": "3.5.0"
},
"devDependencies": {
"vscode": "1.1.5"
},
"engines": {
"vscode": "^1.15"
}
}

View File

@@ -0,0 +1,68 @@
import * as data from 'data';
import * as proto from './protocol';
import * as types from './types';
export interface Ic2p {
asConnectionParams(connectionUri: string, connectionInfo: data.ConnectionInfo): proto.ConnectParams;
asExecutionPlanOptions(planOptions: data.ExecutionPlanOptions): types.ExecutionPlanOptions;
asScriptingParams(connectionUri: string, operation: data.ScriptOperation, metadata: data.ObjectMetadata, paramDetails: data.ScriptingParamDetails): types.ScriptingParams;
}
function asConnectionParams(ownerUri: string, connInfo: data.ConnectionInfo): proto.ConnectParams {
return {
ownerUri,
connection: {
options: connInfo.options
}
};
}
function asExecutionPlanOptions(planOptions: data.ExecutionPlanOptions): types.ExecutionPlanOptions {
return {
includeEstimatedExecutionPlanXml: planOptions ? planOptions.displayEstimatedQueryPlan : undefined,
includeActualExecutionPlanXml: planOptions ? planOptions.displayActualQueryPlan : undefined
};
}
function asScriptingParams(ownerURI: string, operation: data.ScriptOperation, metadata: data.ObjectMetadata, paramDetails: data.ScriptingParamDetails): types.ScriptingParams {
let scriptingObject: types.ScriptingObject = {
type: metadata.metadataTypeName,
schema: metadata.schema,
name: metadata.name
};
let targetDatabaseEngineEdition = paramDetails.targetDatabaseEngineEdition;
let targetDatabaseEngineType = paramDetails.targetDatabaseEngineType;
let scriptCompatibilityOption = paramDetails.scriptCompatibilityOption;
let scriptOptions: types.ScriptOptions = {
scriptCreateDrop: (operation === types.ScriptOperation.Delete) ? 'ScriptDrop' :
(operation === types.ScriptOperation.Select) ? 'ScriptSelect' : 'ScriptCreate',
typeOfDataToScript: 'SchemaOnly',
scriptStatistics: 'ScriptStatsNone',
targetDatabaseEngineEdition: targetDatabaseEngineEdition ? targetDatabaseEngineEdition : 'SqlServerEnterpriseEdition',
targetDatabaseEngineType: targetDatabaseEngineType ? targetDatabaseEngineType : 'SingleInstance',
scriptCompatibilityOption: scriptCompatibilityOption ? scriptCompatibilityOption : 'Script140Compat'
};
return {
connectionString: null,
filePath: paramDetails.filePath,
scriptingObjects: [scriptingObject],
scriptDestination: 'ToEditor',
includeObjectCriteria: null,
excludeObjectCriteria: null,
includeSchemas: null,
excludeSchemas: null,
includeTypes: null,
excludeTypes: null,
scriptOptions,
connectionDetails: null,
selectScript: null,
ownerURI,
operation
};
}
export const c2p: Ic2p = {
asConnectionParams,
asExecutionPlanOptions,
asScriptingParams
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,633 @@
import { ClientCapabilities as VSClientCapabilities, RequestType, NotificationType } from 'vscode-languageclient';
import * as types from './types';
import * as data from 'data';
export interface ConnectionClientCapabilities {
connection?: {
/**
* Whether the connection support dynamic registration
*/
dynamicRegistration?: boolean;
};
backup?: {
/**
* Whether the backup support dynamic registration
*/
dynamicRegistration?: boolean;
};
restore?: {
/**
* Whether the restore support dynamic registration
*/
dynamicRegistration?: boolean;
};
query?: {
/**
* Whether the query support dynamic registration
*/
dynamicRegistration?: boolean;
};
objectExplorer?: {
/**
* Whether the object explorer support dynamic registration
*/
dynamicRegistration?: boolean;
};
scripting?: {
/**
* Whether the scripting support dynamic registration
*/
dynamicRegistration?: boolean;
};
taskServices?: {
/**
* Whether the task services support dynamic registration
*/
dynamicRegistration?: boolean;
};
fileBrowser?: {
/**
* Whether the file browser support dynamic registration
*/
dynamicRegistration?: boolean;
};
profiler?: {
/**
* Whether the profiler support dynamic registration
*/
dynamicRegistration?: boolean;
};
capabilities?: {
/**
*
*/
dynamicRegistration?: boolean;
};
metadata?: {
/**
*
*/
dynamicRegistration?: boolean;
};
adminServices?: {
/**
*
*/
dynamicRegistration?: boolean;
};
}
export interface ClientCapabilities extends VSClientCapabilities {
connection?: ConnectionClientCapabilities;
}
//---- Refresh IntelliSense ----------------------------------------
/**
* Notification sent when the an IntelliSense cache invalidation is requested
*/
export namespace RebuildIntelliSenseNotification {
export const type = new NotificationType<RebuildIntelliSenseParams, void>('textDocument/rebuildIntelliSense');
}
/**
* Rebuild IntelliSense notification parameters
*/
export class RebuildIntelliSenseParams {
/**
* URI identifying the text document
*/
public ownerUri: string;
}
// ------------------------------- < Connect Request > ----------------------------------------------
/**
* Connection request message format
*/
export interface ConnectParams {
/**
* URI identifying the owner of the connection
*/
ownerUri: string;
/**
* Details for creating the connection
*/
connection: types.ConnectionDetails;
}
// Connection request message callback declaration
export namespace ConnectionRequest {
export const type = new RequestType<ConnectParams, boolean, void, void>('connection/connect');
}
// ------------------------------- < Connection Complete Event > ------------------------------------
export namespace ConnectionCompleteNotification {
export const type = new NotificationType<types.ConnectionCompleteParams, void>('connection/complete');
}
// ------------------------------- < Connection Changed Event > -------------------------------------
/**
* Parameters for the ConnectionChanged notification.
*/
export class ConnectionChangedParams {
/**
* Owner URI of the connection that changed.
*/
public ownerUri: string;
/**
* Summary of details containing any connection changes.
*/
public connection: types.ConnectionSummary;
}
/**
* Connection changed event callback declaration.
*/
export namespace ConnectionChangedNotification {
export const type = new NotificationType<ConnectionChangedParams, void>('connection/connectionchanged');
}
// ------------------------------- < Disconnect Request > -------------------------------------------
// Disconnect request message format
export class DisconnectParams {
// URI identifying the owner of the connection
public ownerUri: string;
}
// Disconnect response format
export type DisconnectResult = boolean;
// Disconnect request message callback declaration
export namespace DisconnectRequest {
export const type = new RequestType<DisconnectParams, DisconnectResult, void, void>('connection/disconnect');
}
// ------------------------------- < Cancel Connect Request > ---------------------------------------
// Cancel connect request message format
export class CancelConnectParams {
/**
* URI identifying the owner of the connection
*/
public ownerUri: string;
}
// Cancel connect response format.
export type CancelConnectResult = boolean;
// Cancel connect request message callback declaration
export namespace CancelConnectRequest {
export const type = new RequestType<CancelConnectParams, CancelConnectResult, void, void>('connection/cancelconnect');
}
// ------------------------------- < Change Database Request > -------------------------------------
export class ChangeDatabaseParams {
public ownerUri: string;
public newDatabase: string;
}
export namespace ChangeDatabaseRequest {
export const type = new RequestType<ChangeDatabaseParams, boolean, void, void>('connection/changedatabase');
}
// ------------------------------- < List Databases Request > ---------------------------------------
// List databases request format
export class ListDatabasesParams {
// Connection information to use for querying master
public ownerUri: string;
}
// List databases request callback declaration
export namespace ListDatabasesRequest {
export const type = new RequestType<ListDatabasesParams, data.ListDatabasesResult, void, void>('connection/listdatabases');
}
// Language Flavor Changed ================================================================================
/**
* Parameters to provide when sending a language flavor changed notification
*/
export interface DidChangeLanguageFlavorParams {
uri: string;
language: string;
flavor: string;
}
// ------------------------------- < Language Flavor Changed Notification > ---------------------------------------
export namespace LanguageFlavorChangedNotification {
export const type = new NotificationType<DidChangeLanguageFlavorParams, void>('connection/languageflavorchanged');
}
// ------------------------------- < Table Metadata Request > ---------------------------------------
// Table metadata request format
export class TableMetadataParams {
// Connection information to use for querying master
public ownerUri: string;
public schema: string;
public objectName: string;
}
// Table metadata response format
export class TableMetadataResult {
public columns: data.ColumnMetadata[];
}
// Table metadata request callback declaration
export namespace TableMetadataRequest {
export const type = new RequestType<TableMetadataParams, TableMetadataResult, void, void>('metadata/table');
}
// ------------------------------- < View Metadata Request > ---------------------------------------
// Table metadata request callback declaration
export namespace ViewMetadataRequest {
export const type = new RequestType<TableMetadataParams, TableMetadataResult, void, void>('metadata/view');
}
/**
* Event sent when the language service is finished updating after a connection
*/
export namespace IntelliSenseReadyNotification {
export const type = new NotificationType<types.IntelliSenseReadyParams, void>('textDocument/intelliSenseReady');
}
// ------------------------------- < Capabilties Discovery Event > ------------------------------------
export class CapabiltiesDiscoveryParams {
public hostName: string;
public hostVersion: string;
}
export namespace CapabiltiesDiscoveryRequest {
export const type = new RequestType<CapabiltiesDiscoveryParams, types.CapabiltiesDiscoveryResult, void, void>('capabilities/list');
}
// Query Execution ================================================================================
// ------------------------------- < Query Cancellation Request > ------------------------------------
export namespace QueryCancelRequest {
export const type = new RequestType<QueryCancelParams, data.QueryCancelResult, void, void>('query/cancel');
}
export interface QueryCancelParams {
ownerUri: string;
}
// ------------------------------- < Query Dispose Request > ------------------------------------
export namespace QueryDisposeRequest {
export const type = new RequestType<QueryDisposeParams, QueryDisposeResult, void, void>('query/dispose');
}
/**
* Parameters to provide when disposing of a query
*/
export interface QueryDisposeParams {
ownerUri: string;
}
/**
* Result received upon successful disposal of a query
*/
export interface QueryDisposeResult {
}
// ------------------------------- < Query Execution Complete Notification > ------------------------------------
export namespace QueryExecuteCompleteNotification {
export const type = new NotificationType<data.QueryExecuteCompleteNotificationResult, void>('query/complete');
}
// ------------------------------- < Query Batch Start Notification > ------------------------------------
export namespace QueryExecuteBatchStartNotification {
export const type = new NotificationType<data.QueryExecuteBatchNotificationParams, void>('query/batchStart');
}
// ------------------------------- < Query Batch Complete Notification > ------------------------------------
export namespace QueryExecuteBatchCompleteNotification {
export const type = new NotificationType<data.QueryExecuteBatchNotificationParams, void>('query/batchComplete');
}
// ------------------------------- < Query ResultSet Complete Notification > ------------------------------------
export namespace QueryExecuteResultSetCompleteNotification {
export const type = new NotificationType<data.QueryExecuteResultSetCompleteNotificationParams, void>('query/resultSetComplete');
}
// ------------------------------- < Query Message Notification > ------------------------------------
export namespace QueryExecuteMessageNotification {
export const type = new NotificationType<data.QueryExecuteMessageParams, void>('query/message');
}
// ------------------------------- < Query Execution Request > ------------------------------------
export namespace QueryExecuteRequest {
export const type = new RequestType<types.QueryExecuteParams, QueryExecuteResult, void, void>('query/executeDocumentSelection');
}
export interface QueryExecuteResult { }
// ------------------------------- < Query Results Request > ------------------------------------
export namespace QueryExecuteSubsetRequest {
export const type = new RequestType<data.QueryExecuteSubsetParams, data.QueryExecuteSubsetResult, void, void>('query/subset');
}
export interface ResultSetSubset {
rowCount: number;
rows: data.DbCellValue[][];
}
// ------------------------------- < Execute Statement > ------------------------------------
export interface QueryExecuteStatementParams {
ownerUri: string;
line: number;
column: number;
}
export namespace QueryExecuteStatementRequest {
export const type = new RequestType<QueryExecuteStatementParams, QueryExecuteResult, void, void>('query/executedocumentstatement');
}
// --------------------------------- < Save Results as CSV Request > ------------------------------------------
// save results in csv format
export namespace SaveResultsAsCsvRequest {
export const type = new RequestType<data.SaveResultsRequestParams, data.SaveResultRequestResult, void, void>('query/saveCsv');
}
// --------------------------------- </ Save Results as CSV Request > ------------------------------------------
// --------------------------------- < Save Results as JSON Request > ------------------------------------------
// save results in json format
export namespace SaveResultsAsJsonRequest {
export const type = new RequestType<data.SaveResultsRequestParams, data.SaveResultRequestResult, void, void>('query/saveJson');
}
// --------------------------------- </ Save Results as JSON Request > ------------------------------------------
// --------------------------------- < Save Results as Excel Request > ------------------------------------------
// save results in Excel format
export namespace SaveResultsAsExcelRequest {
export const type = new RequestType<data.SaveResultsRequestParams, data.SaveResultRequestResult, void, void>('query/saveExcel');
}
// --------------------------------- </ Save Results as Excel Request > ------------------------------------------
// ------------------------------- < Execute and Return > -----------------------------------
export namespace SimpleExecuteRequest {
export const type = new RequestType<data.SimpleExecuteParams, data.SimpleExecuteResult, void, void>('query/simpleexecute');
}
// ------------------------------- < Execute String > ------------------------------------
export interface QueryExecuteStringParams {
query: string;
ownerUri: string;
}
export namespace QueryExecuteStringRequest {
export const type = new RequestType<QueryExecuteStringParams, QueryExecuteResult, void, void>('query/executeString');
}
// ------------------------------- < Metadata Events > ------------------------------------
export namespace MetadataQueryRequest {
export const type = new RequestType<types.MetadataQueryParams, types.MetadataQueryResult, void, void>('metadata/list');
}
// ------------------------------- < Scripting Events > ------------------------------------
export namespace ScriptingRequest {
export const type = new RequestType<types.ScriptingParams, data.ScriptingResult, void, void>('scripting/script');
}
// ------------------------------- < Scripting Complete Event > ------------------------------------
export namespace ScriptingCompleteNotification {
export const type = new NotificationType<types.ScriptingCompleteParams, void>('scripting/scriptComplete');
}
// Edit Data ======================================================================================
// Shared Interfaces --------------------------------------------------------------------------
export interface EditSessionOperationParams {
ownerUri: string;
}
export interface EditRowOperationParams extends EditSessionOperationParams {
rowId: number;
}
export interface EditCellResult {
cell: data.EditCell;
isRowDirty: boolean;
}
// edit/commit --------------------------------------------------------------------------------
export namespace EditCommitRequest {
export const type = new RequestType<data.EditCommitParams, EditCommitResult, void, void>('edit/commit');
}
export interface EditCommitResult { }
// edit/createRow -----------------------------------------------------------------------------
export namespace EditCreateRowRequest {
export const type = new RequestType<data.EditCreateRowParams, data.EditCreateRowResult, void, void>('edit/createRow');
}
// edit/deleteRow -----------------------------------------------------------------------------
export namespace EditDeleteRowRequest {
export const type = new RequestType<data.EditDeleteRowParams, EditDeleteRowResult, void, void>('edit/deleteRow');
}
export interface EditDeleteRowResult { }
// edit/dispose -------------------------------------------------------------------------------
export namespace EditDisposeRequest {
export const type = new RequestType<data.EditDisposeParams, EditDisposeResult, void, void>('edit/dispose');
}
export interface EditDisposeResult { }
// edit/initialize ----------------------------------------------------------------------------
export namespace EditInitializeRequest {
export const type = new RequestType<data.EditInitializeParams, EditInitializeResult, void, void>('edit/initialize');
}
export interface EditInitializeResult { }
// edit/revertCell --------------------------------------------------------------------------------
export namespace EditRevertCellRequest {
export const type = new RequestType<data.EditRevertCellParams, data.EditRevertCellResult, void, void>('edit/revertCell');
}
// edit/revertRow -----------------------------------------------------------------------------
export namespace EditRevertRowRequest {
export const type = new RequestType<data.EditRevertRowParams, EditRevertRowResult, void, void>('edit/revertRow');
}
export interface EditRevertRowResult { }
// edit/sessionReady Event --------------------------------------------------------------------
export namespace EditSessionReadyNotification {
export const type = new NotificationType<data.EditSessionReadyParams, void>('edit/sessionReady');
}
// edit/updateCell ----------------------------------------------------------------------------
export namespace EditUpdateCellRequest {
export const type = new RequestType<data.EditUpdateCellParams, data.EditUpdateCellResult, void, void>('edit/updateCell');
}
// edit/subset ------------------------------------------------------------------------------------
export namespace EditSubsetRequest {
export const type = new RequestType<data.EditSubsetParams, data.EditSubsetResult, void, void>('edit/subset');
}
// ------------------------------- < Object Explorer Events > ------------------------------------
export namespace ObjectExplorerCreateSessionRequest {
export const type = new RequestType<types.ConnectionDetails, types.CreateSessionResponse, void, void>('objectexplorer/createsession');
}
export namespace ObjectExplorerExpandRequest {
export const type = new RequestType<types.ExpandParams, boolean, void, void>('objectexplorer/expand');
}
export namespace ObjectExplorerRefreshRequest {
export const type = new RequestType<types.ExpandParams, boolean, void, void>('objectexplorer/refresh');
}
export namespace ObjectExplorerCloseSessionRequest {
export const type = new RequestType<types.CloseSessionParams, types.CloseSessionResponse, void, void>('objectexplorer/closesession');
}
// ------------------------------- < Object Explorer Events > ------------------------------------
export namespace ObjectExplorerCreateSessionCompleteNotification {
export const type = new NotificationType<types.SessionCreatedParameters, void>('objectexplorer/sessioncreated');
}
export namespace ObjectExplorerExpandCompleteNotification {
export const type = new NotificationType<types.ExpandResponse, void>('objectexplorer/expandCompleted');
}
// ------------------------------- < Task Service Events > ------------------------------------
export namespace ListTasksRequest {
export const type = new RequestType<data.ListTasksParams, data.ListTasksResponse, void, void>('tasks/listtasks');
}
export namespace CancelTaskRequest {
export const type = new RequestType<data.CancelTaskParams, boolean, void, void>('tasks/canceltask');
}
// ------------------------------- < Task Service Events > ------------------------------------
export namespace TaskStatusChangedNotification {
export const type = new NotificationType<data.TaskProgressInfo, void>('tasks/statuschanged');
}
export namespace TaskCreatedNotification {
export const type = new NotificationType<data.TaskInfo, void>('tasks/newtaskcreated');
}
// ------------------------------- < Admin Service Events > ------------------------------------
export namespace CreateDatabaseRequest {
export const type = new RequestType<types.CreateDatabaseParams, data.CreateDatabaseResponse, void, void>('admin/createdatabase');
}
export namespace DefaultDatabaseInfoRequest {
export const type = new RequestType<types.DefaultDatabaseInfoParams, types.DefaultDatabaseInfoResponse, void, void>('admin/defaultdatabaseinfo');
}
export namespace CreateLoginRequest {
export const type = new RequestType<types.CreateLoginParams, data.CreateLoginResponse, void, void>('admin/createlogin');
}
export namespace GetDatabaseInfoRequest {
export const type = new RequestType<types.GetDatabaseInfoParams, types.GetDatabaseInfoResponse, void, void>('admin/getdatabaseinfo');
}
// ------------------------------- < Disaster Recovery Events > ------------------------------------
export namespace BackupRequest {
export const type = new RequestType<types.BackupParams, data.BackupResponse, void, void>('backup/backup');
}
export namespace BackupConfigInfoRequest {
export const type = new RequestType<types.DefaultDatabaseInfoParams, types.BackupConfigInfoResponse, void, void>('backup/backupconfiginfo');
}
export namespace RestoreRequest {
export const type = new RequestType<types.RestoreParams, data.RestoreResponse, void, void>('restore/restore');
}
export namespace RestorePlanRequest {
export const type = new RequestType<types.RestoreParams, data.RestorePlanResponse, void, void>('restore/restoreplan');
}
export namespace CancelRestorePlanRequest {
export const type = new RequestType<types.RestoreParams, boolean, void, void>('restore/cancelrestoreplan');
}
export namespace RestoreConfigInfoRequest {
export const type = new RequestType<types.RestoreConfigInfoRequestParams, types.RestoreConfigInfoResponse, void, void>('restore/restoreconfiginfo');
}
// ------------------------------- < File Browser Events > ------------------------------------
export namespace FileBrowserOpenRequest {
export const type = new RequestType<types.FileBrowserOpenParams, boolean, void, void>('filebrowser/open');
}
export namespace FileBrowserOpenedNotification {
export const type = new NotificationType<data.FileBrowserOpenedParams, void>('filebrowser/opencomplete');
}
export namespace FileBrowserExpandRequest {
export const type = new RequestType<types.FileBrowserExpandParams, boolean, void, void>('filebrowser/expand');
}
export namespace FileBrowserExpandedNotification {
export const type = new NotificationType<data.FileBrowserExpandedParams, void>('filebrowser/expandcomplete');
}
export namespace FileBrowserValidateRequest {
export const type = new RequestType<types.FileBrowserValidateParams, boolean, void, void>('filebrowser/validate');
}
export namespace FileBrowserValidatedNotification {
export const type = new NotificationType<data.FileBrowserValidatedParams, void>('filebrowser/validatecomplete');
}
export namespace FileBrowserCloseRequest {
export const type = new RequestType<types.FileBrowserCloseParams, data.FileBrowserCloseResponse, void, void>('filebrowser/close');
}
// ------------------------------- < Profiler Events > ------------------------------------
export namespace StartProfilingRequest {
export const type = new RequestType<types.StartProfilingParams, types.StartProfilingResponse, void, void>('profiler/start');
}
export namespace StopProfilingRequest {
export const type = new RequestType<types.StopProfilingParams, types.StopProfilingResponse, void, void>('profiler/stop');
}
export namespace ProfilerEventsAvailableNotification {
export const type = new NotificationType<types.ProfilerEventsAvailableParams, void>('profiler/eventsavailable');
}

View File

@@ -0,0 +1,198 @@
import * as data from 'data';
import * as types from './types';
export interface Ip2c {
asProviderMetadata(params: types.MetadataQueryResult): data.ProviderMetadata;
asServerCapabilities(result: types.CapabiltiesDiscoveryResult): data.DataProtocolServerCapabilities;
}
function asProviderMetadata(params: types.MetadataQueryResult): data.ProviderMetadata {
let objectMetadata: data.ObjectMetadata[] = [];
if (!params.metadata || !params.metadata.length) {
return {
objectMetadata
};
}
for (let i = 0; i < params.metadata.length; ++i) {
let metadata: data.ObjectMetadata = params.metadata[i];
let metadataTypeName: string;
if (metadata.metadataTypeName) {
// Read from the provider since it's defined
metadataTypeName = metadata.metadataTypeName;
} else if (metadata.metadataType === types.MetadataType.View) {
metadataTypeName = 'View';
} else if (metadata.metadataType === types.MetadataType.SProc) {
metadataTypeName = 'StoredProcedure';
} else if (metadata.metadataType === types.MetadataType.Function) {
metadataTypeName = 'Function';
} else {
metadataTypeName = 'Table';
}
objectMetadata.push({
metadataTypeName,
metadataType: metadata.metadataType,
name: metadata.name,
schema: metadata.schema,
urn: metadata.urn
});
}
return <data.ProviderMetadata>{
objectMetadata
};
}
function asServiceOptionType(val: string): data.ServiceOptionType {
if (val === 'string') {
return data.ServiceOptionType.string;
} else if (val === 'multistring') {
return data.ServiceOptionType.multistring;
} else if (val === 'password') {
return data.ServiceOptionType.password;
} else if (val === 'number') {
return data.ServiceOptionType.number;
} else if (val === 'boolean') {
return data.ServiceOptionType.boolean;
} else if (val === 'category') {
return data.ServiceOptionType.category;
} else if (val === 'object') {
return data.ServiceOptionType.object;
}
// assume string for unknown value types
return data.ServiceOptionType.string;
}
function buildServiceOption(srcOption: types.ServiceOption): data.ServiceOption {
return {
name: srcOption.name,
displayName: srcOption.displayName ? srcOption.displayName : srcOption.name,
description: srcOption.description,
groupName: srcOption.groupName,
defaultValue: srcOption.defaultValue,
categoryValues: srcOption.categoryValues,
isRequired: srcOption.isRequired,
isArray: srcOption.isArray,
objectType: srcOption.objectType,
valueType: asServiceOptionType(srcOption.valueType),
};
}
function asServerCapabilities(result: types.CapabiltiesDiscoveryResult): data.DataProtocolServerCapabilities {
let capabilities: data.DataProtocolServerCapabilities = {
protocolVersion: result.capabilities.protocolVersion,
providerName: result.capabilities.providerName,
providerDisplayName: result.capabilities.providerDisplayName,
connectionProvider: undefined,
adminServicesProvider: undefined,
features: []
};
if (result.capabilities.adminServicesProvider) {
capabilities.adminServicesProvider = <data.AdminServicesOptions>{
databaseInfoOptions: new Array<data.ServiceOption>(),
databaseFileInfoOptions: new Array<data.ServiceOption>(),
fileGroupInfoOptions: new Array<data.ServiceOption>()
};
if (result.capabilities.adminServicesProvider.databaseInfoOptions
&& result.capabilities.adminServicesProvider.databaseInfoOptions.length > 0) {
for (let i = 0; i < result.capabilities.adminServicesProvider.databaseInfoOptions.length; ++i) {
let srcOption: any = result.capabilities.adminServicesProvider.databaseInfoOptions[i];
let descOption: data.ServiceOption = buildServiceOption(srcOption);
capabilities.adminServicesProvider.databaseInfoOptions.push(descOption);
}
}
if (result.capabilities.adminServicesProvider.databaseFileInfoOptions
&& result.capabilities.adminServicesProvider.databaseFileInfoOptions.length > 0) {
for (let i = 0; i < result.capabilities.adminServicesProvider.databaseFileInfoOptions.length; ++i) {
//let srcOption: types.ServiceOption = result.capabilities.adminServicesProvider.databaseFileInfoOptions[i];
let srcOption: any = result.capabilities.adminServicesProvider.databaseFileInfoOptions[i];
let descOption: data.ServiceOption = buildServiceOption(srcOption);
capabilities.adminServicesProvider.databaseFileInfoOptions.push(descOption);
}
}
if (result.capabilities.adminServicesProvider.fileGroupInfoOptions
&& result.capabilities.adminServicesProvider.fileGroupInfoOptions.length > 0) {
for (let i = 0; i < result.capabilities.adminServicesProvider.fileGroupInfoOptions.length; ++i) {
//let srcOption: types.ServiceOption = result.capabilities.adminServicesProvider.fileGroupInfoOptions[i];
let srcOption: any = result.capabilities.adminServicesProvider.fileGroupInfoOptions[i];
let descOption: data.ServiceOption = buildServiceOption(srcOption);
capabilities.adminServicesProvider.fileGroupInfoOptions.push(descOption);
}
}
}
if (result.capabilities.connectionProvider
&& result.capabilities.connectionProvider.options
&& result.capabilities.connectionProvider.options.length > 0) {
capabilities.connectionProvider = <data.ConnectionProviderOptions>{
options: new Array<data.ConnectionOption>()
};
for (let i = 0; i < result.capabilities.connectionProvider.options.length; ++i) {
let srcOption: any = result.capabilities.connectionProvider.options[i];
let descOption: data.ConnectionOption = {
name: srcOption.name,
displayName: srcOption.displayName ? srcOption.displayName : srcOption.name,
description: srcOption.description,
groupName: srcOption.groupName,
defaultValue: srcOption.defaultValue,
categoryValues: srcOption.categoryValues,
isIdentity: srcOption.isIdentity,
isRequired: srcOption.isRequired,
valueType: asServiceOptionType(srcOption.valueType),
specialValueType: undefined
};
if (srcOption.specialValueType === 'serverName') {
descOption.specialValueType = data.ConnectionOptionSpecialType.serverName;
} else if (srcOption.specialValueType === 'databaseName') {
descOption.specialValueType = data.ConnectionOptionSpecialType.databaseName;
} else if (srcOption.specialValueType === 'authType') {
descOption.specialValueType = data.ConnectionOptionSpecialType.authType;
} else if (srcOption.specialValueType === 'userName') {
descOption.specialValueType = data.ConnectionOptionSpecialType.userName;
} else if (srcOption.specialValueType === 'password') {
descOption.specialValueType = data.ConnectionOptionSpecialType.password;
} else if (srcOption.specialValueType === 'appName') {
descOption.specialValueType = data.ConnectionOptionSpecialType.appName;
}
capabilities.connectionProvider.options.push(descOption);
}
}
if (result.capabilities.features
&& result.capabilities.features.length > 0) {
result.capabilities.features.forEach(feature => {
let descFeature: data.FeatureMetadataProvider = {
enabled: feature.enabled,
featureName: feature.featureName,
optionsMetadata: []
};
capabilities.features.push(descFeature);
if (feature.optionsMetadata) {
feature.optionsMetadata.forEach(srcOption => {
descFeature.optionsMetadata.push(buildServiceOption(<any>srcOption));
});
}
});
}
return capabilities;
}
export const p2c: Ip2c = {
asProviderMetadata,
asServerCapabilities
};

View File

@@ -0,0 +1,12 @@
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": false,
"inlineSources": false,
"declaration": true,
"stripInternal": true,
"outDir": "../lib"
}
}

View File

@@ -0,0 +1,939 @@
import * as data from 'data';
export interface CreateSessionResponse {
sessionId: string;
}
export interface SessionCreatedParameters {
success: boolean;
sessionId: string;
rootNode: NodeInfo;
errorMessage: string;
}
export interface ExpandResponse {
nodePath: string;
sessionId: string;
nodes: NodeInfo[];
errorMessage: string;
}
export interface NodeInfo {
nodePath: string;
nodeType: string;
nodeSubType: string;
nodeStatus: string;
label: string;
isLeaf: boolean;
metadata: data.ObjectMetadata;
errorMessage: string;
}
export interface ExpandParams {
sessionId: string;
nodePath: string;
}
export interface CloseSessionParams {
sessionId: string;
}
export interface CloseSessionResponse {
success: boolean;
sessionId: string;
}
export interface CategoryValue {
displayName: string;
name: string;
}
export interface ServiceOption {
name: string;
displayName: string;
description: string;
groupName: string;
valueType: string;
defaultValue: string;
objectType: string;
categoryValues: CategoryValue[];
isRequired: boolean;
isArray: boolean;
}
export interface ConnectionOption {
name: string;
displayName: string;
description: string;
groupName: string;
valueType: string;
defaultValue: string;
objectType: string;
categoryValues: CategoryValue[];
specialValueType: string;
isIdentity: boolean;
isRequired: boolean;
isArray: boolean;
}
export interface ConnectionProviderOptions {
options: ConnectionOption[];
}
export interface AdminServicesProviderOptions {
databaseInfoOptions: ServiceOption[];
databaseFileInfoOptions: ServiceOption[];
fileGroupInfoOptions: ServiceOption[];
}
export interface FeatureMetadataProvider {
enabled: boolean;
featureName: string;
optionsMetadata: ServiceOption[];
}
/**
* Parameters to initialize a connection to a database
*/
export interface ConnectionDetails {
/**
* connection options
*/
options: {};
}
/**
* Summary that identifies a unique database connection.
*/
export class ConnectionSummary {
/**
* server name
*/
public serverName: string;
/**
* database name
*/
public databaseName: string;
/**
* user name
*/
public userName: string;
}
/**
* Connection response format.
*/
export class ConnectionCompleteParams {
/**
* URI identifying the owner of the connection
*/
public ownerUri: string;
/**
* connection id returned from service host.
*/
public connectionId: string;
/**
* any diagnostic messages return from the service host.
*/
public messages: string;
/**
* Error message returned from the engine, if any.
*/
public errorMessage: string;
/**
* Error number returned from the engine, if any.
*/
public errorNumber: number;
/**
* Information about the connected server.
*/
public serverInfo: ServerInfo;
/**
* information about the actual connection established
*/
public connectionSummary: ConnectionSummary;
}
/**
* Update event parameters
*/
export class IntelliSenseReadyParams {
/**
* URI identifying the text document
*/
public ownerUri: string;
}
/**
* Information about a SQL Server instance.
*/
export class ServerInfo {
/**
* The major version of the SQL Server instance.
*/
public serverMajorVersion: number;
/**
* The minor version of the SQL Server instance.
*/
public serverMinorVersion: number;
/**
* The build of the SQL Server instance.
*/
public serverReleaseVersion: number;
/**
* The ID of the engine edition of the SQL Server instance.
*/
public engineEditionId: number;
/**
* String containing the full server version text.
*/
public serverVersion: string;
/**
* String describing the product level of the server.
*/
public serverLevel: string;
/**
* The edition of the SQL Server instance.
*/
public serverEdition: string;
/**
* Whether the SQL Server instance is running in the cloud (Azure) or not.
*/
public isCloud: boolean;
/**
* The version of Azure that the SQL Server instance is running on, if applicable.
*/
public azureVersion: number;
/**
* The Operating System version string of the machine running the SQL Server instance.
*/
public osVersion: string;
}
export class CapabiltiesDiscoveryResult {
public capabilities: data.DataProtocolServerCapabilities;
}
// Task Services types
export enum TaskStatus {
notStarted = 0,
inProgress = 1,
succeeded = 2,
succeededWithWarning = 3,
failed = 4,
canceled = 5
}
// Admin Services types
export interface CreateDatabaseParams {
ownerUri: string;
databaseInfo: data.DatabaseInfo;
}
export interface DefaultDatabaseInfoParams {
ownerUri: string;
}
export interface DefaultDatabaseInfoResponse {
defaultDatabaseInfo: data.DatabaseInfo;
}
export interface GetDatabaseInfoResponse {
databaseInfo: data.DatabaseInfo;
}
export interface GetDatabaseInfoParams {
ownerUri: string;
}
export interface BackupConfigInfoResponse {
backupConfigInfo: data.BackupConfigInfo;
}
export interface CreateLoginParams {
ownerUri: string;
loginInfo: data.LoginInfo;
}
// Disaster Recovery types
export interface BackupInfo {
ownerUri: string;
databaseName: string;
backupType: number;
backupComponent: number;
backupDeviceType: number;
selectedFiles: string;
backupsetName: string;
selectedFileGroup: { [path: string]: string };
// List of {key: backup path, value: device type}
backupPathDevices: { [path: string]: number };
backupPathList: [string];
isCopyOnly: boolean;
formatMedia: boolean;
initialize: boolean;
skipTapeHeader: boolean;
mediaName: string;
mediaDescription: string;
checksum: boolean;
continueAfterError: boolean;
logTruncation: boolean;
tailLogBackup: boolean;
retainDays: number;
compressionOption: number;
verifyBackupRequired: boolean;
encryptionAlgorithm: number;
encryptorType: number;
encryptorName: string;
}
export interface BackupParams {
ownerUri: string;
backupInfo: BackupInfo;
taskExecutionMode: data.TaskExecutionMode;
}
export interface RestoreParams {
ownerUri: string;
options: {};
taskExecutionMode: data.TaskExecutionMode;
}
export interface RestoreConfigInfoRequestParams {
ownerUri: string;
}
export interface RestoreConfigInfoResponse {
configInfo: { [key: string]: any };
}
export interface RestoreDatabaseFileInfo {
fileType: string;
logicalFileName: string;
originalFileName: string;
restoreAsFileName: string;
}
export interface FileBrowserOpenParams {
ownerUri: string;
expandPath: string;
fileFilters: string[];
changeFilter: boolean;
}
export interface FileTreeNode {
children: FileTreeNode[];
isExpanded: boolean;
isFile: boolean;
name: string;
fullPath: string;
}
export interface FileTree {
rootNode: FileTreeNode;
selectedNode: FileTreeNode;
}
export interface FileBrowserExpandParams {
ownerUri: string;
expandPath: string;
}
export interface FileBrowserValidateParams {
ownerUri: string;
serviceType: string;
selectedFiles: string[];
}
export interface FileBrowserCloseParams {
ownerUri: string;
}
export interface DatabaseFileInfo {
properties: LocalizedPropertyInfo[];
id: string;
isSelected: boolean;
}
export interface LocalizedPropertyInfo {
propertyName: string;
propertyValue: string;
propertyDisplayName: string;
propertyValueDisplayName: string;
}
export interface RestorePlanDetailInfo {
name: string;
currentValue: any;
isReadOnly: boolean;
isVisible: boolean;
defaultValue: any;
}
// Query Execution types
export interface ResultSetSummary {
id: number;
batchId: number;
rowCount: number;
columnInfo: IDbColumn[];
}
export interface BatchSummary {
hasError: boolean;
id: number;
selection: data.ISelectionData;
resultSetSummaries: ResultSetSummary[];
executionElapsed: string;
executionEnd: string;
executionStart: string;
}
export interface IDbColumn {
allowDBNull?: boolean;
baseCatalogName: string;
baseColumnName: string;
baseSchemaName: string;
baseServerName: string;
baseTableName: string;
columnName: string;
columnOrdinal?: number;
columnSize?: number;
isAliased?: boolean;
isAutoIncrement?: boolean;
isExpression?: boolean;
isHidden?: boolean;
isIdentity?: boolean;
isKey?: boolean;
isBytes?: boolean;
isChars?: boolean;
isSqlVariant?: boolean;
isUdt?: boolean;
dataType: string;
isXml?: boolean;
isJson?: boolean;
isLong?: boolean;
isReadOnly?: boolean;
isUnique?: boolean;
numericPrecision?: number;
numericScale?: number;
udtAssemblyQualifiedName: string;
dataTypeName: string;
}
export interface IGridResultSet {
columns: IDbColumn[];
rowsUri: string;
numberOfRows: number;
}
export interface IResultMessage {
batchId?: number;
isError: boolean;
time: string;
message: string;
}
export interface ExecutionPlanOptions {
includeEstimatedExecutionPlanXml?: boolean;
includeActualExecutionPlanXml?: boolean;
}
export interface QueryExecuteParams {
ownerUri: string;
querySelection: data.ISelectionData;
executionPlanOptions?: ExecutionPlanOptions;
}
export enum EditRowState {
clean = 0,
dirtyInsert = 1,
dirtyDelete = 2,
dirtyUpdate = 3
}
export interface EditRow {
cells: data.DbCellValue[];
id: number;
isDirty: boolean;
state: EditRowState;
}
export class MetadataQueryParams {
/**
* Owner URI of the connection that changed.
*/
public ownerUri: string;
}
/**
* Used as value version of data.MetadataType THESE SHOULD MIRROR
*/
export enum MetadataType {
Table = 0,
View = 1,
SProc = 2,
Function = 3
}
export class MetadataQueryResult {
public metadata: data.ObjectMetadata[];
}
export interface ScriptOptions {
/**
* Generate ANSI padding statements
*/
scriptANSIPadding?: boolean;
/**
* Append the generated script to a file
*/
appendToFile?: boolean;
/**
* Continue to script if an error occurs. Otherwise, stop.
*/
continueScriptingOnError?: boolean;
/**
* Convert user-defined data types to base types.
*/
convertUDDTToBaseType?: boolean;
/**
* Generate script for dependent objects for each object scripted.
*/
generateScriptForDependentObjects?: boolean;
/**
* Include descriptive headers for each object generated.
*/
includeDescriptiveHeaders?: boolean;
/**
* Check that an object with the given name exists before dropping or altering or that an object with the given name does not exist before creating.
*/
includeIfNotExists?: boolean;
/**
* Script options to set vardecimal storage format.
*/
includeVarDecimal?: boolean;
/**
* Include system generated constraint names to enforce declarative referential integrity.
*/
scriptDRIIncludeSystemNames?: boolean;
/**
* Include statements in the script that are not supported on the specified SQL Server database engine type.
*/
includeUnsupportedStatements?: boolean;
/**
* Prefix object names with the object schema.
*/
schemaQualify?: boolean;
/**
* Script options to set bindings option.
*/
bindings?: boolean;
/**
* Script the objects that use collation.
*/
collation?: boolean;
/**
* Script the default values.
*/
default?: boolean;
/**
* Script Object CREATE/DROP statements.
*/
scriptCreateDrop: string;
/**
* Script the Extended Properties for each object scripted.
*/
scriptExtendedProperties?: boolean;
/**
* Script only features compatible with the specified version of SQL Server.
*/
scriptCompatibilityOption: string;
/**
* Script only features compatible with the specified SQL Server database engine type.
*/
targetDatabaseEngineType: string;
/**
* Script only features compatible with the specified SQL Server database engine edition.
*/
targetDatabaseEngineEdition: string;
/**
* Script all logins available on the server. Passwords will not be scripted.
*/
scriptLogins?: boolean;
/**
* Generate object-level permissions.
*/
scriptObjectLevelPermissions?: boolean;
/**
* Script owner for the objects.
*/
scriptOwner?: boolean;
/**
* Script statistics, and optionally include histograms, for each selected table or view.
*/
scriptStatistics: string;
/**
* Generate USE DATABASE statement.
*/
scripUseDatabase?: boolean;
/**
* Generate script that contains schema only or schema and data.
*/
typeOfDataToScript: string;
/**
* Scripts the change tracking information.
*/
scriptChangeTracking?: boolean;
/**
* Script the check constraints for each table or view scripted.
*/
scriptCheckConstraints?: boolean;
/**
* Scripts the data compression information.
*/
scriptDataCompressionOptions?: boolean;
/**
* Script the foreign keys for each table scripted.
*/
scriptForeignKeys?: boolean;
/**
* Script the full-text indexes for each table or indexed view scripted.
*/
scriptFullTextIndexes?: boolean;
/**
* Script the indexes (including XML and clustered indexes) for each table or indexed view scripted.
*/
scriptIndexes?: boolean;
/**
* Script the primary keys for each table or view scripted
*/
scriptPrimaryKeys?: boolean;
/**
* Script the triggers for each table or view scripted
*/
scriptTriggers?: boolean;
/**
* Script the unique keys for each table or view scripted.
*/
uniqueKeys?: boolean;
}
export interface ScriptingObject {
/**
* The database object type
*/
type: string;
/**
* The schema of the database object
*/
schema: string;
/**
* The database object name
*/
name: string;
}
export interface ScriptingParams {
/**
* File path used when writing out the script.
*/
filePath: string;
/**
* Whether scripting to a single file or file per object.
*/
scriptDestination: string;
/**
* Connection string of the target database the scripting operation will run against.
*/
connectionString: string;
/**
* A list of scripting objects to script
*/
scriptingObjects: ScriptingObject[];
/**
* A list of scripting object which specify the include criteria of objects to script.
*/
includeObjectCriteria: ScriptingObject[];
/**
* A list of scripting object which specify the exclude criteria of objects to not script.
*/
excludeObjectCriteria: ScriptingObject[];
/**
* A list of schema name of objects to script.
*/
includeSchemas: string[];
/**
* A list of schema name of objects to not script.
*/
excludeSchemas: string[];
/**
* A list of type name of objects to script.
*/
includeTypes: string[];
/**
* A list of type name of objects to not script.
*/
excludeTypes: string[];
/**
* Scripting options for the ScriptingParams
*/
scriptOptions: ScriptOptions;
/**
* Connection details for the ScriptingParams
*/
connectionDetails: ConnectionDetails;
/**
* Owner URI of the connection
*/
ownerURI: string;
/**
* Whether the scripting operation is for
* select script statements
*/
selectScript: boolean;
/**
* Operation associated with the script request
*/
operation: data.ScriptOperation;
}
export interface ScriptingCompleteParams {
/**
* The error details for an error that occurred during the scripting operation.
*/
errorDetails: string;
/**
* The error message for an error that occurred during the scripting operation.
*/
errorMessage: string;
/**
* A value to indicate an error occurred during the scripting operation.
*/
hasError: boolean;
/**
* A value to indicate the scripting operation was canceled.
*/
canceled: boolean;
/**
* A value to indicate the scripting operation successfully completed.
*/
success: boolean;
}
export class TableMetadata {
columns: data.ColumnMetadata[];
}
/**
* Parameters to start a profiler session
*/
export interface StartProfilingParams {
/**
* Session Owner URI
*/
ownerUri: string;
/**
* Session options
*/
options: {};
}
export interface StartProfilingResponse {
succeeded: string;
errorMessage: string;
}
/**
* Parameters to start a profiler session
*/
export interface StopProfilingParams {
/**
* Session Owner URI
*/
ownerUri: string;
}
export interface StopProfilingResponse {
succeeded: string;
errorMessage: string;
}
/**
* Profiler Event
*/
export interface ProfilerEvent {
/**
* Event class name
*/
name: string;
/**
* Event timestamp
*/
timestamp: string;
/**
* Event values
*/
values: {};
}
/**
* Profiler events available notification parameters
*/
export interface ProfilerEventsAvailableParams {
/**
* Session owner URI
*/
ownerUri: string;
/**
* New profiler events available
*/
events: ProfilerEvent[];
}
/**
* Used as value version of data.ScriptOperation THESE SHOULD BE THE SAME
*/
export enum ScriptOperation {
Select = 0,
Create = 1,
Insert = 2,
Update = 3,
Delete = 4,
Execute = 5,
Alter = 6
}

View File

@@ -0,0 +1,2 @@
/// <reference path='../../../src/sql/data.d.ts'/>

View File

@@ -0,0 +1,17 @@
{
"tabSize": 4,
"indentSize": 4,
"newLineCharacter": "\n",
"convertTabsToSpaces": false,
"insertSpaceAfterCommaDelimiter": true,
"insertSpaceAfterSemicolonInForStatements": true,
"insertSpaceBeforeAndAfterBinaryOperators": true,
"insertSpaceAfterKeywordsInControlFlowStatements": true,
"insertSpaceAfterFunctionKeywordForAnonymousFunctions": true,
"insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false,
"insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false,
"insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false,
"insertSpaceBeforeFunctionParenthesis": false,
"placeOpenBraceOnNewLineForFunctions": false,
"placeOpenBraceOnNewLineForControlBlocks": false
}

File diff suppressed because it is too large Load Diff

3
extensions-modules/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
lib/
node_modules
*.log

View File

@@ -0,0 +1,9 @@
.vscode/
lib/test/
lib/**/*.map
src/
test/
.eslintrc
.gitignore
gulpfile.js
tsd.json

View File

@@ -0,0 +1,28 @@
{
"name": "extensions-modules",
"version": "0.1.0",
"description": "Shared modules for Carbon extensions",
"dependencies": {
"dataprotocol-client": "file:../dataprotocol-client",
"decompress": "^4.2.0",
"fs-extra-promise": "^1.0.1",
"http-proxy-agent": "^2.0.0",
"https-proxy-agent": "^2.1.0",
"opener": "^1.4.3",
"tmp": "0.0.33",
"vscode-extension-telemetry": "0.0.8",
"vscode-languageclient": "^3.5.0"
},
"devDependencies": {
"@types/node": "^6.0.61",
"vscode": "1.0.1"
},
"scripts": {
"prepare": "tsc -p ./src",
"compile": "tsc -p ./src",
"watch": "tsc -w -p ./src",
"update-vscode": "node ./node_modules/vscode/bin/install"
},
"main": "./lib/main.js",
"typings": "./lib/main"
}

View File

@@ -0,0 +1,89 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
const fs = require('fs');
import * as path from 'path';
import { IConfig } from '../languageservice/interfaces';
import { Constants } from '../models/constants';
/*
* Config class handles getting values from config.json.
*/
export default class Config implements IConfig {
private _configJsonContent: any = undefined;
private _extensionConfigSectionName: string = undefined;
private _fromBuild: boolean = undefined;
constructor(extensionConfigSectionName: string, private path: string, fromBuild?: boolean) {
this._extensionConfigSectionName = extensionConfigSectionName;
this._fromBuild = fromBuild;
}
public get configJsonContent(): any {
if (this._configJsonContent === undefined) {
this._configJsonContent = this.loadConfig();
}
return this._configJsonContent;
}
public getDownloadUrl(): string {
return this.getConfigValue(Constants.downloadUrlConfigKey);
}
public getInstallDirectory(): string {
return this.getConfigValue(Constants.installDirConfigKey);
}
public getExecutableFiles(): string[] {
return this.getConfigValue(Constants.executableFilesConfigKey);
}
public getPackageVersion(): string {
return this.getConfigValue(Constants.versionConfigKey);
}
public getConfigValue(configKey: string): any {
let json = this.configJsonContent;
let toolsConfig = json[Constants.serviceConfigKey];
let configValue: string = undefined;
if (toolsConfig !== undefined) {
configValue = toolsConfig[configKey];
}
return configValue;
}
public getExtensionConfig(key: string, defaultValue?: any): any {
let json = this.configJsonContent;
let extensionConfig = json[this._extensionConfigSectionName];
let configValue = extensionConfig[key];
if (!configValue) {
configValue = defaultValue;
}
return configValue;
}
public getWorkspaceConfig(key: string, defaultValue?: any): any {
let json = this.configJsonContent;
let configValue = json[key];
if (!configValue) {
configValue = defaultValue;
}
return configValue;
}
public loadConfig(): any {
let configContent = undefined;
if (this._fromBuild) {
let remainingPath = '../../../extensions/' + this._extensionConfigSectionName + '/client/out/config.json';
configContent = fs.readFileSync(path.join(__dirname, remainingPath));
}
else {
configContent = fs.readFileSync(this.path);
}
return JSON.parse(configContent);
}
}

View File

@@ -0,0 +1,76 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import Config from './config';
import { workspace, WorkspaceConfiguration } from 'vscode';
import { IConfig } from '../languageservice/interfaces';
import { Constants } from '../models/constants';
/*
* ExtConfig class handles getting values from workspace config or config.json.
*/
export default class ExtConfig implements IConfig {
constructor(private _extensionConfigSectionName: string, private _config?: IConfig,
path?: string,
private _extensionConfig?: WorkspaceConfiguration,
private _workspaceConfig?: WorkspaceConfiguration) {
if (this._config === undefined) {
this._config = new Config(_extensionConfigSectionName, path);
}
if (this._extensionConfig === undefined) {
this._extensionConfig = workspace.getConfiguration(_extensionConfigSectionName);
}
if (this._workspaceConfig === undefined) {
this._workspaceConfig = workspace.getConfiguration();
}
}
public getDownloadUrl(): string {
return this.getConfigValue(Constants.downloadUrlConfigKey);
}
public getInstallDirectory(): string {
return this.getConfigValue(Constants.installDirConfigKey);
}
public getExecutableFiles(): string[] {
return this.getConfigValue(Constants.executableFilesConfigKey);
}
public getPackageVersion(): string {
return this.getConfigValue(Constants.versionConfigKey);
}
public getConfigValue(configKey: string): any {
let configValue: string = <string>this.getExtensionConfig(`${Constants.serviceConfigKey}.${configKey}`);
if (!configValue) {
configValue = this._config.getConfigValue(configKey);
}
return configValue;
}
public getExtensionConfig(key: string, defaultValue?: any): any {
let configValue = this._extensionConfig.get(key);
if (configValue === undefined) {
configValue = defaultValue;
}
return configValue;
}
public getWorkspaceConfig(key: string, defaultValue?: any): any {
let configValue = this._workspaceConfig.get(key);
if (configValue === undefined) {
configValue = defaultValue;
}
return configValue;
}
public updateWorkspaceConfig(configKey: string, configValue: any) {
this._workspaceConfig.update(configKey, configValue, true);
}
}

View File

@@ -0,0 +1,278 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import vscode = require('vscode');
import { IExtensionConstants } from '../models/contracts/contracts';
export class VscodeWrapper {
private _extensionConstants: IExtensionConstants;
/**
* Output channel for logging. Shared among all instances.
*/
private static _outputChannel: vscode.OutputChannel;
/**
* Default constructor.
*/
public constructor(constants: IExtensionConstants) {
this._extensionConstants = constants;
if (typeof VscodeWrapper._outputChannel === 'undefined') {
VscodeWrapper._outputChannel = this.createOutputChannel(this._extensionConstants.outputChannelName);
}
}
/**
* Get the current active text editor
*/
public get activeTextEditor(): vscode.TextEditor {
return vscode.window.activeTextEditor;
}
/**
* get the current textDocument; any that are open?
*/
public get textDocuments(): vscode.TextDocument[] {
return vscode.workspace.textDocuments;
}
/**
* Parse uri
*/
public parseUri(uri: string): vscode.Uri {
return vscode.Uri.parse(uri);
}
/**
* Get the URI string for the current active text editor
*/
public get activeTextEditorUri(): string {
if (typeof vscode.window.activeTextEditor !== 'undefined' &&
typeof vscode.window.activeTextEditor.document !== 'undefined') {
return vscode.window.activeTextEditor.document.uri.toString();
}
return undefined;
}
public get constants(): IExtensionConstants {
return this._extensionConstants;
}
/**
* Create an output channel in vscode.
*/
public createOutputChannel(channelName: string): vscode.OutputChannel {
return vscode.window.createOutputChannel(channelName);
}
/**
* Executes the command denoted by the given command identifier.
*
* When executing an editor command not all types are allowed to
* be passed as arguments. Allowed are the primitive types `string`, `boolean`,
* `number`, `undefined`, and `null`, as well as classes defined in this API.
* There are no restrictions when executing commands that have been contributed
* by extensions.
*
* @param command Identifier of the command to execute.
* @param rest Parameters passed to the command function.
* @return A thenable that resolves to the returned value of the given command. `undefined` when
* the command handler function doesn't return anything.
* @see vscode.commands.executeCommand
*/
public executeCommand<T>(command: string, ...rest: any[]): Thenable<T> {
return vscode.commands.executeCommand<T>(command, ...rest);
}
/**
* Get the configuration for a extensionName; NOT YET IMPLEMENTED
* @param extensionName The string name of the extension to get the configuration for
*/
public getConfiguration(extensionName: string): vscode.WorkspaceConfiguration {
return vscode.workspace.getConfiguration(extensionName);
}
/**
* @return 'true' if the active editor window has a .sql file, false otherwise
*/
public get isEditingSqlFile(): boolean {
let sqlFile = false;
let editor = this.activeTextEditor;
if (editor) {
if (editor.document.languageId === this._extensionConstants.languageId) {
sqlFile = true;
}
}
return sqlFile;
}
/**
* An event that is emitted when a [text document](#TextDocument) is disposed.
*/
public get onDidCloseTextDocument(): vscode.Event<vscode.TextDocument> {
return vscode.workspace.onDidCloseTextDocument;
}
/**
* An event that is emitted when a [text document](#TextDocument) is opened.
*/
public get onDidOpenTextDocument(): vscode.Event<vscode.TextDocument> {
return vscode.workspace.onDidOpenTextDocument;
}
/**
* An event that is emitted when a [text document](#TextDocument) is saved to disk.
*/
public get onDidSaveTextDocument(): vscode.Event<vscode.TextDocument> {
return vscode.workspace.onDidSaveTextDocument;
}
/**
* Opens the denoted document from disk. Will return early if the
* document is already open, otherwise the document is loaded and the
* [open document](#workspace.onDidOpenTextDocument)-event fires.
* The document to open is denoted by the [uri](#Uri). Two schemes are supported:
*
* file: A file on disk, will be rejected if the file does not exist or cannot be loaded, e.g. `file:///Users/frodo/r.ini`.
* untitled: A new file that should be saved on disk, e.g. `untitled:c:\frodo\new.js`. The language will be derived from the file name.
*
* Uris with other schemes will make this method return a rejected promise.
*
* @param uri Identifies the resource to open.
* @return A promise that resolves to a [document](#TextDocument).
* @see vscode.workspace.openTextDocument
*/
public openTextDocument(uri: vscode.Uri): Thenable<vscode.TextDocument> {
return vscode.workspace.openTextDocument(uri);
}
/**
* Helper to log messages to output channel.
*/
public logToOutputChannel(msg: any): void {
let date: Date = new Date();
if (msg instanceof Array) {
msg.forEach(element => {
VscodeWrapper._outputChannel.appendLine('[' + date.toLocaleTimeString() + '] ' + element.toString());
});
} else {
VscodeWrapper._outputChannel.appendLine('[' + date.toLocaleTimeString() + '] ' + msg.toString());
}
}
/**
* Create a vscode.Range object
* @param start The start position for the range
* @param end The end position for the range
*/
public range(start: vscode.Position, end: vscode.Position): vscode.Range {
return new vscode.Range(start, end);
}
/**
* Create a vscode.Position object
* @param line The line for the position
* @param column The column for the position
*/
public position(line: number, column: number): vscode.Position {
return new vscode.Position(line, column);
}
/**
* Create a vscode.Selection object
* @param start The start postion of the selection
* @param end The end position of the selection
*/
public selection(start: vscode.Position, end: vscode.Position): vscode.Selection {
return new vscode.Selection(start, end);
}
/**
* Formats and shows a vscode error message
*/
public showErrorMessage(msg: string, ...items: string[]): Thenable<string> {
return vscode.window.showErrorMessage(this._extensionConstants.extensionName + ': ' + msg, ...items);
}
/**
* Formats and shows a vscode information message
*/
public showInformationMessage(msg: string, ...items: string[]): Thenable<string> {
return vscode.window.showInformationMessage(this._extensionConstants.extensionName + ': ' + msg, ...items);
}
/**
* Shows a selection list.
*
* @param items An array of items, or a promise that resolves to an array of items.
* @param options Configures the behavior of the selection list.
* @return A promise that resolves to the selected item or undefined.
*/
public showQuickPick<T extends vscode.QuickPickItem>(items: T[] | Thenable<T[]>, options?: vscode.QuickPickOptions): Thenable<T> {
return vscode.window.showQuickPick<T>(items, options);
}
/**
* Show the given document in a text editor. A [column](#ViewColumn) can be provided
* to control where the editor is being shown. Might change the [active editor](#window.activeTextEditor).
*
* @param document A text document to be shown.
* @param column A view column in which the editor should be shown. The default is the [one](#ViewColumn.One), other values
* are adjusted to be __Min(column, columnCount + 1)__.
* @param preserveFocus When `true` the editor will not take focus.
* @return A promise that resolves to an [editor](#TextEditor).
*/
public showTextDocument(document: vscode.TextDocument, column?: vscode.ViewColumn, preserveFocus?: boolean): Thenable<vscode.TextEditor> {
return vscode.window.showTextDocument(document, column, preserveFocus);
}
/**
* Formats and shows a vscode warning message
*/
public showWarningMessage(msg: string): Thenable<string> {
return vscode.window.showWarningMessage(this._extensionConstants.extensionName + ': ' + msg );
}
/**
* Returns a array of the text editors currently visible in the window
*/
public get visibleEditors(): vscode.TextEditor[] {
return vscode.window.visibleTextEditors;
}
/**
* Create an URI from a file system path. The [scheme](#Uri.scheme)
* will be `file`.
*
* @param path A file system or UNC path.
* @return A new Uri instance.
* @see vscode.Uri.file
*/
public uriFile(path: string): vscode.Uri {
return vscode.Uri.file(path);
}
/**
* Create an URI from a string. Will throw if the given value is not
* valid.
*
* @param value The string value of an Uri.
* @return A new Uri instance.
* @see vscode.Uri.parse
*/
public uriParse(value: string): vscode.Uri {
return vscode.Uri.parse(value);
}
/**
* The folder that is open in VS Code. `undefined` when no folder
* has been opened.
*
* @readonly
* @see vscode.workspace.rootPath
*/
public get workspaceRootPath(): string {
return vscode.workspace.rootPath;
}
}

View File

@@ -0,0 +1,24 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IDecompressProvider, IPackage } from './interfaces';
import { ILogger } from '../models/interfaces';
const decompress = require('decompress');
export default class DecompressProvider implements IDecompressProvider {
public decompress(pkg: IPackage, logger: ILogger): Promise<void> {
return new Promise<void>((resolve, reject) => {
decompress(pkg.tmpFile.name, pkg.installPath).then(files => {
logger.appendLine(`Done! ${files.length} files unpacked.\n`);
resolve();
}).catch(decompressErr => {
logger.appendLine(`[ERROR] ${decompressErr}`);
reject(decompressErr);
});
});
}
}

View File

@@ -0,0 +1,146 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IPackage, IStatusView, PackageError, IHttpClient } from './interfaces';
import { ILogger } from '../models/interfaces';
import { parse as parseUrl, Url } from 'url';
import * as https from 'https';
import * as http from 'http';
import { getProxyAgent } from './proxy';
const fs = require('fs');
/*
* Http client class to handle downloading files using http or https urls
*/
export default class HttpClient implements IHttpClient {
/*
* Downloads a file and stores the result in the temp file inside the package object
*/
public downloadFile(urlString: string, pkg: IPackage, logger: ILogger, statusView: IStatusView, proxy?: string, strictSSL?: boolean): Promise<void> {
const url = parseUrl(urlString);
let options = this.getHttpClientOptions(url, proxy, strictSSL);
let clientRequest = url.protocol === 'http:' ? http.request : https.request;
return new Promise<void>((resolve, reject) => {
if (!pkg.tmpFile || pkg.tmpFile.fd === 0) {
return reject(new PackageError('Temporary package file unavailable', pkg));
}
let request = clientRequest(options, response => {
if (response.statusCode === 301 || response.statusCode === 302) {
// Redirect - download from new location
return resolve(this.downloadFile(response.headers.location, pkg, logger, statusView, proxy, strictSSL));
}
if (response.statusCode !== 200) {
// Download failed - print error message
logger.appendLine(`failed (error code '${response.statusCode}')`);
return reject(new PackageError(response.statusCode.toString(), pkg));
}
// If status code is 200
this.handleSuccessfulResponse(pkg, response, logger, statusView).then(_ => {
resolve();
}).catch(err => {
reject(err);
});
});
request.on('error', error => {
// reject(new PackageError(`Request error: ${error.code || 'NONE'}`, pkg, error));
reject(new PackageError(`Request error: ${error.name || 'NONE'}`, pkg, error));
});
// Execute the request
request.end();
});
}
private getHttpClientOptions(url: Url, proxy?: string, strictSSL?: boolean): any {
const agent = getProxyAgent(url, proxy, strictSSL);
let options: http.RequestOptions = {
host: url.hostname,
path: url.path,
agent: agent,
port: +url.port
};
if (url.protocol === 'https:') {
let httpsOptions: https.RequestOptions = {
host: url.hostname,
path: url.path,
agent: agent,
port: +url.port
};
options = httpsOptions;
}
return options;
}
/*
* Calculate the download percentage and stores in the progress object
*/
public handleDataReceivedEvent(progress: IDownloadProgress, data: any, logger: ILogger, statusView: IStatusView): void {
progress.downloadedBytes += data.length;
// Update status bar item with percentage
if (progress.packageSize > 0) {
let newPercentage = Math.ceil(100 * (progress.downloadedBytes / progress.packageSize));
if (newPercentage !== progress.downloadPercentage) {
statusView.updateServiceDownloadingProgress(progress.downloadPercentage);
progress.downloadPercentage = newPercentage;
}
// Update dots after package name in output console
let newDots = Math.ceil(progress.downloadPercentage / 5);
if (newDots > progress.dots) {
logger.append('.'.repeat(newDots - progress.dots));
progress.dots = newDots;
}
}
return;
}
private handleSuccessfulResponse(pkg: IPackage, response: http.IncomingMessage, logger: ILogger, statusView: IStatusView): Promise<void> {
return new Promise<void>((resolve, reject) => {
let progress: IDownloadProgress = {
packageSize: parseInt(response.headers['content-length'], 10),
dots: 0,
downloadedBytes: 0,
downloadPercentage: 0
};
logger.append(`(${Math.ceil(progress.packageSize / 1024)} KB) `);
response.on('data', data => {
this.handleDataReceivedEvent(progress, data, logger, statusView);
});
let tmpFile = fs.createWriteStream(undefined, { fd: pkg.tmpFile.fd });
response.on('end', () => {
resolve();
});
response.on('error', err => {
reject(new PackageError(`Response error: ${err.name || 'NONE'}`, pkg, err));
});
// Begin piping data from the response to the package file
response.pipe(tmpFile, { end: false });
});
}
}
/*
* Interface to store the values needed to calculate download percentage
*/
export interface IDownloadProgress {
packageSize: number;
downloadedBytes: number;
downloadPercentage: number;
dots: number;
}

View File

@@ -0,0 +1,46 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as tmp from 'tmp';
import { ILogger } from '../models/interfaces';
export interface IStatusView {
installingService(): void;
serviceInstalled(): void;
serviceInstallationFailed(): void;
updateServiceDownloadingProgress(downloadPercentage: number): void;
}
export interface IConfig {
getDownloadUrl(): string;
getInstallDirectory(): string;
getExecutableFiles(): string[];
getPackageVersion(): string;
getExtensionConfig(key: string, defaultValue?: any): any;
getWorkspaceConfig(key: string, defaultValue?: any): any;
getConfigValue(configKey: string): any;
}
export interface IPackage {
url: string;
installPath?: string;
tmpFile: tmp.SynchronousResult;
}
export class PackageError extends Error {
// Do not put PII (personally identifiable information) in the 'message' field as it will be logged to telemetry
constructor(public message: string,
public pkg: IPackage = undefined,
public innerError: any = undefined) {
super(message);
}
}
export interface IHttpClient {
downloadFile(urlString: string, pkg: IPackage, logger: ILogger, statusView: IStatusView, proxy: string, strictSSL: boolean): Promise<void>;
}
export interface IDecompressProvider {
decompress(pkg: IPackage, logger: ILogger): Promise<void>;
}

View File

@@ -0,0 +1,48 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Url, parse as parseUrl } from 'url';
const HttpProxyAgent = require('http-proxy-agent');
const HttpsProxyAgent = require('https-proxy-agent');
function getSystemProxyURL(requestURL: Url): string {
if (requestURL.protocol === 'http:') {
return process.env.HTTP_PROXY || process.env.http_proxy || undefined;
} else if (requestURL.protocol === 'https:') {
return process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy || undefined;
}
return undefined;
}
/*
* Returns the proxy agent using the proxy url in the parameters or the system proxy. Returns null if no proxy found
*/
export function getProxyAgent(requestURL: Url, proxy?: string, strictSSL?: boolean): any {
const proxyURL = proxy || getSystemProxyURL(requestURL);
if (!proxyURL) {
return undefined;
}
const proxyEndpoint = parseUrl(proxyURL);
if (!/^https?:$/.test(proxyEndpoint.protocol)) {
return undefined;
}
strictSSL = strictSSL || true;
const opts = {
host: proxyEndpoint.hostname,
port: Number(proxyEndpoint.port),
auth: proxyEndpoint.auth,
rejectUnauthorized: strictSSL
};
return requestURL.protocol === 'http:' ? new HttpProxyAgent(opts) : new HttpsProxyAgent(opts);
}

View File

@@ -0,0 +1,112 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as path from 'path';
import { Runtime } from '../models/platform';
import ServiceDownloadProvider from './serviceDownloadProvider';
import { IConfig, IStatusView } from './interfaces';
const fs = require('fs-extra-promise');
/*
* Service Provider class finds the SQL tools service executable file or downloads it if doesn't exist.
*/
export default class ServerProvider {
constructor(private _downloadProvider: ServiceDownloadProvider,
private _config: IConfig,
private _statusView: IStatusView,
private _extensionConfigSectionName: string) {
}
/**
* Public get method for downloadProvider
*/
public get downloadProvider(): ServiceDownloadProvider {
return this._downloadProvider;
}
/**
* Given a file path, returns the path to the SQL Tools service file.
*/
public findServerPath(filePath: string, executableFiles: string[] = undefined): Promise<string> {
return fs.lstatAsync(filePath).then(stats => {
// If a file path was passed, assume its the launch file.
if (stats.isFile()) {
return filePath;
}
// Otherwise, search the specified folder.
let candidate: string;
if (executableFiles === undefined && this._config !== undefined) {
executableFiles = this._config.getExecutableFiles();
}
if (executableFiles !== undefined) {
executableFiles.forEach(element => {
let executableFile = path.join(filePath, element);
if (candidate === undefined && fs.existsSync(executableFile)) {
candidate = executableFile;
return candidate;
}
});
}
return candidate;
});
}
/**
* Download the service if doesn't exist and returns the file path.
*/
public getOrDownloadServer(runtime: Runtime): Promise<string> {
// Attempt to find launch file path first from options, and then from the default install location.
// If SQL tools service can't be found, download it.
return new Promise<string>((resolve, reject) => {
return this.getServerPath(runtime).then(result => {
if (result === undefined) {
return this.downloadServerFiles(runtime).then ( downloadResult => {
resolve(downloadResult);
});
} else {
return resolve(result);
}
}).catch(err => {
return reject(err);
});
}).catch(err => {
throw err;
});
}
/**
* Returns the path of the installed service
*/
public getServerPath(runtime: Runtime): Promise<string> {
const installDirectory = this._downloadProvider.getInstallDirectory(runtime, this._extensionConfigSectionName);
return this.findServerPath(installDirectory);
}
/**
* Downloads the service and returns the path of the installed service
*/
public downloadServerFiles(runtime: Runtime): Promise<string> {
return new Promise<string>((resolve, reject) => {
const installDirectory = this._downloadProvider.getInstallDirectory(runtime, this._extensionConfigSectionName);
return this._downloadProvider.installService(runtime).then( _ => {
return this.findServerPath(installDirectory).then ( result => {
return resolve(result);
});
}).catch(err => {
this._statusView.serviceInstallationFailed();
reject(err);
});
});
}
}

View File

@@ -0,0 +1,125 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IStatusView } from './interfaces';
import vscode = require('vscode');
import { IExtensionConstants } from '../models/contracts/contracts';
import { Constants } from '../models/constants';
/*
* The status class which includes the service initialization result.
*/
export class ServerInitializationResult {
public constructor(
public installedBeforeInitializing: Boolean = false,
public isRunning: Boolean = false,
public serverPath: string = undefined
) {
}
public Clone(): ServerInitializationResult {
return new ServerInitializationResult(this.installedBeforeInitializing, this.isRunning, this.serverPath);
}
public WithRunning(isRunning: Boolean): ServerInitializationResult {
return new ServerInitializationResult(this.installedBeforeInitializing, isRunning, this.serverPath);
}
}
/*
* The status class shows service installing progress in UI
*/
export class ServerStatusView implements IStatusView, vscode.Disposable {
private _numberOfSecondsBeforeHidingMessage = 5000;
private _statusBarItem: vscode.StatusBarItem = undefined;
private _progressTimerId: NodeJS.Timer;
private _constants: IExtensionConstants;
constructor(constants: IExtensionConstants) {
this._statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right);
vscode.window.onDidChangeActiveTextEditor((params) => this.onDidChangeActiveTextEditor(params));
vscode.workspace.onDidCloseTextDocument((params) => this.onDidCloseTextDocument(params));
this._constants = constants;
}
public installingService(): void {
this._statusBarItem.command = undefined;
this._statusBarItem.show();
this.showProgress('$(desktop-download) ' + Constants.serviceInstalling);
}
public updateServiceDownloadingProgress(downloadPercentage: number): void {
this._statusBarItem.text = '$(cloud-download) ' + `${Constants.serviceDownloading} ... ${downloadPercentage}%`;
this._statusBarItem.show();
}
public serviceInstalled(): void {
this._statusBarItem.command = undefined;
this._statusBarItem.text = this._constants.serviceInstalled;
this._statusBarItem.show();
// Cleat the status bar after 2 seconds
setTimeout(() => {
this._statusBarItem.hide();
}, this._numberOfSecondsBeforeHidingMessage);
}
public serviceInstallationFailed(): void {
this._statusBarItem.command = undefined;
this._statusBarItem.text = this._constants.serviceInstallationFailed;
this._statusBarItem.show();
}
private showProgress(statusText: string): void {
let index = 0;
let progressTicks = [ '|', '/', '-', '\\'];
this._progressTimerId = setInterval(() => {
index++;
if (index > 3) {
index = 0;
}
let progressTick = progressTicks[index];
if (this._statusBarItem.text !== this._constants.serviceInstalled) {
this._statusBarItem.text = statusText + ' ' + progressTick;
this._statusBarItem.show();
}
}, 200);
}
dispose(): void {
this.destroyStatusBar();
}
private hideLastShownStatusBar(): void {
if (typeof this._statusBarItem !== 'undefined') {
this._statusBarItem.hide();
}
}
private onDidChangeActiveTextEditor(editor: vscode.TextEditor): void {
// Hide the most recently shown status bar
this.hideLastShownStatusBar();
}
private onDidCloseTextDocument(doc: vscode.TextDocument): void {
// Remove the status bar associated with the document
this.destroyStatusBar();
}
private destroyStatusBar(): void {
if (typeof this._statusBarItem !== 'undefined') {
this._statusBarItem.dispose();
}
}
}

View File

@@ -0,0 +1,503 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { ExtensionContext, workspace, window, OutputChannel, languages } from 'vscode';
import { SqlOpsDataClient, LanguageClientOptions } from 'dataprotocol-client';
import { CloseAction, ErrorAction, ServerOptions, NotificationHandler, NotificationType, RequestType, TransportKind } from 'vscode-languageclient';
import { VscodeWrapper } from '../controllers/vscodeWrapper';
import { Telemetry } from '../models/telemetry';
import { Utils } from '../models/utils';
import { VersionRequest, IExtensionConstants } from '../models/contracts/contracts';
import { Logger } from '../models/logger';
import ServerProvider from './server';
import ServiceDownloadProvider from './serviceDownloadProvider';
import DecompressProvider from './decompressProvider';
import HttpClient from './httpClient';
import ExtConfig from '../configurations/extConfig';
import { PlatformInformation, Runtime } from '../models/platform';
import { ServerInitializationResult, ServerStatusView } from './serverStatus';
import StatusView from '../views/statusView';
import * as LanguageServiceContracts from '../models/contracts/languageService';
import { Constants } from '../models/constants';
import ServiceStatus from './serviceStatus';
const opener = require('opener');
const path = require('path');
let _channel: OutputChannel = undefined;
/**
* @interface IMessage
*/
interface IMessage {
jsonrpc: string;
}
/**
* Handle Language Service client errors
* @class LanguageClientErrorHandler
*/
class LanguageClientErrorHandler {
private vscodeWrapper: VscodeWrapper;
/**
* Creates an instance of LanguageClientErrorHandler.
* @memberOf LanguageClientErrorHandler
*/
constructor(constants: IExtensionConstants) {
if (!this.vscodeWrapper) {
this.vscodeWrapper = new VscodeWrapper(constants);
}
Telemetry.getRuntimeId = this.vscodeWrapper.constants.getRuntimeId;
}
/**
* Show an error message prompt with a link to known issues wiki page
* @memberOf LanguageClientErrorHandler
*/
showOnErrorPrompt(): void {
let extensionConstants = this.vscodeWrapper.constants;
Telemetry.sendTelemetryEvent(extensionConstants.serviceName + 'Crash');
this.vscodeWrapper.showErrorMessage(
extensionConstants.serviceCrashMessage,
Constants.serviceCrashButton).then(action => {
if (action && action === Constants.serviceCrashButton) {
opener(extensionConstants.serviceCrashLink);
}
});
}
/**
* Callback for language service client error
*
* @param {Error} error
* @param {Message} message
* @param {number} count
* @returns {ErrorAction}
*
* @memberOf LanguageClientErrorHandler
*/
error(error: Error, message: IMessage, count: number): ErrorAction {
this.showOnErrorPrompt();
// we don't retry running the service since crashes leave the extension
// in a bad, unrecovered state
return ErrorAction.Shutdown;
}
/**
* Callback for language service client closed
*
* @returns {CloseAction}
*
* @memberOf LanguageClientErrorHandler
*/
closed(): CloseAction {
this.showOnErrorPrompt();
// we don't retry running the service since crashes leave the extension
// in a bad, unrecovered state
return CloseAction.DoNotRestart;
}
}
// The Service Client class handles communication with the VS Code LanguageClient
export class SqlToolsServiceClient {
// singleton instance
private static _instance: SqlToolsServiceClient = undefined;
private static _constants: IExtensionConstants = undefined;
public static get constants(): IExtensionConstants {
return this._constants;
}
public static set constants(constantsObject: IExtensionConstants) {
this._constants = constantsObject;
Telemetry.getRuntimeId = this._constants.getRuntimeId;
}
private static _helper: LanguageServiceContracts.ILanguageClientHelper = undefined;
public static get helper(): LanguageServiceContracts.ILanguageClientHelper {
return this._helper;
}
public static set helper(helperObject: LanguageServiceContracts.ILanguageClientHelper) {
this._helper = helperObject;
}
// VS Code Language Client
private _client: SqlOpsDataClient = undefined;
// getter method for the Language Client
private get client(): SqlOpsDataClient {
return this._client;
}
private set client(client: SqlOpsDataClient) {
this._client = client;
}
public installDirectory: string;
private _downloadProvider: ServiceDownloadProvider;
private _vscodeWrapper: VscodeWrapper;
private _serviceStatus: ServiceStatus;
private _languageClientStartTime: number = undefined;
private _installationTime: number = undefined;
constructor(
private _server: ServerProvider,
private _logger: Logger,
private _statusView: StatusView,
private _config: ExtConfig) {
this._downloadProvider = _server.downloadProvider;
if (!this._vscodeWrapper) {
this._vscodeWrapper = new VscodeWrapper(SqlToolsServiceClient.constants);
}
this._serviceStatus = new ServiceStatus(SqlToolsServiceClient._constants.serviceName);
}
// gets or creates the singleton service client instance
public static getInstance(path: string): SqlToolsServiceClient {
if (this._instance === undefined) {
let constants = this._constants;
let config = new ExtConfig(constants.extensionConfigSectionName, undefined, path);
_channel = window.createOutputChannel(constants.serviceInitializingOutputChannelName);
let logger = new Logger(text => _channel.append(text), constants);
let serverStatusView = new ServerStatusView(constants);
let httpClient = new HttpClient();
let decompressProvider = new DecompressProvider();
let downloadProvider = new ServiceDownloadProvider(config, logger, serverStatusView, httpClient,
decompressProvider, constants, false);
let serviceProvider = new ServerProvider(downloadProvider, config, serverStatusView, constants.extensionConfigSectionName);
let statusView = new StatusView();
this._instance = new SqlToolsServiceClient(serviceProvider, logger, statusView, config);
}
return this._instance;
}
// initialize the Service Client instance by launching
// out-of-proc server through the LanguageClient
public initialize(context: ExtensionContext): Promise<any> {
this._logger.appendLine(SqlToolsServiceClient._constants.serviceInitializing);
this._languageClientStartTime = Date.now();
return PlatformInformation.getCurrent(SqlToolsServiceClient._constants.getRuntimeId, SqlToolsServiceClient._constants.extensionName).then(platformInfo => {
return this.initializeForPlatform(platformInfo, context);
}).catch(err => {
this._vscodeWrapper.showErrorMessage(err);
});
}
public initializeForPlatform(platformInfo: PlatformInformation, context: ExtensionContext): Promise<ServerInitializationResult> {
return new Promise<ServerInitializationResult>((resolve, reject) => {
this._logger.appendLine(SqlToolsServiceClient._constants.commandsNotAvailableWhileInstallingTheService);
this._logger.appendLine();
this._logger.append(`Platform: ${platformInfo.toString()}`);
if (!platformInfo.isValidRuntime()) {
// if it's an unknown Linux distro then try generic Linux x64 and give a warning to the user
if (platformInfo.isLinux()) {
this._logger.appendLine(Constants.usingDefaultPlatformMessage);
platformInfo.runtimeId = Runtime.Linux_64;
}
let ignoreWarning: boolean = this._config.getWorkspaceConfig(Constants.ignorePlatformWarning, false);
if (!ignoreWarning) {
this._vscodeWrapper.showErrorMessage(
Constants.unsupportedPlatformErrorMessage,
Constants.neverShowAgain)
.then(action => {
if (action === Constants.neverShowAgain) {
this._config.updateWorkspaceConfig(Constants.ignorePlatformWarning, true);
}
});
}
Telemetry.sendTelemetryEvent('UnsupportedPlatform', { platform: platformInfo.toString() });
}
if (platformInfo.runtimeId) {
this._logger.appendLine(` (${platformInfo.getRuntimeDisplayName()})`);
} else {
this._logger.appendLine();
}
this._logger.appendLine();
this._server.getServerPath(platformInfo.runtimeId).then(serverPath => {
if (serverPath === undefined) {
// Check if the service already installed and if not open the output channel to show the logs
if (_channel !== undefined) {
_channel.show();
}
let installationStartTime = Date.now();
this._server.downloadServerFiles(platformInfo.runtimeId).then(installedServerPath => {
this._installationTime = Date.now() - installationStartTime;
this.initializeLanguageClient(installedServerPath, context, platformInfo.runtimeId);
resolve(new ServerInitializationResult(true, true, installedServerPath));
}).catch(downloadErr => {
reject(downloadErr);
});
} else {
this.initializeLanguageClient(serverPath, context, platformInfo.runtimeId);
resolve(new ServerInitializationResult(false, true, serverPath));
}
}).catch(err => {
Utils.logDebug(SqlToolsServiceClient._constants.serviceLoadingFailed + ' ' + err, SqlToolsServiceClient._constants.extensionConfigSectionName);
Utils.showErrorMsg(SqlToolsServiceClient._constants.serviceLoadingFailed, SqlToolsServiceClient._constants.extensionName);
Telemetry.sendTelemetryEvent('ServiceInitializingFailed');
reject(err);
});
});
}
/**
* Initializes the SQL language configuration
*
* @memberOf SqlToolsServiceClient
*/
private initializeLanguageConfiguration(): void {
languages.setLanguageConfiguration('sql', {
comments: {
lineComment: '--',
blockComment: ['/*', '*/']
},
brackets: [
['{', '}'],
['[', ']'],
['(', ')']
],
__characterPairSupport: {
autoClosingPairs: [
{ open: '{', close: '}' },
{ open: '[', close: ']' },
{ open: '(', close: ')' },
{ open: '"', close: '"', notIn: ['string'] },
{ open: '\'', close: '\'', notIn: ['string', 'comment'] }
]
}
});
}
private initializeLanguageClient(serverPath: string, context: ExtensionContext, runtimeId: Runtime): void {
if (serverPath === undefined) {
Utils.logDebug(SqlToolsServiceClient._constants.invalidServiceFilePath, SqlToolsServiceClient._constants.extensionConfigSectionName);
throw new Error(SqlToolsServiceClient._constants.invalidServiceFilePath);
} else {
let self = this;
if (SqlToolsServiceClient._constants.languageId === 'sql') {
self.initializeLanguageConfiguration();
}
// Use default createServerOptions if one isn't specified
let serverOptions: ServerOptions = SqlToolsServiceClient._helper ?
SqlToolsServiceClient._helper.createServerOptions(serverPath, runtimeId) : self.createServerOptions(serverPath);
this.client = this.createLanguageClient(serverOptions);
this.installDirectory = this._downloadProvider.getInstallDirectory(runtimeId, SqlToolsServiceClient._constants.extensionConfigSectionName);
if (context !== undefined) {
// Create the language client and start the client.
let disposable = this.client.start();
// Push the disposable to the context's subscriptions so that the
// client can be deactivated on extension deactivation
context.subscriptions.push(disposable);
}
}
}
public createClient(context: ExtensionContext, runtimeId: Runtime, languageClientHelper: LanguageServiceContracts.ILanguageClientHelper, executableFiles: string[]): Promise<SqlOpsDataClient> {
return new Promise<SqlOpsDataClient>((resolve, reject) => {
let client: SqlOpsDataClient;
this._server.findServerPath(this.installDirectory, executableFiles).then(serverPath => {
if (serverPath === undefined) {
reject(new Error(SqlToolsServiceClient._constants.invalidServiceFilePath));
} else {
let serverOptions: ServerOptions = languageClientHelper ?
languageClientHelper.createServerOptions(serverPath, runtimeId) : this.createServerOptions(serverPath);
// Options to control the language client
let clientOptions: LanguageClientOptions = {
documentSelector: [SqlToolsServiceClient._constants.languageId],
providerId: '',
synchronize: {
configurationSection: SqlToolsServiceClient._constants.extensionConfigSectionName
},
errorHandler: new LanguageClientErrorHandler(SqlToolsServiceClient._constants),
serverConnectionMetadata: this._config.getConfigValue(Constants.serverConnectionMetadata),
outputChannel: {
append: () => {
},
appendLine: () => {
},
dispose: () => {
},
clear: () => {
},
hide: () => {
},
name: '',
show: () => {
}
}
};
this._serviceStatus.showServiceLoading();
// cache the client instance for later use
client = new SqlOpsDataClient(SqlToolsServiceClient._constants.serviceName, serverOptions, clientOptions);
if (context !== undefined) {
// Create the language client and start the client.
let disposable = client.start();
// Push the disposable to the context's subscriptions so that the
// client can be deactivated on extension deactivation
context.subscriptions.push(disposable);
}
client.onReady().then(this._serviceStatus.showServiceLoaded);
resolve(client);
}
}, error => {
reject(error);
});
});
}
private createServerOptions(servicePath): ServerOptions {
let serverArgs = [];
let serverCommand: string = servicePath;
if (servicePath.endsWith('.dll')) {
serverArgs = [servicePath];
serverCommand = 'dotnet';
}
// Enable diagnostic logging in the service if it is configured
let config = workspace.getConfiguration(SqlToolsServiceClient._constants.extensionConfigSectionName);
if (config) {
let logDebugInfo = config[Constants.configLogDebugInfo];
if (logDebugInfo) {
serverArgs.push('--enable-logging');
}
}
serverArgs.push('--log-dir');
let logFileLocation = path.join(Utils.getDefaultLogLocation(), SqlToolsServiceClient.constants.extensionName);
serverArgs.push(logFileLocation);
// run the service host using dotnet.exe from the path
let serverOptions: ServerOptions = { command: serverCommand, args: serverArgs, transport: TransportKind.stdio };
return serverOptions;
}
private createLanguageClient(serverOptions: ServerOptions): SqlOpsDataClient {
// Options to control the language client
let clientOptions: LanguageClientOptions = {
documentSelector: [SqlToolsServiceClient._constants.languageId],
providerId: SqlToolsServiceClient._constants.providerId,
synchronize: {
configurationSection: SqlToolsServiceClient._constants.extensionConfigSectionName
},
errorHandler: new LanguageClientErrorHandler(SqlToolsServiceClient._constants),
serverConnectionMetadata: this._config.getConfigValue(Constants.serverConnectionMetadata)
};
this._serviceStatus.showServiceLoading();
// cache the client instance for later use
let client = new SqlOpsDataClient(SqlToolsServiceClient._constants.serviceName, serverOptions, clientOptions);
client.onReady().then(() => {
this.checkServiceCompatibility();
this._serviceStatus.showServiceLoaded();
client.onNotification(LanguageServiceContracts.TelemetryNotification.type, this.handleLanguageServiceTelemetryNotification());
client.onNotification(LanguageServiceContracts.StatusChangedNotification.type, this.handleLanguageServiceStatusNotification());
// Report the language client startup time
let endTime = Date.now();
let installationTime = this._installationTime || 0;
let totalTime = endTime - this._languageClientStartTime;
let processStartupTime = totalTime - installationTime;
Telemetry.sendTelemetryEvent('startup/LanguageClientStarted', {
installationTime: String(installationTime),
processStartupTime: String(processStartupTime),
totalTime: String(totalTime),
beginningTimestamp: String(this._languageClientStartTime)
});
this._languageClientStartTime = undefined;
this._installationTime = undefined;
});
return client;
}
private handleLanguageServiceTelemetryNotification(): NotificationHandler<LanguageServiceContracts.TelemetryParams> {
return (event: LanguageServiceContracts.TelemetryParams): void => {
Telemetry.sendTelemetryEvent(event.params.eventName, event.params.properties, event.params.measures);
};
}
/**
* Public for testing purposes only.
*/
public handleLanguageServiceStatusNotification(): NotificationHandler<LanguageServiceContracts.StatusChangeParams> {
return (event: LanguageServiceContracts.StatusChangeParams): void => {
this._statusView.languageServiceStatusChanged(event.ownerUri, event.status);
};
}
/**
* Send a request to the service client
* @param type The of the request to make
* @param params The params to pass with the request
* @returns A thenable object for when the request receives a response
*/
public sendRequest<P, R, E, RO>(type: RequestType<P, R, E, RO>, params?: P, client: SqlOpsDataClient = undefined): Thenable<R> {
if (client === undefined) {
client = this._client;
}
if (client !== undefined) {
return client.sendRequest(type, params);
}
}
/**
* Register a handler for a notification type
* @param type The notification type to register the handler for
* @param handler The handler to register
*/
public onNotification<P, RO>(type: NotificationType<P, RO>, handler: NotificationHandler<P>, client: SqlOpsDataClient = undefined): void {
if (client === undefined) {
client = this._client;
}
if (client !== undefined) {
return client.onNotification(type, handler);
}
}
public checkServiceCompatibility(): Promise<boolean> {
return new Promise<boolean>((resolve, reject) => {
this._client.sendRequest(VersionRequest.type, undefined).then((result) => {
Utils.logDebug(SqlToolsServiceClient._constants.extensionName + ' service client version: ' + result, SqlToolsServiceClient._constants.extensionConfigSectionName);
if (result === undefined || !result.startsWith(SqlToolsServiceClient._constants.serviceCompatibleVersion)) {
Utils.showErrorMsg(Constants.serviceNotCompatibleError, SqlToolsServiceClient._constants.extensionName);
Utils.logDebug(Constants.serviceNotCompatibleError, SqlToolsServiceClient._constants.extensionConfigSectionName);
resolve(false);
} else {
resolve(true);
}
});
});
}
}

View File

@@ -0,0 +1,186 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Runtime, getRuntimeDisplayName } from '../models/platform';
import * as path from 'path';
import { IConfig, IStatusView, IPackage, PackageError, IHttpClient, IDecompressProvider } from './interfaces';
import { ILogger } from '../models/interfaces';
import { Constants } from '../models/constants';
import * as tmp from 'tmp';
import { IExtensionConstants } from '../models/contracts/contracts';
const fse = require('fs-extra');
/*
* Service Download Provider class which handles downloading the SQL Tools service.
*/
export default class ServiceDownloadProvider {
constructor(private _config: IConfig,
private _logger: ILogger,
private _statusView: IStatusView,
private _httpClient: IHttpClient,
private _decompressProvider: IDecompressProvider,
private _extensionConstants: IExtensionConstants,
private _fromBuild: boolean) {
// Ensure our temp files get cleaned up in case of error.
tmp.setGracefulCleanup();
}
/**
* Returns the download url for given platform
*/
public getDownloadFileName(platform: Runtime): string {
let fileNamesJson = this._config.getConfigValue('downloadFileNames');
console.info('Platform: ', platform.toString());
let fileName = fileNamesJson[platform.toString()];
console.info('Filename: ', fileName);
if (fileName === undefined) {
if (process.platform === 'linux') {
throw new Error('Unsupported linux distribution');
} else {
throw new Error(`Unsupported platform: ${process.platform}`);
}
}
return fileName;
}
/**
* Returns SQL tools service installed folder.
*/
public getInstallDirectory(platform: Runtime, extensionConfigSectionName: string): string {
let basePath = this.getInstallDirectoryRoot(platform, extensionConfigSectionName);
let versionFromConfig = this._config.getPackageVersion();
basePath = basePath.replace('{#version#}', versionFromConfig);
basePath = basePath.replace('{#platform#}', getRuntimeDisplayName(platform));
if (!fse.existsSync(basePath)) {
fse.mkdirsSync(basePath);
}
return basePath;
}
private getLocalUserFolderPath(platform: Runtime): string {
if (platform) {
switch (platform) {
case Runtime.Windows_64:
case Runtime.Windows_86:
return process.env.APPDATA;
case Runtime.OSX:
return process.env.HOME + '/Library/Preferences';
default:
return process.env.HOME;
}
}
}
/**
* Returns SQL tools service installed folder root.
*/
public getInstallDirectoryRoot(platform: Runtime, extensionConfigSectionName: string): string {
let installDirFromConfig : string;
installDirFromConfig = this._config.getInstallDirectory();
if (!installDirFromConfig || installDirFromConfig === '') {
let rootFolderName: string = '.sqlops';
if (platform === Runtime.Windows_64 || platform === Runtime.Windows_86) {
rootFolderName = 'sqlops';
}
installDirFromConfig = path.join(this.getLocalUserFolderPath(platform), `/${rootFolderName}/${this._extensionConstants.installFolderName}/{#version#}/{#platform#}`);
}
let basePath: string;
if (path.isAbsolute(installDirFromConfig)) {
basePath = installDirFromConfig;
} else if (this._fromBuild) {
basePath = path.join(__dirname, '../../../extensions/' + extensionConfigSectionName + '/' + installDirFromConfig);
} else {
// The path from config is relative to the out folder
basePath = path.join(__dirname, '../../../../' + extensionConfigSectionName + '/' + installDirFromConfig);
}
return basePath;
}
private getGetDownloadUrl(fileName: string): string {
let baseDownloadUrl = this._config.getDownloadUrl();
let version = this._config.getPackageVersion();
baseDownloadUrl = baseDownloadUrl.replace('{#version#}', version);
baseDownloadUrl = baseDownloadUrl.replace('{#fileName#}', fileName);
return baseDownloadUrl;
}
/**
* Downloads the service and decompress it in the install folder.
*/
public installService(platform: Runtime): Promise<boolean> {
const proxy = <string>this._config.getWorkspaceConfig('http.proxy');
const strictSSL = this._config.getWorkspaceConfig('http.proxyStrictSSL', true);
return new Promise<boolean>((resolve, reject) => {
const fileName = this.getDownloadFileName(platform);
const installDirectory = this.getInstallDirectory(platform, this._extensionConstants.extensionConfigSectionName);
this._logger.appendLine(`${this._extensionConstants.serviceInstallingTo} ${installDirectory}.`);
const urlString = this.getGetDownloadUrl(fileName);
this._logger.appendLine(`${Constants.serviceDownloading} ${urlString}`);
let pkg: IPackage = {
installPath: installDirectory,
url: urlString,
tmpFile: undefined
};
this.createTempFile(pkg).then(tmpResult => {
pkg.tmpFile = tmpResult;
this._httpClient.downloadFile(pkg.url, pkg, this._logger, this._statusView, proxy, strictSSL).then(_ => {
this._logger.logDebug(`Downloaded to ${pkg.tmpFile.name}...`);
this._logger.appendLine(' Done!');
this.install(pkg).then(result => {
resolve(true);
}).catch(installError => {
reject(installError);
});
}).catch(downloadError => {
this._logger.appendLine(`[ERROR] ${downloadError}`);
reject(downloadError);
});
});
});
}
private createTempFile(pkg: IPackage): Promise<tmp.SynchronousResult> {
return new Promise<tmp.SynchronousResult>((resolve, reject) => {
tmp.file({ prefix: 'package-' }, (err, path, fd, cleanupCallback) => {
if (err) {
return reject(new PackageError('Error from tmp.file', pkg, err));
}
resolve(<tmp.SynchronousResult>{ name: path, fd: fd, removeCallback: cleanupCallback });
});
});
}
private install(pkg: IPackage): Promise<void> {
this._logger.appendLine('Installing ...');
this._statusView.installingService();
return new Promise<void>((resolve, reject) => {
this._decompressProvider.decompress(pkg, this._logger).then(_ => {
this._statusView.serviceInstalled();
resolve();
}).catch(err => {
reject(err);
});
});
}
}

View File

@@ -0,0 +1,130 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Runtime, PlatformInformation } from '../models/platform';
import Config from '../configurations/config';
import ServiceDownloadProvider from './serviceDownloadProvider';
import DecompressProvider from './decompressProvider';
import HttpClient from './httpClient';
import ServerProvider from './server';
import { IStatusView } from './interfaces';
import { ILogger } from '../models/interfaces';
import { IExtensionConstants } from '../models/contracts/contracts';
class StubStatusView implements IStatusView {
installingService(): void {
console.log('...');
}
serviceInstalled(): void {
console.log('Service installed');
}
serviceInstallationFailed(): void {
console.log('Service installation failed');
}
updateServiceDownloadingProgress(downloadPercentage: number): void {
if (downloadPercentage === 100) {
process.stdout.write('100%');
}
}
}
class StubLogger implements ILogger {
logDebug(message: string): void {
console.log(message);
}
increaseIndent(): void {
console.log('increaseIndent');
}
decreaseIndent(): void {
console.log('decreaseIndent');
}
append(message?: string): void {
process.stdout.write(message);
}
appendLine(message?: string): void {
console.log(message);
}
}
export class ServiceInstaller {
private _config = undefined;
private _logger = new StubLogger();
private _statusView = new StubStatusView();
private _httpClient = new HttpClient();
private _decompressProvider = new DecompressProvider();
private _downloadProvider = undefined;
private _serverProvider = undefined;
private _extensionConstants = undefined;
constructor(extensionConstants: IExtensionConstants, path?: string) {
this._extensionConstants = extensionConstants;
this._config = new Config(extensionConstants.extensionConfigSectionName, path, true);
this._downloadProvider = new ServiceDownloadProvider(this._config, this._logger, this._statusView, this._httpClient, this._decompressProvider, extensionConstants, true);
this._serverProvider = new ServerProvider(this._downloadProvider, this._config, this._statusView, extensionConstants.extensionConfigSectionName);
}
/*
* Installs the service for the given platform if it's not already installed.
*/
public installService(): Promise<String> {
return PlatformInformation.getCurrent(this._extensionConstants.getRuntimeId, this._extensionConstants.extensionName).then(platformInfo => {
if (platformInfo.isValidRuntime()) {
return this._serverProvider.getOrDownloadServer(platformInfo.runtimeId);
} else {
throw new Error('unsupported runtime');
}
});
}
/*
* Returns the install folder path for given platform.
*/
public getServiceInstallDirectory(runtime: Runtime): Promise<string> {
return new Promise<string>((resolve, reject) => {
if (runtime === undefined) {
PlatformInformation.getCurrent(this._extensionConstants.getRuntimeId, this._extensionConstants.extensionName).then(platformInfo => {
if (platformInfo.isValidRuntime()) {
resolve(this._downloadProvider.getInstallDirectory(platformInfo.runtimeId));
} else {
reject('unsupported runtime');
}
}).catch(error => {
reject(error);
});
} else {
resolve(this._downloadProvider.getInstallDirectory(runtime));
}
});
}
/*
* Returns the path to the root folder of service install location.
*/
public getServiceInstallDirectoryRoot(runtime: Runtime): Promise<string> {
return new Promise<string>((resolve, reject) => {
if (runtime === undefined) {
PlatformInformation.getCurrent(this._extensionConstants.getRuntimeId, this._extensionConstants.extensionName).then(platformInfo => {
if (platformInfo.isValidRuntime()) {
let directoryPath: string = this._downloadProvider.getInstallDirectoryRoot(platformInfo, this._extensionConstants.extensionName);
directoryPath = directoryPath.replace('\\{#version#}', '');
directoryPath = directoryPath.replace('\\{#platform#}', '');
directoryPath = directoryPath.replace('/{#platform#}', '');
directoryPath = directoryPath.replace('/{#version#}', '');
resolve(directoryPath);
} else {
reject('unsupported runtime');
}
}).catch(error => {
reject(error);
});
} else {
resolve(this._downloadProvider.getInstallDirectory(runtime));
}
});
}
}

View File

@@ -0,0 +1,80 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import vscode = require('vscode');
export default class ServiceStatus implements vscode.Disposable {
private _progressTimerId: NodeJS.Timer;
private _statusBarItem: vscode.StatusBarItem = undefined;
private durationStatusInMs: number = 1500;
// These need localization
private _serviceStartingMessage: string = `Starting ${this._serviceName}`;
private _serviceStartedMessage: string = `${this._serviceName} started`;
constructor(private _serviceName: string) {
this._statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
}
public showServiceLoading(): Promise<void> {
return this === undefined ?
Promise.resolve() :
Promise.resolve(this.updateStatusView(this._serviceStartingMessage, true));
}
public showServiceLoaded(): Promise<void> {
return this === undefined ?
Promise.resolve() :
Promise.resolve(this.updateStatusView(this._serviceStartedMessage, false, this.durationStatusInMs));
}
//TODO: This can be merged with the serverStatus code
private showProgress(statusText: string): void {
let index: number = 0;
let progressTicks: string[] = ['.', '..', '...', '....'];
this._progressTimerId = setInterval(() => {
index = (index + 1) % progressTicks.length;
let progressTick = progressTicks[index];
if (this._statusBarItem.text !== this._serviceStartedMessage) {
this._statusBarItem.text = statusText + ' ' + progressTick;
this._statusBarItem.show();
}
}, 400);
}
private updateStatusView(message: string, showAsProgress: boolean = false, disposeAfter: number = -1): Promise<void> {
return new Promise<void>((resolve, reject) => {
if (showAsProgress) {
this.showProgress(message);
}
else {
this._statusBarItem.text = message;
this._statusBarItem.show();
if (this._progressTimerId !== undefined) {
clearInterval(this._progressTimerId);
}
}
if (disposeAfter !== -1) {
setInterval(() => {
this._statusBarItem.hide();
}, disposeAfter);
}
resolve();
});
}
dispose(): void {
if (this._progressTimerId !== undefined) {
clearInterval(this._progressTimerId);
}
this._statusBarItem.dispose();
}
}

View File

@@ -0,0 +1,15 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export * from './controllers/vscodeWrapper';
export * from './models/constants';
export * from './models/utils';
export { SqlToolsServiceClient } from './languageservice/serviceClient';
export { IExtensionConstants } from './models/contracts/contracts';
export { ILanguageClientHelper } from './models/contracts/languageService';
export { Runtime, PlatformInformation } from './models/platform';
export { Telemetry } from './models/telemetry';
export { LinuxDistribution } from './models/platform';
export { ServiceInstaller } from './languageservice/serviceInstallerUtil';

View File

@@ -0,0 +1,25 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export namespace Constants {
//constants
export const configLogDebugInfo: string = 'logDebugInfo';
export const serviceNotCompatibleError: string = 'Client is not compatible with the service layer';
export const serviceDownloading: string = 'Downloading';
export const serviceInstalling: string = 'Installing';
export const unsupportedPlatformErrorMessage: string = 'This platform is unsupported and application services may not function correctly';
export const serviceConfigKey = 'service';
export const executableFilesConfigKey = 'executableFiles';
export const versionConfigKey = 'version';
export const downloadUrlConfigKey = 'downloadUrl';
export const installDirConfigKey = 'installDir';
export const serviceCrashButton = 'View Known Issues';
export const neverShowAgain = 'Do not show again';
export const ignorePlatformWarning = 'ignorePlatformWarning';
export const usingDefaultPlatformMessage = 'Unknown platform detected, defaulting to Linux_x64 platform';
export const serverConnectionMetadata = 'serverConnectionMetadata';
export const extensionDeactivated: string = 'de-activated.';
export const extensionActivated: string = 'activated.';
}

View File

@@ -0,0 +1,50 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { RequestType } from 'vscode-languageclient';
import { Runtime, LinuxDistribution } from '../platform';
// --------------------------------- < Version Request > -------------------------------------------------
// Version request message callback declaration
export namespace VersionRequest {
export const type = new RequestType<void, VersionResult, void, void>('version');
}
// Version response format
export type VersionResult = string;
// ------------------------------- </ Version Request > --------------------------------------------------
// Constants interface for each extension
export interface IExtensionConstants {
// TODO: Fill in interface
// Definitely dependent on the extension
extensionName: string;
invalidServiceFilePath: string;
serviceName: string;
extensionConfigSectionName: string;
serviceCompatibleVersion: string;
outputChannelName: string;
languageId: string;
serviceInstallingTo: string;
serviceInitializing: string;
serviceInstalled: string;
serviceLoadingFailed: string;
serviceInstallationFailed: string;
serviceInitializingOutputChannelName: string;
commandsNotAvailableWhileInstallingTheService: string;
providerId: string;
serviceCrashMessage: string;
serviceCrashLink: string;
installFolderName: string;
telemetryExtensionName: string;
getRuntimeId(platform: string, architecture: string, distribution: LinuxDistribution): Runtime;
}

View File

@@ -0,0 +1,59 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { NotificationType, ServerOptions } from 'vscode-languageclient';
import { ITelemetryEventProperties, ITelemetryEventMeasures } from '../telemetry';
import { Runtime } from '../platform';
// ------------------------------- < Telemetry Sent Event > ------------------------------------
/**
* Event sent when the language service send a telemetry event
*/
export namespace TelemetryNotification {
export const type = new NotificationType<TelemetryParams, void>('telemetry/sqlevent');
}
/**
* Update event parameters
*/
export class TelemetryParams {
public params: {
eventName: string;
properties: ITelemetryEventProperties;
measures: ITelemetryEventMeasures;
};
}
// ------------------------------- </ Telemetry Sent Event > ----------------------------------
// ------------------------------- < Status Event > ------------------------------------
/**
* Event sent when the language service send a status change event
*/
export namespace StatusChangedNotification {
export const type = new NotificationType<StatusChangeParams, void>('textDocument/statusChanged');
}
/**
* Update event parameters
*/
export class StatusChangeParams {
/**
* URI identifying the text document
*/
public ownerUri: string;
/**
* The new status of the document
*/
public status: string;
}
// ------------------------------- </ Status Sent Event > ----------------------------------
export interface ILanguageClientHelper {
createServerOptions(servicePath: string, runtimeId?: Runtime): ServerOptions;
}

View File

@@ -4,5 +4,10 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
export const serviceName = 'AzureResourceProvider';
export const providerId = 'azureresourceProvider';
export interface ILogger {
logDebug(message: string): void;
increaseIndent(): void;
decreaseIndent(): void;
append(message?: string): void;
appendLine(message?: string): void;
}

View File

@@ -0,0 +1,69 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as os from 'os';
import { ILogger } from './interfaces';
import { Utils } from './utils';
import { IExtensionConstants } from './contracts/contracts';
/*
* Logger class handles logging messages using the Util functions.
*/
export class Logger implements ILogger {
private _writer: (message: string) => void;
private _prefix: string;
private _extensionConstants: IExtensionConstants;
private _indentLevel: number = 0;
private _indentSize: number = 4;
private _atLineStart: boolean = false;
constructor(writer: (message: string) => void, extensionConstants: IExtensionConstants, prefix?: string) {
this._writer = writer;
this._prefix = prefix;
this._extensionConstants = extensionConstants;
}
public logDebug(message: string): void {
Utils.logDebug(message, this._extensionConstants.extensionConfigSectionName);
}
private _appendCore(message: string): void {
if (this._atLineStart) {
if (this._indentLevel > 0) {
const indent = ' '.repeat(this._indentLevel * this._indentSize);
this._writer(indent);
}
if (this._prefix) {
this._writer(`[${this._prefix}] `);
}
this._atLineStart = false;
}
this._writer(message);
}
public increaseIndent(): void {
this._indentLevel += 1;
}
public decreaseIndent(): void {
if (this._indentLevel > 0) {
this._indentLevel -= 1;
}
}
public append(message?: string): void {
message = message || '';
this._appendCore(message);
}
public appendLine(message?: string): void {
message = message || '';
this._appendCore(message + os.EOL);
this._atLineStart = true;
}
}

View File

@@ -0,0 +1,314 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as child_process from 'child_process';
import * as fs from 'fs';
import * as os from 'os';
const unknown = 'unknown';
export enum Runtime {
UnknownRuntime = <any>'Unknown',
UnknownVersion = <any>'Unknown',
Windows_86 = <any>'Windows_86',
Windows_64 = <any>'Windows_64',
OSX = <any>'OSX',
CentOS_7 = <any>'CentOS_7',
Debian_8 = <any>'Debian_8',
Fedora_23 = <any>'Fedora_23',
OpenSUSE_13_2 = <any>'OpenSUSE_13_2',
SLES_12_2 = <any>'SLES_12_2',
RHEL_7 = <any>'RHEL_7',
Ubuntu_14 = <any>'Ubuntu_14',
Ubuntu_16 = <any>'Ubuntu_16',
Linux_64 = <any>'Linux_64',
Linux_86 = <any>'Linux-86'
}
export function getRuntimeDisplayName(runtime: Runtime): string {
switch (runtime) {
case Runtime.Windows_64:
return 'Windows';
case Runtime.Windows_86:
return 'Windows';
case Runtime.OSX:
return 'OSX';
case Runtime.CentOS_7:
return 'Linux';
case Runtime.Debian_8:
return 'Linux';
case Runtime.Fedora_23:
return 'Linux';
case Runtime.OpenSUSE_13_2:
return 'Linux';
case Runtime.SLES_12_2:
return 'Linux';
case Runtime.RHEL_7:
return 'Linux';
case Runtime.Ubuntu_14:
return 'Linux';
case Runtime.Ubuntu_16:
return 'Linux';
case Runtime.Linux_64:
return 'Linux';
case Runtime.Linux_86:
return 'Linux';
default:
return 'Unknown';
}
}
export class PlatformInformation {
public runtimeId: Runtime;
public constructor(
public platform: string,
public architecture: string,
public distribution: LinuxDistribution = undefined,
public getRuntimeId: (platform: string, architecture: string, distribution: LinuxDistribution) => Runtime) {
try {
this.runtimeId = this.getRuntimeId(platform, architecture, distribution);
} catch (err) {
this.runtimeId = undefined;
}
}
public isWindows(): boolean {
return this.platform === 'win32';
}
public isMacOS(): boolean {
return this.platform === 'darwin';
}
public isLinux(): boolean {
return this.platform === 'linux';
}
public isValidRuntime(): boolean {
return this.runtimeId !== undefined && this.runtimeId !== Runtime.UnknownRuntime && this.runtimeId !== Runtime.UnknownVersion;
}
public getRuntimeDisplayName(): string {
return getRuntimeDisplayName(this.runtimeId);
}
public toString(): string {
let result = this.platform;
if (this.architecture) {
if (result) {
result += ', ';
}
result += this.architecture;
}
if (this.distribution) {
if (result) {
result += ', ';
}
result += this.distribution.toString();
}
return result;
}
public static getCurrent(getRuntimeId: (platform: string, architecture: string, distribution: LinuxDistribution) => Runtime,
extensionName: string): Promise<any> {
let platform = os.platform();
let architecturePromise: Promise<string>;
let distributionPromise: Promise<LinuxDistribution>;
switch (platform) {
case 'win32':
architecturePromise = PlatformInformation.getWindowsArchitecture();
distributionPromise = Promise.resolve(undefined);
break;
case 'darwin':
let osVersion = os.release();
if (parseFloat(osVersion) < 16.0 && extensionName === 'mssql') {
return Promise.reject('The current version of macOS is not supported. Only macOS Sierra and above (>= 10.12) are supported.');
}
architecturePromise = PlatformInformation.getUnixArchitecture();
distributionPromise = Promise.resolve(undefined);
break;
case 'linux':
architecturePromise = PlatformInformation.getUnixArchitecture();
distributionPromise = LinuxDistribution.getCurrent();
break;
default:
return Promise.reject(`Unsupported platform: ${platform}`);
}
return architecturePromise.then(arch => {
return distributionPromise.then(distro => {
return new PlatformInformation(platform, arch, distro, getRuntimeId);
});
});
}
private static getWindowsArchitecture(): Promise<string> {
return new Promise<string>((resolve, reject) => {
// try to get the architecture from WMIC
PlatformInformation.getWindowsArchitectureWmic().then(architecture => {
if (architecture && architecture !== unknown) {
resolve(architecture);
} else {
// sometimes WMIC isn't available on the path so then try to parse the envvar
PlatformInformation.getWindowsArchitectureEnv().then(architecture => {
resolve(architecture);
});
}
});
});
}
private static getWindowsArchitectureWmic(): Promise<string> {
return this.execChildProcess('wmic os get osarchitecture')
.then(architecture => {
if (architecture) {
let archArray: string[] = architecture.split(os.EOL);
if (archArray.length >= 2) {
let arch = archArray[1].trim();
// Note: This string can be localized. So, we'll just check to see if it contains 32 or 64.
if (arch.indexOf('64') >= 0) {
return 'x86_64';
} else if (arch.indexOf('32') >= 0) {
return 'x86';
}
}
}
return unknown;
}).catch((error) => {
return unknown;
});
}
private static getWindowsArchitectureEnv(): Promise<string> {
return new Promise<string>((resolve, reject) => {
if (process.env.PROCESSOR_ARCHITECTURE === 'x86' && process.env.PROCESSOR_ARCHITEW6432 === undefined) {
resolve('x86');
}
else {
resolve('x86_64');
}
});
}
private static getUnixArchitecture(): Promise<string> {
return this.execChildProcess('uname -m')
.then(architecture => {
if (architecture) {
return architecture.trim();
}
return undefined;
});
}
private static execChildProcess(process: string): Promise<string> {
return new Promise<string>((resolve, reject) => {
child_process.exec(process, { maxBuffer: 500 * 1024 }, (error: Error, stdout: string, stderr: string) => {
if (error) {
reject(error);
return;
}
if (stderr && stderr.length > 0) {
reject(new Error(stderr));
return;
}
resolve(stdout);
});
});
}
}
/**
* There is no standard way on Linux to find the distribution name and version.
* Recently, systemd has pushed to standardize the os-release file. This has
* seen adoption in "recent" versions of all major distributions.
* https://www.freedesktop.org/software/systemd/man/os-release.html
*/
export class LinuxDistribution {
public constructor(
public name: string,
public version: string,
public idLike?: string[]) { }
public static getCurrent(): Promise<LinuxDistribution> {
// Try /etc/os-release and fallback to /usr/lib/os-release per the synopsis
// at https://www.freedesktop.org/software/systemd/man/os-release.html.
return LinuxDistribution.fromFilePath('/etc/os-release')
.catch(() => LinuxDistribution.fromFilePath('/usr/lib/os-release'))
.catch(() => Promise.resolve(new LinuxDistribution(unknown, unknown)));
}
public toString(): string {
return `name=${this.name}, version=${this.version}`;
}
private static fromFilePath(filePath: string): Promise<LinuxDistribution> {
return new Promise<LinuxDistribution>((resolve, reject) => {
fs.readFile(filePath, 'utf8', (error, data) => {
if (error) {
reject(error);
} else {
resolve(LinuxDistribution.fromReleaseInfo(data));
}
});
});
}
public static fromReleaseInfo(releaseInfo: string, eol: string = os.EOL): LinuxDistribution {
let name = unknown;
let version = unknown;
let idLike: string[] = undefined;
const lines = releaseInfo.split(eol);
for (let line of lines) {
line = line.trim();
let equalsIndex = line.indexOf('=');
if (equalsIndex >= 0) {
let key = line.substring(0, equalsIndex);
let value = line.substring(equalsIndex + 1);
// Strip quotes if necessary
if (value.length > 1 && value.startsWith('"') && value.endsWith('"')) {
value = value.substring(1, value.length - 1);
} else if (value.length > 1 && value.startsWith('\'') && value.endsWith('\'')) {
value = value.substring(1, value.length - 1);
}
if (key === 'ID') {
name = value;
} else if (key === 'VERSION_ID') {
version = value;
} else if (key === 'ID_LIKE') {
idLike = value.split(' ');
}
if (name !== unknown && version !== unknown && idLike !== undefined) {
break;
}
}
}
return new LinuxDistribution(name, version, idLike);
}
}

View File

@@ -4,16 +4,11 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as vscode from 'vscode';
import * as opener from 'opener';
import vscode = require('vscode');
import TelemetryReporter from 'vscode-extension-telemetry';
import { PlatformInformation } from 'service-downloader/out/platform';
import { ErrorAction, ErrorHandler, Message, CloseAction } from 'vscode-languageclient';
import * as Utils from './utils';
import * as Constants from './constants';
const packageJson = require('../package.json');
import { Utils } from './utils';
import { PlatformInformation, Runtime, LinuxDistribution } from './platform';
import { IExtensionConstants } from './contracts/contracts';
export interface ITelemetryEventProperties {
[key: string]: string;
@@ -43,6 +38,15 @@ export class Telemetry {
private static userId: string;
private static platformInformation: PlatformInformation;
private static disabled: boolean;
private static _getRuntimeId: (platform: string, architecture: string, distribution: LinuxDistribution) => Runtime;
public static get getRuntimeId() {
return this._getRuntimeId;
}
public static set getRuntimeId(runtimeIdGetter: (platform: string, architecture: string, distribution: LinuxDistribution) => Runtime) {
this._getRuntimeId = runtimeIdGetter;
}
// Get the unique ID for the current user of the extension
public static getUserId(): Promise<string> {
@@ -65,7 +69,7 @@ export class Telemetry {
return Promise.resolve(this.platformInformation);
} else {
return new Promise<PlatformInformation>(resolve => {
PlatformInformation.getCurrent().then(info => {
PlatformInformation.getCurrent(this.getRuntimeId, 'telemetry').then(info => {
this.platformInformation = info;
resolve(this.platformInformation);
});
@@ -73,6 +77,8 @@ export class Telemetry {
}
}
/**
* Disable telemetry reporting
*/
@@ -83,7 +89,7 @@ export class Telemetry {
/**
* Initialize the telemetry reporter for use.
*/
public static initialize(): void {
public static initialize(context: vscode.ExtensionContext, extensionConstants: IExtensionConstants): void {
if (typeof this.reporter === 'undefined') {
// Check if the user has opted out of telemetry
if (!vscode.workspace.getConfiguration('telemetry').get<boolean>('enableTelemetry', true)) {
@@ -91,8 +97,8 @@ export class Telemetry {
return;
}
let packageInfo = Utils.getPackageInfo(packageJson);
this.reporter = new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
let packageInfo = Utils.getPackageInfo(context);
this.reporter = new TelemetryReporter(extensionConstants.telemetryExtensionName, packageInfo.version, packageInfo.aiKey);
}
}
@@ -114,10 +120,10 @@ export class Telemetry {
// Only adding the method name and the fist line of the stack trace. We don't add the error message because it might have PII
this.sendTelemetryEvent('Exception', { methodName: methodName, errorLine: firstLine });
// Utils.logDebug('Unhandled Exception occurred. error: ' + err + ' method: ' + methodName, extensionConfigName);
Utils.logDebug('Unhandled Exception occurred. error: ' + err + ' method: ' + methodName, extensionConfigName);
} catch (telemetryErr) {
// If sending telemetry event fails ignore it so it won't break the extension
// Utils.logDebug('Failed to send telemetry event. error: ' + telemetryErr, extensionConfigName);
Utils.logDebug('Failed to send telemetry event. error: ' + telemetryErr, extensionConfigName);
}
}
@@ -132,7 +138,6 @@ export class Telemetry {
if (typeof this.disabled === 'undefined') {
this.disabled = false;
}
if (this.disabled || typeof (this.reporter) === 'undefined') {
// Don't do anything if telemetry is disabled
return;
@@ -143,7 +148,7 @@ export class Telemetry {
}
// Augment the properties structure with additional common properties before sending
Promise.all([this.getUserId(), this.getPlatformInformation()]).then(() => {
Promise.all([this.getUserId, this.getPlatformInformation]).then(() => {
properties['userId'] = this.userId;
properties['distribution'] = (this.platformInformation && this.platformInformation.distribution) ?
`${this.platformInformation.distribution.name}, ${this.platformInformation.distribution.version}` : '';
@@ -152,60 +157,3 @@ export class Telemetry {
});
}
}
/**
* Handle Language Service client errors
* @class LanguageClientErrorHandler
*/
export class LanguageClientErrorHandler implements ErrorHandler {
/**
* Show an error message prompt with a link to known issues wiki page
* @memberOf LanguageClientErrorHandler
*/
showOnErrorPrompt(): void {
Telemetry.sendTelemetryEvent(Constants.serviceName + 'Crash');
vscode.window.showErrorMessage(
Constants.serviceCrashMessage,
Constants.serviceCrashButton).then(action => {
if (action && action === Constants.serviceCrashButton) {
opener(Constants.serviceCrashLink);
}
});
}
/**
* Callback for language service client error
*
* @param {Error} error
* @param {Message} message
* @param {number} count
* @returns {ErrorAction}
*
* @memberOf LanguageClientErrorHandler
*/
error(error: Error, message: Message, count: number): ErrorAction {
this.showOnErrorPrompt();
// we don't retry running the service since crashes leave the extension
// in a bad, unrecovered state
return ErrorAction.Shutdown;
}
/**
* Callback for language service client closed
*
* @returns {CloseAction}
*
* @memberOf LanguageClientErrorHandler
*/
closed(): CloseAction {
this.showOnErrorPrompt();
// we don't retry running the service since crashes leave the extension
// in a bad, unrecovered state
return CloseAction.DoNotRestart;
}
}
Telemetry.initialize();

View File

@@ -0,0 +1,130 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as crypto from 'crypto';
import * as os from 'os';
import vscode = require('vscode');
import { Constants } from './constants';
import { ExtensionContext } from 'vscode';
var path = require('path');
export namespace Utils {
// INTERFACES /////////////////////////////////////////////////////////////////////////////////////
// Interface for package.json information
export interface IPackageInfo {
name: string;
version: string;
aiKey: string;
}
// FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////
// Get information from the extension's package.json file
export function getPackageInfo(context: ExtensionContext): IPackageInfo {
let extensionPackage = require(context.asAbsolutePath('./package.json'));
if (extensionPackage) {
return {
name: extensionPackage.name,
version: extensionPackage.version,
aiKey: extensionPackage.aiKey
};
}
}
// Generate a new GUID
export function generateGuid(): string {
let hexValues: string[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
// c.f. rfc4122 (UUID version 4 = xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx)
let oct: string = '';
let tmp: number;
/* tslint:disable:no-bitwise */
for (let a: number = 0; a < 4; a++) {
tmp = (4294967296 * Math.random()) | 0;
oct += hexValues[tmp & 0xF] +
hexValues[tmp >> 4 & 0xF] +
hexValues[tmp >> 8 & 0xF] +
hexValues[tmp >> 12 & 0xF] +
hexValues[tmp >> 16 & 0xF] +
hexValues[tmp >> 20 & 0xF] +
hexValues[tmp >> 24 & 0xF] +
hexValues[tmp >> 28 & 0xF];
}
// 'Set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and one, respectively'
let clockSequenceHi: string = hexValues[8 + (Math.random() * 4) | 0];
return oct.substr(0, 8) + '-' + oct.substr(9, 4) + '-4' + oct.substr(13, 3) + '-' + clockSequenceHi + oct.substr(16, 3) + '-' + oct.substr(19, 12);
/* tslint:enable:no-bitwise */
}
// Generate a unique, deterministic ID for the current user of the extension
export function generateUserId(): Promise<string> {
return new Promise<string>(resolve => {
try {
let interfaces = os.networkInterfaces();
let mac;
for (let key of Object.keys(interfaces)) {
let item = interfaces[key][0];
if (!item.internal) {
mac = item.mac;
break;
}
}
if (mac) {
resolve(crypto.createHash('sha256').update(mac + os.homedir(), 'utf8').digest('hex'));
} else {
resolve(generateGuid());
}
} catch (err) {
resolve(generateGuid()); // fallback
}
});
}
// Retrieve the URI for the currently open file if there is one; otherwise return the empty string
export function getActiveTextEditorUri(): string {
if (typeof vscode.window.activeTextEditor !== 'undefined' &&
typeof vscode.window.activeTextEditor.document !== 'undefined') {
return vscode.window.activeTextEditor.document.uri.toString();
}
return '';
}
// Helper to log debug messages
export function logDebug(msg: any, extensionConfigSectionName: string): void {
let config = vscode.workspace.getConfiguration(extensionConfigSectionName);
let logDebugInfo = config[Constants.configLogDebugInfo];
if (logDebugInfo === true) {
let currentTime = new Date().toLocaleTimeString();
let outputMsg = '[' + currentTime + ']: ' + msg ? msg.toString() : '';
console.log(outputMsg);
}
}
// Helper to show an error message
export function showErrorMsg(msg: string, extensionName: string): void {
vscode.window.showErrorMessage(extensionName + ': ' + msg);
}
export function isEmpty(str: any): boolean {
return (!str || '' === str);
}
// The function is a duplicate of \src\paths.js. IT would be better to import path.js but it doesn't
// work for now because the extension is running in different process.
export function getAppDataPath() {
var platform = process.platform;
switch (platform) {
case 'win32': return process.env['APPDATA'] || path.join(process.env['USERPROFILE'], 'AppData', 'Roaming');
case 'darwin': return path.join(os.homedir(), 'Library', 'Application Support');
case 'linux': return process.env['XDG_CONFIG_HOME'] || path.join(os.homedir(), '.config');
default: throw new Error('Platform not supported');
}
}
export function getDefaultLogLocation() {
return path.join(getAppDataPath(), 'sqlops');
}
}

View File

@@ -3,7 +3,7 @@
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"outDir": "./out",
"outDir": "../lib",
"lib": [
"es6", "es2015.promise"
],

View File

@@ -3,8 +3,5 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
dashboard-home-tab {
height: 100%;
width: 100%;
display: block;
}
/// <reference path='../../../src/vs/vscode.d.ts'/>
/// <reference path='../../../src/sql/data.d.ts'/>

Some files were not shown because too many files have changed in this diff Show More