Merge branch 'microsoft:main' into main

This commit is contained in:
Liangcheng Juves 2021-06-09 21:49:04 +08:00
commit e3c4990c67
236 changed files with 5034 additions and 4112 deletions

View file

@ -104,6 +104,7 @@
"restrictions": [
"assert",
"sinon",
"sinon-test",
"vs/nls",
"**/vs/base/common/**",
"**/vs/base/test/common/**"
@ -139,6 +140,7 @@
"restrictions": [
"assert",
"sinon",
"sinon-test",
"vs/nls",
"**/vs/base/{common,browser}/**",
"**/vs/base/test/{common,browser}/**"
@ -212,6 +214,7 @@
"restrictions": [
"assert",
"sinon",
"sinon-test",
"vs/nls",
"**/vs/base/common/**",
"**/vs/base/parts/*/common/**",
@ -225,6 +228,7 @@
"restrictions": [
"assert",
"sinon",
"sinon-test",
"vs/nls",
"**/vs/base/{common,browser}/**",
"**/vs/base/parts/*/{common,browser}/**",
@ -289,6 +293,7 @@
"restrictions": [
"assert",
"sinon",
"sinon-test",
"vs/nls",
"**/vs/base/{common,browser}/**",
"**/vs/base/parts/*/{common,browser}/**",
@ -311,6 +316,7 @@
"restrictions": [
"assert",
"sinon",
"sinon-test",
"vs/nls",
"**/vs/base/common/**",
"**/vs/platform/*/common/**",
@ -334,6 +340,7 @@
"restrictions": [
"assert",
"sinon",
"sinon-test",
"vs/nls",
"**/vs/base/{common,browser}/**",
"**/vs/platform/*/{common,browser}/**",
@ -357,6 +364,7 @@
"restrictions": [
"assert",
"sinon",
"sinon-test",
"vs/nls",
"**/vs/base/common/**",
"**/vs/platform/*/common/**",
@ -383,6 +391,7 @@
"restrictions": [
"assert",
"sinon",
"sinon-test",
"vs/nls",
"**/vs/base/{common,browser}/**",
"**/vs/platform/*/{common,browser}/**",
@ -397,6 +406,7 @@
"restrictions": [
"assert",
"sinon",
"sinon-test",
"vs/nls",
"**/vs/base/{common,browser}/**",
"**/vs/base/test/{common,browser}/**",
@ -921,6 +931,7 @@
"**/vs/**",
"assert",
"sinon",
"sinon-test",
"crypto",
"vscode"
]
@ -952,6 +963,7 @@
"**/vs/**",
"assert",
"sinon",
"sinon-test",
"crypto",
"xterm*"
]
@ -962,6 +974,7 @@
"**/vs/**",
"assert",
"sinon",
"sinon-test",
"crypto",
"xterm*"
]
@ -989,6 +1002,7 @@
"vscode-dts-cancellation": "warn",
"vscode-dts-use-thenable": "warn",
"vscode-dts-region-comments": "warn",
"vscode-dts-vscode-in-comments": "warn",
"vscode-dts-provider-naming": [
"warn",
{

View file

@ -7,19 +7,17 @@ on:
jobs:
main:
runs-on: ubuntu-latest
if: contains(github.event.issue.labels.*.name, '*english-please')
steps:
- name: Checkout Actions
if: contains(github.event.issue.labels.*.name, '*english-please')
uses: actions/checkout@v2
with:
repository: "microsoft/vscode-github-triage-actions"
ref: stable
path: ./actions
- name: Install Actions
if: contains(github.event.issue.labels.*.name, '*english-please')
run: npm install --production --prefix ./actions
- name: Run English Please
if: contains(github.event.issue.labels.*.name, '*english-please')
uses: ./actions/english-please
with:
appInsightsKey: ${{secrets.TRIAGE_ACTIONS_APP_INSIGHTS}}

View file

@ -33,5 +33,5 @@ jobs:
with:
languages: typescript
repo-token: ${{ secrets.GITHUB_TOKEN }}
typescriptVersion: 0.6.0-next.8
typescriptVersion: 0.6.0-dev.1
continue-on-error: true

View file

@ -7,7 +7,7 @@
{
"kind": 2,
"language": "github-issues",
"value": "$repo=repo:microsoft/vscode\n$milestone=milestone:\"May 2021\""
"value": "$repo=repo:microsoft/vscode\n$milestone=milestone:\"June 2021\""
},
{
"kind": 1,

View file

@ -51,7 +51,7 @@ module.exports.indentationFilter = [
'!test/monaco/out/**',
'!test/smoke/out/**',
'!extensions/typescript-language-features/test-workspace/**',
'!extensions/notebook-markdown-extensions/notebook-out/**',
'!extensions/markdown-math/notebook-out/**',
'!extensions/vscode-api-tests/testWorkspace/**',
'!extensions/vscode-api-tests/testWorkspace2/**',
'!extensions/vscode-custom-editor-tests/test-workspace/**',
@ -89,7 +89,7 @@ module.exports.indentationFilter = [
'!**/*.dockerfile',
'!extensions/markdown-language-features/media/*.js',
'!extensions/markdown-language-features/notebook-out/*.js',
'!extensions/notebook-markdown-extensions/notebook-out/*.js',
'!extensions/markdown-math/notebook-out/*.js',
'!extensions/simple-browser/media/*.js',
];
@ -119,7 +119,7 @@ module.exports.copyrightFilter = [
'!resources/completions/**',
'!extensions/configuration-editing/build/inline-allOf.ts',
'!extensions/markdown-language-features/media/highlight.css',
'!extensions/notebook-markdown-extensions/notebook-out/**',
'!extensions/markdown-math/notebook-out/**',
'!extensions/html-language-features/server/src/modes/typescript/*',
'!extensions/*/server/bin/*',
'!src/vs/editor/test/node/classification/typescript-test.ts',

View file

@ -50,6 +50,7 @@ const compilations = [
'json-language-features/server/tsconfig.json',
'markdown-language-features/preview-src/tsconfig.json',
'markdown-language-features/tsconfig.json',
'markdown-math/tsconfig.json',
'merge-conflict/tsconfig.json',
'microsoft-authentication/tsconfig.json',
'npm/tsconfig.json',

View file

@ -0,0 +1,45 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
module.exports = new class ApiVsCodeInComments {
constructor() {
this.meta = {
messages: {
comment: `Don't use the term 'vs code' in comments`
}
};
}
create(context) {
const sourceCode = context.getSourceCode();
return {
['Program']: (_node) => {
for (const comment of sourceCode.getAllComments()) {
if (comment.type !== 'Block') {
continue;
}
if (!comment.range) {
continue;
}
const startIndex = comment.range[0] + '/*'.length;
const re = /vs code/ig;
let match;
while ((match = re.exec(comment.value))) {
// Allow using 'VS Code' in quotes
if (comment.value[match.index - 1] === `'` && comment.value[match.index + match[0].length] === `'`) {
continue;
}
// Types for eslint seem incorrect
const start = sourceCode.getLocFromIndex(startIndex + match.index);
const end = sourceCode.getLocFromIndex(startIndex + match.index + match[0].length);
context.report({
messageId: 'comment',
loc: { start, end }
});
}
}
}
};
}
};

View file

@ -0,0 +1,53 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as eslint from 'eslint';
import type * as estree from 'estree';
export = new class ApiVsCodeInComments implements eslint.Rule.RuleModule {
readonly meta: eslint.Rule.RuleMetaData = {
messages: {
comment: `Don't use the term 'vs code' in comments`
}
};
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
const sourceCode = context.getSourceCode();
return {
['Program']: (_node: any) => {
for (const comment of sourceCode.getAllComments()) {
if (comment.type !== 'Block') {
continue;
}
if (!comment.range) {
continue;
}
const startIndex = comment.range[0] + '/*'.length;
const re = /vs code/ig;
let match: RegExpExecArray | null;
while ((match = re.exec(comment.value))) {
// Allow using 'VS Code' in quotes
if (comment.value[match.index - 1] === `'` && comment.value[match.index + match[0].length] === `'`) {
continue;
}
// Types for eslint seem incorrect
const start = sourceCode.getLocFromIndex(startIndex + match.index) as any as estree.Position;
const end = sourceCode.getLocFromIndex(startIndex + match.index + match[0].length) as any as estree.Position;
context.report({
messageId: 'comment',
loc: { start, end }
});
}
}
}
};
}
};

View file

@ -338,7 +338,7 @@ const webpackMediaConfigFiles = [
// Additional projects to run esbuild on. These typically build code for webviews
const esbuildMediaScripts = [
'markdown-language-features/esbuild.js',
'notebook-markdown-extensions/esbuild.js',
'markdown-math/esbuild.js',
];
async function webpackExtensions(taskName, isWatch, webpackConfigLocations) {
const webpack = require('webpack');

View file

@ -417,7 +417,7 @@ const webpackMediaConfigFiles = [
// Additional projects to run esbuild on. These typically build code for webviews
const esbuildMediaScripts = [
'markdown-language-features/esbuild.js',
'notebook-markdown-extensions/esbuild.js',
'markdown-math/esbuild.js',
];
export async function webpackExtensions(taskName: string, isWatch: boolean, webpackConfigLocations: { configPath: string, outputRoot?: string }[]) {

File diff suppressed because it is too large Load diff

View file

@ -148,9 +148,9 @@ fsevents@~2.3.1:
integrity sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==
glob-parent@^5.1.1, glob-parent@~5.1.0:
version "5.1.1"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
is-glob "^4.0.1"

View file

@ -28,9 +28,9 @@ exports.dirs = [
'extensions/json-language-features',
'extensions/json-language-features/server',
'extensions/markdown-language-features',
'extensions/markdown-math',
'extensions/merge-conflict',
'extensions/microsoft-authentication',
'extensions/notebook-markdown-extensions',
'extensions/npm',
'extensions/php-language-features',
'extensions/search-result',

View file

@ -25,7 +25,7 @@ function update(options) {
throw new Error(`${location} doesn't exist.`);
}
let locExtFolder = idOrPath;
if (/^\w{2}(-\w+)?$/.test(idOrPath)) {
if (/^\w{2,3}(-\w+)?$/.test(idOrPath)) {
locExtFolder = path.join('..', 'vscode-loc', 'i18n', `vscode-language-pack-${idOrPath}`);
}
let locExtStat = fs.statSync(locExtFolder);
@ -88,7 +88,7 @@ function update(options) {
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'));
fs.writeFileSync(path.join(locExtFolder, 'package.json'), JSON.stringify(packageJSON, null, '\t') + '\n');
}
});
});

View file

@ -52,7 +52,7 @@
"p-limit": "^3.1.0",
"plist": "^3.0.1",
"source-map": "0.6.1",
"typescript": "^4.4.0-dev.20210528",
"typescript": "^4.4.0-dev.20210607",
"vsce": "1.48.0",
"vscode-universal": "deepak1556/universal#61454d96223b774c53cda10f72c2098c0ce02d58"
},

View file

@ -13,6 +13,8 @@
"allowJs": true,
"checkJs": true,
"strict": true,
"strictOptionalProperties": false,
"useUnknownInCatchVariables": false,
"noUnusedLocals": true,
"noUnusedParameters": true,
"newLine": "lf"

View file

@ -1488,9 +1488,9 @@ node-fetch@^2.6.0:
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
normalize-url@^4.1.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129"
integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==
version "4.5.1"
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a"
integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==
nth-check@~1.0.1:
version "1.0.2"
@ -1879,10 +1879,10 @@ typescript@^4.1.3:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7"
integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==
typescript@^4.4.0-dev.20210528:
version "4.4.0-dev.20210528"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.0-dev.20210528.tgz#42453bc42e9d9df8ad0741c207c24d56407c0347"
integrity sha512-ACV+mYKC+PhWUXIDUL6qmFClIdrKc20KRxDePt8bniCgkKQD4XRYKl7m02paxJM3nTMRdlfjs0ncaslA5BA1GA==
typescript@^4.4.0-dev.20210607:
version "4.4.0-dev.20210607"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.0-dev.20210607.tgz#ea802e420785ef3b6b9c2e12d1ff4b8d2e52ee19"
integrity sha512-tKAp1IL4APSdxD7xHLDU6tIDOEN8yJOTUGG+cSdLunmysl3yOkGrdUbByDaFDmGjKywghGhQvcG8gOqbLUcDcg==
uc.micro@^1.0.1, uc.micro@^1.0.5:
version "1.0.5"

View file

@ -92,26 +92,6 @@ export function startClient(context: ExtensionContext, newLanguageClient: Langua
// client can be deactivated on extension deactivation
context.subscriptions.push(disposable);
let indentationRules = {
increaseIndentPattern: /(^.*\{[^}]*$)/,
decreaseIndentPattern: /^\s*\}/
};
languages.setLanguageConfiguration('css', {
wordPattern: /(#?-?\d*\.\d\w*%?)|(::?[\w-]*(?=[^,{;]*[,{]))|(([@#.!])?[\w-?]+%?|[@#!.])/g,
indentationRules: indentationRules
});
languages.setLanguageConfiguration('less', {
wordPattern: /(#?-?\d*\.\d\w*%?)|(::?[\w-]+(?=[^,{;]*[,{]))|(([@#.!])?[\w-?]+%?|[@#!.])/g,
indentationRules: indentationRules
});
languages.setLanguageConfiguration('scss', {
wordPattern: /(#?-?\d*\.\d\w*%?)|(::?[\w-]*(?=[^,{;]*[,{]))|(([@$#.!])?[\w-?]+%?|[@#!$.])/g,
indentationRules: indentationRules
});
client.onReady().then(() => {
context.subscriptions.push(initCompletionProvider());
});

View file

@ -26,5 +26,10 @@
"start": "^\\s*\\/\\*\\s*#region\\b\\s*(.*?)\\s*\\*\\/",
"end": "^\\s*\\/\\*\\s*#endregion\\b.*\\*\\/"
}
}
},
"indentationRules": {
"increaseIndentPattern": "(^.*\\{[^}]*$)",
"decreaseIndentPattern": "^\\s*\\}"
},
"wordPattern": "(#?-?\\d*\\.\\d\\w*%?)|(::?[\\w-]*(?=[^,{;]*[,{]))|(([@#.!])?[\\w-?]+%?|[@#!.])"
}

View file

@ -125,7 +125,7 @@ export class GitHubAuthenticationProvider implements vscode.AuthenticationProvid
}
});
this._sessions.map(session => {
this._sessions.forEach(session => {
const matchesExisting = storedSessions.some(s => s.id === session.id);
// Another window has logged out, remove from our state
if (!matchesExisting) {

View file

@ -22,5 +22,21 @@
{ "open": "\"", "close": "\"" },
{ "open": "<", "close": ">" },
{ "open": "{", "close": "}" }
]
],
"wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\$\\^\\&\\*\\(\\)\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\s]+)",
"onEnterRules": [
{
"beforeText": { "pattern": "<(?!(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr))([_:\\w][_:\\w-.\\d]*)([^/>]*(?!\\/)>)[^<]*$", "flags": "i" },
"afterText": { "pattern": "^<\\/([_:\\w][_:\\w-.\\d]*)\\s*>", "flags": "i" },
"action": {
"indent": "indentOutdent"
}
},
{
"beforeText": { "pattern": "<(?!(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr))(\\w[\\w\\d]*)([^/>]*(?!\\/)>)[^<]*$", "flags": "i" },
"action": {
"indent": "indent"
}
}
],
}

View file

@ -7,7 +7,7 @@ import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import {
languages, ExtensionContext, IndentAction, Position, TextDocument, Range, CompletionItem, CompletionItemKind, SnippetString, workspace, extensions,
languages, ExtensionContext, Position, TextDocument, Range, CompletionItem, CompletionItemKind, SnippetString, workspace, extensions,
Disposable, FormattingOptions, CancellationToken, ProviderResult, TextEdit, CompletionContext, CompletionList, SemanticTokensLegend,
DocumentSemanticTokensProvider, DocumentRangeSemanticTokensProvider, SemanticTokens, window, commands
} from 'vscode';
@ -15,7 +15,6 @@ import {
LanguageClientOptions, RequestType, TextDocumentPositionParams, DocumentRangeFormattingParams,
DocumentRangeFormattingRequest, ProvideCompletionItemsSignature, TextDocumentIdentifier, RequestType0, Range as LspRange, NotificationType, CommonLanguageClient
} from 'vscode-languageclient';
import { EMPTY_ELEMENTS } from './htmlEmptyTagsShared';
import { activateTagClosing } from './tagClosing';
import { RequestService } from './requests';
import { getCustomDataSource } from './customData';
@ -197,40 +196,6 @@ export function startClient(context: ExtensionContext, newLanguageClient: Langua
}
}
languages.setLanguageConfiguration('html', {
indentationRules: {
increaseIndentPattern: /<(?!\?|(?:area|base|br|col|frame|hr|html|img|input|keygen|link|menuitem|meta|param|source|track|wbr)\b|[^>]*\/>)([-_\.A-Za-z0-9]+)(?=\s|>)\b[^>]*>(?!.*<\/\1>)|<!--(?!.*-->)|\{[^}"']*$/,
decreaseIndentPattern: /^\s*(<\/(?!html)[-_\.A-Za-z0-9]+\b[^>]*>|-->|\})/
},
wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g,
onEnterRules: [
{
beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))([_:\\w][_:\\w-.\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'),
afterText: /^<\/([_:\w][_:\w-.\d]*)\s*>/i,
action: { indentAction: IndentAction.IndentOutdent }
},
{
beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'),
action: { indentAction: IndentAction.Indent }
}
],
});
languages.setLanguageConfiguration('handlebars', {
wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g,
onEnterRules: [
{
beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))([_:\\w][_:\\w-.\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'),
afterText: /^<\/([_:\w][_:\w-.\d]*)\s*>/i,
action: { indentAction: IndentAction.IndentOutdent }
},
{
beforeText: new RegExp(`<(?!(?:${EMPTY_ELEMENTS.join('|')}))(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$`, 'i'),
action: { indentAction: IndentAction.Indent }
}
],
});
const regionCompletionRegExpr = /^(\s*)(<(!(-(-\s*(#\w*)?)?)?)?)?$/;
const htmlSnippetCompletionRegExpr = /^(\s*)(<(h(t(m(l)?)?)?)?)?$/;
languages.registerCompletionItemProvider(documentSelector, {

View file

@ -29,5 +29,25 @@
"start": "^\\s*<!--\\s*#region\\b.*-->",
"end": "^\\s*<!--\\s*#endregion\\b.*-->"
}
},
"wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\`\\~\\!\\@\\$\\^\\&\\*\\(\\)\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\s]+)",
"onEnterRules": [
{
"beforeText": { "pattern": "<(?!(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr))([_:\\w][_:\\w-.\\d]*)([^/>]*(?!\\/)>)[^<]*$", "flags": "i" },
"afterText": { "pattern": "^<\\/([_:\\w][_:\\w-.\\d]*)\\s*>", "flags": "i" },
"action": {
"indent": "indentOutdent"
}
},
{
"beforeText": { "pattern": "<(?!(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr))(\\w[\\w\\d]*)([^/>]*(?!\\/)>)[^<]*$", "flags": "i" },
"action": {
"indent": "indent"
}
}
],
"indentationRules": {
"increaseIndentPattern": "<(?!\\?|(?:area|base|br|col|frame|hr|html|img|input|keygen|link|menuitem|meta|param|source|track|wbr)\\b|[^>]*\\/>)([-_\\.A-Za-z0-9]+)(?=\\s|>)\\b[^>]*>(?!.*<\\/\\1>)|<!--(?!.*-->)|\\{[^}\"']*$",
"decreaseIndentPattern": "^\\s*(<\\/(?!html)[-_\\.A-Za-z0-9]+\\b[^>]*>|-->|\\})"
}
}
}

View file

@ -7,7 +7,7 @@ import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import {
workspace, window, languages, commands, ExtensionContext, extensions, Uri, LanguageConfiguration,
workspace, window, languages, commands, ExtensionContext, extensions, Uri,
Diagnostic, StatusBarAlignment, TextEditor, TextDocument, FormattingOptions, CancellationToken,
ProviderResult, TextEdit, Range, Position, Disposable, CompletionItem, CompletionList, CompletionContext, Hover, MarkdownString,
} from 'vscode';
@ -358,17 +358,6 @@ export function startClient(context: ExtensionContext, newLanguageClient: Langua
}
});
const languageConfiguration: LanguageConfiguration = {
wordPattern: /("(?:[^\\\"]*(?:\\.)?)*"?)|[^\s{}\[\],:]+/,
indentationRules: {
increaseIndentPattern: /({+(?=([^"]*"[^"]*")*[^"}]*$))|(\[+(?=([^"]*"[^"]*")*[^"\]]*$))/,
decreaseIndentPattern: /^\s*[}\]],?\s*$/
}
};
languages.setLanguageConfiguration('json', languageConfiguration);
languages.setLanguageConfiguration('jsonc', languageConfiguration);
}
function getSchemaAssociations(_context: ExtensionContext): ISchemaAssociation[] {

View file

@ -14,5 +14,10 @@
{ "open": "'", "close": "'", "notIn": ["string"] },
{ "open": "\"", "close": "\"", "notIn": ["string", "comment"] },
{ "open": "`", "close": "`", "notIn": ["string", "comment"] }
]
],
"wordPattern": "(\"(?:[^\\\\\\\"]*(?:\\\\.)?)*\"?)|[^\\s{}\\[\\],:]+",
"indentationRules": {
"increaseIndentPattern": "({+(?=([^\"]*\"[^\"]*\")*[^\"}]*$))|(\\[+(?=([^\"]*\"[^\"]*\")*[^\"\\]]*$))",
"decreaseIndentPattern": "^\\s*[}\\]],?\\s*$"
}
}

View file

@ -22,14 +22,15 @@
["\"", "\""],
["'", "'"]
],
"indentationRules": {
"increaseIndentPattern": "(^.*\\{[^}]*$)",
"decreaseIndentPattern": "^\\s*\\}"
},
"folding": {
"markers": {
"start": "^\\s*\\/\\*\\s*#region\\b\\s*(.*?)\\s*\\*\\/",
"end": "^\\s*\\/\\*\\s*#endregion\\b.*\\*\\/"
}
}
}
},
"indentationRules": {
"increaseIndentPattern": "(^.*\\{[^}]*$)",
"decreaseIndentPattern": "^\\s*\\}"
},
"wordPattern": "(#?-?\\d*\\.\\d\\w*%?)|(::?[\\w-]+(?=[^,{;]*[,{]))|(([@#.!])?[\\w-?]+%?|[@#!.])"
}

View file

@ -49,5 +49,6 @@
"start": "^\\s*<!--\\s*#?region\\b.*-->",
"end": "^\\s*<!--\\s*#?endregion\\b.*-->"
}
}
},
"wordPattern": { "pattern": "(\\p{Alphabetic}|\\p{Number}|\\p{Nonspacing_Mark})(((\\p{Alphabetic}|\\p{Number}|\\p{Nonspacing_Mark})|[_])?(\\p{Alphabetic}|\\p{Number}|\\p{Nonspacing_Mark}))*", "flags": "ug" },
}

View file

@ -10,14 +10,164 @@ export function activate() {
html: true
});
const style = document.createElement('style');
style.classList.add('markdown-style');
style.textContent = `
.emptyMarkdownCell::before {
content: "${document.documentElement.style.getPropertyValue('--notebook-cell-markup-empty-content')}";
font-style: italic;
opacity: 0.6;
}
img {
max-width: 100%;
max-height: 100%;
}
a {
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
a:focus,
input:focus,
select:focus,
textarea:focus {
outline: 1px solid -webkit-focus-ring-color;
outline-offset: -1px;
}
hr {
border: 0;
height: 2px;
border-bottom: 2px solid;
}
h1 {
font-size: 26px;
line-height: 31px;
margin: 0;
margin-bottom: 13px;
}
h2 {
font-size: 19px;
margin: 0;
margin-bottom: 10px;
}
h1,
h2,
h3 {
font-weight: normal;
}
div {
width: 100%;
}
/* Adjust margin of first item in markdown cell */
*:first-child {
margin-top: 0px;
}
/* h1 tags don't need top margin */
h1:first-child {
margin-top: 0;
}
/* Removes bottom margin when only one item exists in markdown cell */
*:only-child,
*:last-child {
margin-bottom: 0;
padding-bottom: 0;
}
/* makes all markdown cells consistent */
div {
min-height: var(--notebook-markdown-min-height);
}
table {
border-collapse: collapse;
border-spacing: 0;
}
table th,
table td {
border: 1px solid;
}
table > thead > tr > th {
text-align: left;
border-bottom: 1px solid;
}
table > thead > tr > th,
table > thead > tr > td,
table > tbody > tr > th,
table > tbody > tr > td {
padding: 5px 10px;
}
table > tbody > tr + tr > td {
border-top: 1px solid;
}
blockquote {
margin: 0 7px 0 5px;
padding: 0 16px 0 10px;
border-left-width: 5px;
border-left-style: solid;
}
code,
.code {
font-size: 1em;
line-height: 1.357em;
}
.code {
white-space: pre-wrap;
}
`;
document.head.append(style);
return {
renderOutputItem: (outputInfo: { text(): string }, element: HTMLElement) => {
const rendered = markdownIt.render(outputInfo.text());
element.innerHTML = rendered;
let previewNode: HTMLElement;
if (!element.shadowRoot) {
const previewRoot = element.attachShadow({ mode: 'open' });
// Insert styles into markdown preview shadow dom so that they are applied
for (const markdownStyleNode of document.getElementsByClassName('markdown-style')) {
element.insertAdjacentElement('beforebegin', markdownStyleNode.cloneNode(true) as Element);
// Insert styles into markdown preview shadow dom so that they are applied.
// First add default webview style
const defaultStyles = document.getElementById('_defaultStyles') as HTMLStyleElement;
previewRoot.appendChild(defaultStyles.cloneNode(true));
// And then contributed styles
for (const markdownStyleNode of document.getElementsByClassName('markdown-style')) {
previewRoot.appendChild(markdownStyleNode.cloneNode(true));
}
previewNode = document.createElement('div');
previewNode.id = 'preview';
previewRoot.appendChild(previewNode);
} else {
previewNode = element.shadowRoot.getElementById('preview')!;
}
const text = outputInfo.text();
if (text.trim().length === 0) {
previewNode.innerText = '';
previewNode.classList.add('emptyMarkdownCell');
} else {
previewNode.classList.remove('emptyMarkdownCell');
const rendered = markdownIt.render(text);
previewNode.innerHTML = rendered;
}
},
extendMarkdownIt: (f: (md: typeof markdownIt) => void) => {

View file

@ -26,6 +26,7 @@
"onCommand:markdown.showSource",
"onCommand:markdown.showPreviewSecuritySelector",
"onCommand:markdown.api.render",
"onCommand:markdown.api.reloadPlugins",
"onWebviewPanel:markdown.preview",
"onCustomEditor:vscode.markdown.preview.editor"
],

View file

@ -3,11 +3,13 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export { OpenDocumentLinkCommand } from './openDocumentLink';
export { ShowPreviewCommand, ShowPreviewToSideCommand, ShowLockedPreviewToSideCommand } from './showPreview';
export { ShowSourceCommand } from './showSource';
export { RefreshPreviewCommand } from './refreshPreview';
export { ShowPreviewSecuritySelectorCommand } from './showPreviewSecuritySelector';
export { MoveCursorToPositionCommand } from './moveCursorToPosition';
export { ToggleLockCommand } from './toggleLock';
export { OpenDocumentLinkCommand } from './openDocumentLink';
export { RefreshPreviewCommand } from './refreshPreview';
export { ReloadPlugins } from './reloadPlugins';
export { RenderDocument } from './renderDocument';
export { ShowLockedPreviewToSideCommand, ShowPreviewCommand, ShowPreviewToSideCommand } from './showPreview';
export { ShowPreviewSecuritySelectorCommand } from './showPreviewSecuritySelector';
export { ShowSourceCommand } from './showSource';
export { ToggleLockCommand } from './toggleLock';

View file

@ -0,0 +1,23 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Command } from '../commandManager';
import { MarkdownPreviewManager } from '../features/previewManager';
import { MarkdownEngine } from '../markdownEngine';
export class ReloadPlugins implements Command {
public readonly id = 'markdown.api.reloadPlugins';
public constructor(
private readonly webviewManager: MarkdownPreviewManager,
private readonly engine: MarkdownEngine,
) { }
public execute(): void {
this.engine.reloadPlugins();
this.engine.cleanCache();
this.webviewManager.refresh();
}
}

View file

@ -52,12 +52,7 @@ function registerMarkdownLanguageFeatures(
): vscode.Disposable {
const selector: vscode.DocumentSelector = { language: 'markdown', scheme: '*' };
const charPattern = '(\\p{Alphabetic}|\\p{Number}|\\p{Nonspacing_Mark})';
return vscode.Disposable.from(
vscode.languages.setLanguageConfiguration('markdown', {
wordPattern: new RegExp(`${charPattern}((${charPattern}|[_])?${charPattern})*`, 'ug'),
}),
vscode.languages.registerDocumentSymbolProvider(selector, symbolProvider),
vscode.languages.registerDocumentLinkProvider(selector, new LinkProvider()),
vscode.languages.registerFoldingRangeProvider(selector, new MarkdownFoldingProvider(engine)),
@ -85,6 +80,7 @@ function registerMarkdownCommands(
commandManager.register(new commands.OpenDocumentLinkCommand(engine));
commandManager.register(new commands.ToggleLockCommand(previewManager));
commandManager.register(new commands.RenderDocument(engine));
commandManager.register(new commands.ReloadPlugins(previewManager, engine));
return commandManager;
}

View file

@ -67,6 +67,7 @@ interface RenderEnv {
}
export class MarkdownEngine {
private md?: Promise<MarkdownIt>;
private _slugCount = new Map<string, number>();
@ -129,6 +130,10 @@ export class MarkdownEngine {
return md;
}
public reloadPlugins() {
this.md = undefined;
}
private tokenizeDocument(
document: SkinnyTextDocument,
config: MarkdownItConfig,

View file

@ -1,3 +1,3 @@
# Markdown Notebook Math support
# Markdown Math support
**Notice:** This extension is bundled with Visual Studio Code. It can be disabled but not uninstalled.

View file

@ -20,7 +20,6 @@ const outDir = path.join(outputRoot, 'notebook-out');
esbuild.build({
entryPoints: [
path.join(__dirname, 'notebook', 'katex.ts'),
path.join(__dirname, 'notebook', 'emoji.ts')
],
bundle: true,
minify: true,

View file

@ -0,0 +1,17 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
//@ts-check
'use strict';
const withBrowserDefaults = require('../shared.webpack.config').browser;
module.exports = withBrowserDefaults({
context: __dirname,
entry: {
extension: './src/extension.ts'
}
});

View file

@ -0,0 +1,20 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
//@ts-check
'use strict';
const withDefaults = require('../shared.webpack.config');
module.exports = withDefaults({
context: __dirname,
resolve: {
mainFields: ['module', 'main']
},
entry: {
extension: './src/extension.ts',
}
});

View file

Before

Width:  |  Height:  |  Size: 903 B

After

Width:  |  Height:  |  Size: 903 B

View file

@ -1,11 +1,10 @@
{
"name": "notebook-markdown-extensions",
"name": "markdown-math",
"displayName": "%displayName%",
"description": "%description%",
"version": "1.0.0",
"icon": "icon.png",
"publisher": "vscode",
"enableProposedApi": true,
"license": "MIT",
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
"engines": {
@ -20,22 +19,34 @@
"supported": true
}
},
"main": "./out/extension",
"browser": "./dist/browser/extension",
"activationEvents": [],
"contributes": {
"notebookRenderer": [
{
"id": "markdownItRenderer-katex",
"displayName": "Markdown it katex renderer",
"displayName": "Markdown it KaTeX renderer",
"entrypoint": {
"extends": "markdownItRenderer",
"path": "./notebook-out/katex.js"
}
},
}
],
"markdown.markdownItPlugins": true,
"markdown.previewStyles": [
"./node_modules/katex/dist/katex.min.css",
"./preview-styles/index.css"
],
"configuration": [
{
"id": "markdownItRenderer-emoji",
"displayName": "Markdown it emoji renderer",
"entrypoint": {
"extends": "markdownItRenderer",
"path": "./notebook-out/emoji.js"
"title": "Markdown",
"properties": {
"markdown.math.enabled": {
"type": "boolean",
"default": true,
"description": "%config.markdown.math.enabled%"
}
}
}
]
@ -45,11 +56,11 @@
"watch": "npm run build-notebook",
"build-notebook": "node ./esbuild"
},
"dependencies": {
"@iktakahiro/markdown-it-katex": "https://github.com/mjbvz/markdown-it-katex.git"
},
"devDependencies": {
"@iktakahiro/markdown-it-katex": "https://github.com/mjbvz/markdown-it-katex.git",
"@types/markdown-it": "^0.0.0",
"markdown-it": "^12.0.4",
"markdown-it-emoji": "^2.0.0"
"@types/markdown-it": "^0.0.0"
},
"repository": {
"type": "git",

View file

@ -0,0 +1,5 @@
{
"displayName": "Markdown Math",
"description": "Adds math support to markdown in notebooks.",
"config.markdown.math.enabled": "Enable/disable rendering math in the built-in markdown preview."
}

View file

@ -3,4 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export const EMPTY_ELEMENTS: string[] = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'];
.katex-error {
color: var(--vscode-editorError-foreground);
}

View file

@ -0,0 +1,31 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
const enabledSetting = 'markdown.math.enabled';
export function activate(context: vscode.ExtensionContext) {
function isEnabled(): boolean {
const config = vscode.workspace.getConfiguration('markdown');
console.log(config.get<boolean>('math.enabled', true));
return config.get<boolean>('math.enabled', true);
}
vscode.workspace.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(enabledSetting)) {
vscode.commands.executeCommand('markdown.api.reloadPlugins');
}
}, undefined, context.subscriptions);
return {
extendMarkdownIt(md: any) {
if (isEnabled()) {
const katex = require('@iktakahiro/markdown-it-katex');
return md.use(katex);
}
return md;
}
};
}

View file

@ -0,0 +1 @@
/// <reference path='../../../src/vs/vscode.d.ts'/>

View file

@ -0,0 +1,17 @@
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"outDir": "./out",
"experimentalDecorators": true,
"lib": [
"es6",
"es2015.promise",
"es2019.array",
"es2020.string",
"dom"
]
},
"include": [
"src/**/*"
]
}

View file

@ -0,0 +1,26 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@iktakahiro/markdown-it-katex@https://github.com/mjbvz/markdown-it-katex.git":
version "4.0.1"
resolved "https://github.com/mjbvz/markdown-it-katex.git#2bf0b89c6c22ef0b585f55ccab66d1f7c5356bea"
dependencies:
katex "^0.13.0"
"@types/markdown-it@^0.0.0":
version "0.0.0"
resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-0.0.0.tgz#8f6acaa5e3245e275f684e95deb3e518d1c6ab16"
integrity sha1-j2rKpeMkXidfaE6V3rPlGNHGqxY=
commander@^6.0.0:
version "6.2.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
katex@^0.13.0:
version "0.13.0"
resolved "https://registry.yarnpkg.com/katex/-/katex-0.13.0.tgz#62900e56c1ad8fdf7da23399e50d7a7b690b39ab"
integrity sha512-6cHbzbegYgS9vvVGuH8UA+o97X+ZshtboSqJJCdq7trBYzuD75JNwr7Ef606xkUjecPPhFnyB+afx1dVafielg==
dependencies:
commander "^6.0.0"

View file

@ -1,22 +1,22 @@
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"baseUrl": ".",
"experimentalDecorators": true,
"forceConsistentCasingInFileNames": true,
"lib": ["es2019"],
"module": "commonjs",
"moduleResolution": "node",
"noFallthroughCasesInSwitch": true,
"noImplicitReturns": true,
"noUnusedLocals": false,
"outDir": "dist",
"resolveJsonModule": true,
"rootDir": "src",
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"target": "es2019"
"sourceMap": true
},
"exclude": ["node_modules"],
"include": ["src/**/*"]
"exclude": [
"node_modules"
],
"include": [
"src/**/*"
]
}

View file

@ -1,20 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import type * as markdownIt from 'markdown-it';
const emoji = require('markdown-it-emoji');
export async function activate(ctx: {
getRenderer: (id: string) => any
}) {
const markdownItRenderer = await ctx.getRenderer('markdownItRenderer');
if (!markdownItRenderer) {
throw new Error('Could not load markdownItRenderer');
}
markdownItRenderer.extendMarkdownIt((md: markdownIt.MarkdownIt) => {
return md.use(emoji);
});
}

View file

@ -1,4 +0,0 @@
{
"displayName": "Markdown Notebook math",
"description": "Provides rich language support for Markdown."
}

View file

@ -1,69 +0,0 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@iktakahiro/markdown-it-katex@https://github.com/mjbvz/markdown-it-katex.git":
version "4.0.1"
resolved "https://github.com/mjbvz/markdown-it-katex.git#2bf0b89c6c22ef0b585f55ccab66d1f7c5356bea"
dependencies:
katex "^0.13.0"
"@types/markdown-it@^0.0.0":
version "0.0.0"
resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-0.0.0.tgz#8f6acaa5e3245e275f684e95deb3e518d1c6ab16"
integrity sha1-j2rKpeMkXidfaE6V3rPlGNHGqxY=
argparse@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
commander@^6.0.0:
version "6.2.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
entities@~2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5"
integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==
katex@^0.13.0:
version "0.13.0"
resolved "https://registry.yarnpkg.com/katex/-/katex-0.13.0.tgz#62900e56c1ad8fdf7da23399e50d7a7b690b39ab"
integrity sha512-6cHbzbegYgS9vvVGuH8UA+o97X+ZshtboSqJJCdq7trBYzuD75JNwr7Ef606xkUjecPPhFnyB+afx1dVafielg==
dependencies:
commander "^6.0.0"
linkify-it@^3.0.1:
version "3.0.2"
resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.2.tgz#f55eeb8bc1d3ae754049e124ab3bb56d97797fb8"
integrity sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==
dependencies:
uc.micro "^1.0.1"
markdown-it-emoji@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/markdown-it-emoji/-/markdown-it-emoji-2.0.0.tgz#3164ad4c009efd946e98274f7562ad611089a231"
integrity sha512-39j7/9vP/CPCKbEI44oV8yoPJTpvfeReTn/COgRhSpNrjWF3PfP/JUxxB0hxV6ynOY8KH8Y8aX9NMDdo6z+6YQ==
markdown-it@^12.0.4:
version "12.0.4"
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.0.4.tgz#eec8247d296327eac3ba9746bdeec9cfcc751e33"
integrity sha512-34RwOXZT8kyuOJy25oJNJoulO8L0bTHYWXcdZBYZqFnjIy3NgjeoM3FmPXIOFQ26/lSHYMr8oc62B6adxXcb3Q==
dependencies:
argparse "^2.0.1"
entities "~2.1.0"
linkify-it "^3.0.1"
mdurl "^1.0.1"
uc.micro "^1.0.5"
mdurl@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e"
integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=
uc.micro@^1.0.1, uc.micro@^1.0.5:
version "1.0.6"
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac"
integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==

View file

@ -19,37 +19,4 @@ export function activate(context: vscode.ExtensionContext): any {
context.subscriptions.push(vscode.languages.registerCompletionItemProvider('php', new PHPCompletionItemProvider(), '>', '$'));
context.subscriptions.push(vscode.languages.registerHoverProvider('php', new PHPHoverProvider()));
context.subscriptions.push(vscode.languages.registerSignatureHelpProvider('php', new PHPSignatureHelpProvider(), '(', ','));
// need to set in the extension host as well as the completion provider uses it.
vscode.languages.setLanguageConfiguration('php', {
wordPattern: /(-?\d*\.\d\w*)|([^\-\`\~\!\@\#\%\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,
onEnterRules: [
{
// e.g. /** | */
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
afterText: /^\s*\*\/$/,
action: { indentAction: vscode.IndentAction.IndentOutdent, appendText: ' * ' }
},
{
// e.g. /** ...|
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
action: { indentAction: vscode.IndentAction.None, appendText: ' * ' }
},
{
// e.g. * ...|
beforeText: /^(\t|(\ \ ))*\ \*(\ ([^\*]|\*(?!\/))*)?$/,
action: { indentAction: vscode.IndentAction.None, appendText: '* ' }
},
{
// e.g. */|
beforeText: /^(\t|(\ \ ))*\ \*\/\s*$/,
action: { indentAction: vscode.IndentAction.None, removeText: 1 }
},
{
// e.g. *-----*/|
beforeText: /^(\t|(\ \ ))*\ \*[^/]*\*\/\s*$/,
action: { indentAction: vscode.IndentAction.None, removeText: 1 }
}
]
});
}
}

View file

@ -33,5 +33,49 @@
"start": "^\\s*(#|\/\/)region\\b",
"end": "^\\s*(#|\/\/)endregion\\b"
}
}
},
"wordPattern": "(-?\\d*\\.\\d\\w*)|([^\\-\\`\\~\\!\\@\\#\\%\\^\\&\\*\\(\\)\\=\\+\\[\\{\\]\\}\\\\\\|\\;\\:\\'\\\"\\,\\.\\<\\>\\/\\?\\s]+)",
"onEnterRules": [
{
// e.g. /** | */
"beforeText": "^\\s*\\/\\*\\*(?!\\/)([^\\*]|\\*(?!\\/))*$",
"afterText": "^\\s*\\*\\/$",
"action": {
"indent": "indentOutdent",
"appendText": " * "
}
},
{
// e.g. /** ...|
"beforeText": "^\\s*\\/\\*\\*(?!\\/)([^\\*]|\\*(?!\\/))*$",
"action": {
"indent": "none",
"appendText": " * "
}
},
{
// e.g. * ...|
"beforeText": "^(\\t|(\\ \\ ))*\\ \\*(\\ ([^\\*]|\\*(?!\\/))*)?$",
"action": {
"indent": "none",
"appendText": "* ",
},
},
{
// e.g. */|
"beforeText": "^(\\t|(\\ \\ ))*\\ \\*\\/\\s*$",
"action": {
"indent": "none",
"removeText": 1
},
},
{
// e.g. *-----*/|
"beforeText": "^(\\t|(\\ \\ ))*\\ \\*[^/]*\\*\\/\\s*$",
"action": {
"indent": "none",
"removeText": 1
}
}
]
}

View file

@ -27,5 +27,10 @@
"start": "^\\s*\\/\\*\\s*#region\\b\\s*(.*?)\\s*\\*\\/",
"end": "^\\s*\\/\\*\\s*#endregion\\b.*\\*\\/"
}
}
}
},
"indentationRules": {
"increaseIndentPattern": "(^.*\\{[^}]*$)",
"decreaseIndentPattern": "^\\s*\\}"
},
"wordPattern": "(#?-?\\d*\\.\\d\\w*%?)|(::?[\\w-]*(?=[^,{;]*[,{]))|(([@$#.!])?[\\w-?]+%?|[@#!$.])"
}

View file

@ -31,6 +31,7 @@ let nonBuiltInLanguages = { // { fileNames, extensions }
"ocaml": { extensions: ['ml', 'mli', 'mll', 'mly', 'eliom', 'eliomi'] },
"puppet": { extensions: ['puppet'] },
"r": { extensions: ['r', 'rhistory', 'rprofile', 'rt'] },
"rescript": { extensions: ['res', 'resi'] },
"sass": { extensions: ['sass'] },
"stylus": { extensions: ['styl'] },
"terraform": { extensions: ['tf', 'tfvars', 'hcl'] },

View file

@ -6,7 +6,7 @@
"git": {
"name": "seti-ui",
"repositoryUrl": "https://github.com/jesseweed/seti-ui",
"commitHash": "2b078f89a535a9f6dda47817bac01f02a4350078"
"commitHash": "e80b920f4268e5daf1f65183dae33297aa4d0d17"
}
},
"version": "0.1.0"

View file

@ -1142,351 +1142,367 @@
"fontCharacter": "\\E07C",
"fontColor": "#cc3e44"
},
"_rollup_light": {
"_rescript_light": {
"fontCharacter": "\\E07D",
"fontColor": "#b8383d"
},
"_rescript": {
"fontCharacter": "\\E07D",
"fontColor": "#cc3e44"
},
"_rescript_1_light": {
"fontCharacter": "\\E07D",
"fontColor": "#dd4b78"
},
"_rescript_1": {
"fontCharacter": "\\E07D",
"fontColor": "#f55385"
},
"_rollup_light": {
"fontCharacter": "\\E07E",
"fontColor": "#b8383d"
},
"_rollup": {
"fontCharacter": "\\E07D",
"fontCharacter": "\\E07E",
"fontColor": "#cc3e44"
},
"_ruby_light": {
"fontCharacter": "\\E07E",
"fontCharacter": "\\E07F",
"fontColor": "#b8383d"
},
"_ruby": {
"fontCharacter": "\\E07E",
"fontCharacter": "\\E07F",
"fontColor": "#cc3e44"
},
"_rust_light": {
"fontCharacter": "\\E07F",
"fontCharacter": "\\E080",
"fontColor": "#627379"
},
"_rust": {
"fontCharacter": "\\E07F",
"fontCharacter": "\\E080",
"fontColor": "#6d8086"
},
"_salesforce_light": {
"fontCharacter": "\\E080",
"fontCharacter": "\\E081",
"fontColor": "#498ba7"
},
"_salesforce": {
"fontCharacter": "\\E080",
"fontCharacter": "\\E081",
"fontColor": "#519aba"
},
"_sass_light": {
"fontCharacter": "\\E081",
"fontCharacter": "\\E082",
"fontColor": "#dd4b78"
},
"_sass": {
"fontCharacter": "\\E081",
"fontCharacter": "\\E082",
"fontColor": "#f55385"
},
"_sbt_light": {
"fontCharacter": "\\E082",
"fontCharacter": "\\E083",
"fontColor": "#498ba7"
},
"_sbt": {
"fontCharacter": "\\E082",
"fontCharacter": "\\E083",
"fontColor": "#519aba"
},
"_scala_light": {
"fontCharacter": "\\E083",
"fontCharacter": "\\E084",
"fontColor": "#b8383d"
},
"_scala": {
"fontCharacter": "\\E083",
"fontCharacter": "\\E084",
"fontColor": "#cc3e44"
},
"_shell_light": {
"fontCharacter": "\\E086",
"fontCharacter": "\\E087",
"fontColor": "#455155"
},
"_shell": {
"fontCharacter": "\\E086",
"fontCharacter": "\\E087",
"fontColor": "#4d5a5e"
},
"_slim_light": {
"fontCharacter": "\\E087",
"fontCharacter": "\\E088",
"fontColor": "#cc6d2e"
},
"_slim": {
"fontCharacter": "\\E087",
"fontCharacter": "\\E088",
"fontColor": "#e37933"
},
"_smarty_light": {
"fontCharacter": "\\E088",
"fontCharacter": "\\E089",
"fontColor": "#b7b73b"
},
"_smarty": {
"fontCharacter": "\\E088",
"fontCharacter": "\\E089",
"fontColor": "#cbcb41"
},
"_spring_light": {
"fontCharacter": "\\E089",
"fontCharacter": "\\E08A",
"fontColor": "#7fae42"
},
"_spring": {
"fontCharacter": "\\E089",
"fontCharacter": "\\E08A",
"fontColor": "#8dc149"
},
"_stylelint_light": {
"fontCharacter": "\\E08A",
"fontCharacter": "\\E08B",
"fontColor": "#bfc2c1"
},
"_stylelint": {
"fontCharacter": "\\E08A",
"fontCharacter": "\\E08B",
"fontColor": "#d4d7d6"
},
"_stylelint_1_light": {
"fontCharacter": "\\E08A",
"fontCharacter": "\\E08B",
"fontColor": "#455155"
},
"_stylelint_1": {
"fontCharacter": "\\E08A",
"fontCharacter": "\\E08B",
"fontColor": "#4d5a5e"
},
"_stylus_light": {
"fontCharacter": "\\E08B",
"fontCharacter": "\\E08C",
"fontColor": "#7fae42"
},
"_stylus": {
"fontCharacter": "\\E08B",
"fontCharacter": "\\E08C",
"fontColor": "#8dc149"
},
"_sublime_light": {
"fontCharacter": "\\E08C",
"fontCharacter": "\\E08D",
"fontColor": "#cc6d2e"
},
"_sublime": {
"fontCharacter": "\\E08C",
"fontCharacter": "\\E08D",
"fontColor": "#e37933"
},
"_svelte_light": {
"fontCharacter": "\\E08D",
"fontCharacter": "\\E08E",
"fontColor": "#b8383d"
},
"_svelte": {
"fontCharacter": "\\E08D",
"fontCharacter": "\\E08E",
"fontColor": "#cc3e44"
},
"_svg_light": {
"fontCharacter": "\\E08E",
"fontCharacter": "\\E08F",
"fontColor": "#9068b0"
},
"_svg": {
"fontCharacter": "\\E08E",
"fontCharacter": "\\E08F",
"fontColor": "#a074c4"
},
"_svg_1_light": {
"fontCharacter": "\\E08E",
"fontCharacter": "\\E08F",
"fontColor": "#498ba7"
},
"_svg_1": {
"fontCharacter": "\\E08E",
"fontCharacter": "\\E08F",
"fontColor": "#519aba"
},
"_swift_light": {
"fontCharacter": "\\E08F",
"fontCharacter": "\\E090",
"fontColor": "#cc6d2e"
},
"_swift": {
"fontCharacter": "\\E08F",
"fontCharacter": "\\E090",
"fontColor": "#e37933"
},
"_terraform_light": {
"fontCharacter": "\\E090",
"fontCharacter": "\\E091",
"fontColor": "#9068b0"
},
"_terraform": {
"fontCharacter": "\\E090",
"fontCharacter": "\\E091",
"fontColor": "#a074c4"
},
"_tex_light": {
"fontCharacter": "\\E091",
"fontCharacter": "\\E092",
"fontColor": "#498ba7"
},
"_tex": {
"fontCharacter": "\\E091",
"fontCharacter": "\\E092",
"fontColor": "#519aba"
},
"_tex_1_light": {
"fontCharacter": "\\E091",
"fontCharacter": "\\E092",
"fontColor": "#b7b73b"
},
"_tex_1": {
"fontCharacter": "\\E091",
"fontCharacter": "\\E092",
"fontColor": "#cbcb41"
},
"_tex_2_light": {
"fontCharacter": "\\E091",
"fontCharacter": "\\E092",
"fontColor": "#cc6d2e"
},
"_tex_2": {
"fontCharacter": "\\E091",
"fontCharacter": "\\E092",
"fontColor": "#e37933"
},
"_tex_3_light": {
"fontCharacter": "\\E091",
"fontCharacter": "\\E092",
"fontColor": "#bfc2c1"
},
"_tex_3": {
"fontCharacter": "\\E091",
"fontCharacter": "\\E092",
"fontColor": "#d4d7d6"
},
"_todo": {
"fontCharacter": "\\E093"
"fontCharacter": "\\E094"
},
"_tsconfig_light": {
"fontCharacter": "\\E094",
"fontCharacter": "\\E095",
"fontColor": "#498ba7"
},
"_tsconfig": {
"fontCharacter": "\\E094",
"fontCharacter": "\\E095",
"fontColor": "#519aba"
},
"_twig_light": {
"fontCharacter": "\\E095",
"fontCharacter": "\\E096",
"fontColor": "#7fae42"
},
"_twig": {
"fontCharacter": "\\E095",
"fontCharacter": "\\E096",
"fontColor": "#8dc149"
},
"_typescript_light": {
"fontCharacter": "\\E096",
"fontCharacter": "\\E097",
"fontColor": "#498ba7"
},
"_typescript": {
"fontCharacter": "\\E096",
"fontCharacter": "\\E097",
"fontColor": "#519aba"
},
"_typescript_1_light": {
"fontCharacter": "\\E096",
"fontCharacter": "\\E097",
"fontColor": "#b7b73b"
},
"_typescript_1": {
"fontCharacter": "\\E096",
"fontCharacter": "\\E097",
"fontColor": "#cbcb41"
},
"_vala_light": {
"fontCharacter": "\\E097",
"fontCharacter": "\\E098",
"fontColor": "#627379"
},
"_vala": {
"fontCharacter": "\\E097",
"fontCharacter": "\\E098",
"fontColor": "#6d8086"
},
"_video_light": {
"fontCharacter": "\\E098",
"fontCharacter": "\\E099",
"fontColor": "#dd4b78"
},
"_video": {
"fontCharacter": "\\E098",
"fontCharacter": "\\E099",
"fontColor": "#f55385"
},
"_vue_light": {
"fontCharacter": "\\E099",
"fontCharacter": "\\E09A",
"fontColor": "#7fae42"
},
"_vue": {
"fontCharacter": "\\E099",
"fontCharacter": "\\E09A",
"fontColor": "#8dc149"
},
"_wasm_light": {
"fontCharacter": "\\E09A",
"fontCharacter": "\\E09B",
"fontColor": "#9068b0"
},
"_wasm": {
"fontCharacter": "\\E09A",
"fontCharacter": "\\E09B",
"fontColor": "#a074c4"
},
"_wat_light": {
"fontCharacter": "\\E09B",
"fontCharacter": "\\E09C",
"fontColor": "#9068b0"
},
"_wat": {
"fontCharacter": "\\E09B",
"fontCharacter": "\\E09C",
"fontColor": "#a074c4"
},
"_webpack_light": {
"fontCharacter": "\\E09C",
"fontCharacter": "\\E09D",
"fontColor": "#498ba7"
},
"_webpack": {
"fontCharacter": "\\E09C",
"fontCharacter": "\\E09D",
"fontColor": "#519aba"
},
"_wgt_light": {
"fontCharacter": "\\E09D",
"fontCharacter": "\\E09E",
"fontColor": "#498ba7"
},
"_wgt": {
"fontCharacter": "\\E09D",
"fontCharacter": "\\E09E",
"fontColor": "#519aba"
},
"_windows_light": {
"fontCharacter": "\\E09E",
"fontCharacter": "\\E09F",
"fontColor": "#498ba7"
},
"_windows": {
"fontCharacter": "\\E09E",
"fontCharacter": "\\E09F",
"fontColor": "#519aba"
},
"_word_light": {
"fontCharacter": "\\E09F",
"fontCharacter": "\\E0A0",
"fontColor": "#498ba7"
},
"_word": {
"fontCharacter": "\\E09F",
"fontCharacter": "\\E0A0",
"fontColor": "#519aba"
},
"_xls_light": {
"fontCharacter": "\\E0A0",
"fontCharacter": "\\E0A1",
"fontColor": "#7fae42"
},
"_xls": {
"fontCharacter": "\\E0A0",
"fontCharacter": "\\E0A1",
"fontColor": "#8dc149"
},
"_xml_light": {
"fontCharacter": "\\E0A1",
"fontCharacter": "\\E0A2",
"fontColor": "#cc6d2e"
},
"_xml": {
"fontCharacter": "\\E0A1",
"fontCharacter": "\\E0A2",
"fontColor": "#e37933"
},
"_yarn_light": {
"fontCharacter": "\\E0A2",
"fontCharacter": "\\E0A3",
"fontColor": "#498ba7"
},
"_yarn": {
"fontCharacter": "\\E0A2",
"fontCharacter": "\\E0A3",
"fontColor": "#519aba"
},
"_yml_light": {
"fontCharacter": "\\E0A3",
"fontCharacter": "\\E0A4",
"fontColor": "#9068b0"
},
"_yml": {
"fontCharacter": "\\E0A3",
"fontCharacter": "\\E0A4",
"fontColor": "#a074c4"
},
"_zip_light": {
"fontCharacter": "\\E0A4",
"fontCharacter": "\\E0A5",
"fontColor": "#b8383d"
},
"_zip": {
"fontCharacter": "\\E0A4",
"fontCharacter": "\\E0A5",
"fontColor": "#cc3e44"
},
"_zip_1_light": {
"fontCharacter": "\\E0A4",
"fontCharacter": "\\E0A5",
"fontColor": "#627379"
},
"_zip_1": {
"fontCharacter": "\\E0A4",
"fontCharacter": "\\E0A5",
"fontColor": "#6d8086"
}
},
@ -1571,7 +1587,6 @@
"jinja2": "_jinja",
"kt": "_kotlin",
"kts": "_kotlin",
"dart": "_dart",
"liquid": "_liquid",
"ls": "_livescript",
"argdown": "_argdown",
@ -1611,6 +1626,8 @@
"spec.tsx": "_react_2",
"test.tsx": "_react_2",
"re": "_reasonml",
"res": "_rescript",
"resi": "_rescript_1",
"r": "_R",
"rmd": "_R",
"erb": "_html_erb",
@ -1783,6 +1800,7 @@
"cuda-cpp": "_cu",
"csharp": "_c-sharp",
"css": "_css",
"dart": "_dart",
"dockerfile": "_docker",
"ignore": "_git",
"fsharp": "_f-sharp",
@ -1836,6 +1854,7 @@
"mustache": "_mustache",
"nunjucks": "_nunjucks",
"ocaml": "_ocaml",
"rescript": "_rescript",
"sass": "_sass",
"stylus": "_stylus",
"terraform": "_terraform",
@ -1927,7 +1946,6 @@
"jinja2": "_jinja_light",
"kt": "_kotlin_light",
"kts": "_kotlin_light",
"dart": "_dart_light",
"liquid": "_liquid_light",
"ls": "_livescript_light",
"argdown": "_argdown_light",
@ -1967,6 +1985,8 @@
"spec.tsx": "_react_2_light",
"test.tsx": "_react_2_light",
"re": "_reasonml_light",
"res": "_rescript_light",
"resi": "_rescript_1_light",
"r": "_R_light",
"rmd": "_R_light",
"erb": "_html_erb_light",
@ -2078,6 +2098,7 @@
"cuda-cpp": "_cu_light",
"csharp": "_c-sharp_light",
"css": "_css_light",
"dart": "_dart_light",
"dockerfile": "_docker_light",
"ignore": "_git_light",
"fsharp": "_f-sharp_light",
@ -2131,6 +2152,7 @@
"mustache": "_mustache_light",
"nunjucks": "_nunjucks_light",
"ocaml": "_ocaml_light",
"rescript": "_rescript_light",
"sass": "_sass_light",
"stylus": "_stylus_light",
"terraform": "_terraform_light",
@ -2200,5 +2222,5 @@
"npm-debug.log": "_npm_ignored_light"
}
},
"version": "https://github.com/jesseweed/seti-ui/commit/2b078f89a535a9f6dda47817bac01f02a4350078"
"version": "https://github.com/jesseweed/seti-ui/commit/e80b920f4268e5daf1f65183dae33297aa4d0d17"
}

View file

@ -1,11 +1,13 @@
{
"compilerOptions": {
"target": "es2018",
"target": "es2019",
"lib": [
"es2018"
"es2019"
],
"module": "commonjs",
"strict": true,
"strictOptionalProperties": false,
"useUnknownInCatchVariables": false,
"alwaysStrict": true,
"noImplicitAny": true,
"noImplicitReturns": true,

View file

@ -91,7 +91,7 @@ function fromProtocolCallHierarchyItem(item: Proto.CallHierarchyItem): vscode.Ca
);
const kindModifiers = item.kindModifiers ? parseKindModifier(item.kindModifiers) : undefined;
if (kindModifiers?.has(PConst.KindModifiers.depreacted)) {
if (kindModifiers?.has(PConst.KindModifiers.deprecated)) {
result.tags = [vscode.SymbolTag.Deprecated];
}
return result;

View file

@ -121,7 +121,7 @@ class MyCompletionItem extends vscode.CompletionItem {
}
this.label += '?';
}
if (kindModifiers.has(PConst.KindModifiers.depreacted)) {
if (kindModifiers.has(PConst.KindModifiers.deprecated)) {
this.tags = [vscode.CompletionItemTag.Deprecated];
}

View file

@ -109,7 +109,7 @@ class TypeScriptDocumentSymbolProvider implements vscode.DocumentSymbolProvider
const kindModifiers = parseKindModifier(item.kindModifiers);
if (kindModifiers.has(PConst.KindModifiers.depreacted)) {
if (kindModifiers.has(PConst.KindModifiers.deprecated)) {
symbolInfo.tags = [vscode.SymbolTag.Deprecated];
}

View file

@ -97,7 +97,7 @@ class TypeScriptWorkspaceSymbolProvider implements vscode.WorkspaceSymbolProvide
item.containerName || '',
typeConverters.Location.fromTextSpan(this.client.toResource(item.file), item));
const kindModifiers = item.kindModifiers ? parseKindModifier(item.kindModifiers) : undefined;
if (kindModifiers?.has(PConst.KindModifiers.depreacted)) {
if (kindModifiers?.has(PConst.KindModifiers.deprecated)) {
info.tags = [vscode.SymbolTag.Deprecated];
}
return info;

View file

@ -45,7 +45,7 @@ export class DiagnosticCategory {
export class KindModifiers {
public static readonly optional = 'optional';
public static readonly depreacted = 'deprecated';
public static readonly deprecated = 'deprecated';
public static readonly color = 'color';
public static readonly dtsFile = '.d.ts';

View file

@ -703,7 +703,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
if (isWeb()) {
// On web, treat absolute paths as pointing to standard lib files
if (filepath.startsWith('/')) {
return vscode.Uri.joinPath(this.context.extensionUri, 'node_modules', 'typescript', 'lib', filepath.slice(1));
return vscode.Uri.joinPath(this.context.extensionUri, 'dist', 'browser', 'typescript', filepath.slice(1));
}
}

View file

@ -38,6 +38,7 @@ suite('Notebook Document', function () {
};
const disposables: vscode.Disposable[] = [];
const testDisposables: vscode.Disposable[] = [];
suiteTeardown(async function () {
utils.assertNoRpc();
@ -47,6 +48,11 @@ suite('Notebook Document', function () {
disposables.length = 0;
});
teardown(async function () {
utils.disposeAll(testDisposables);
testDisposables.length = 0;
});
suiteSetup(function () {
disposables.push(vscode.workspace.registerNotebookContentProvider('notebook.nbdtest', complexContentProvider));
disposables.push(vscode.workspace.registerNotebookSerializer('notebook.nbdserializer', simpleContentProvider));
@ -277,6 +283,37 @@ suite('Notebook Document', function () {
assert.strictEqual(data.changes[0].items[1], document.cellAt(1));
});
test('workspace edit API (replaceMetadata)', async function () {
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
const document = await vscode.workspace.openNotebookDocument(uri);
const edit = new vscode.WorkspaceEdit();
edit.replaceNotebookCellMetadata(document.uri, 0, { inputCollapsed: true });
const success = await vscode.workspace.applyEdit(edit);
assert.strictEqual(success, true);
assert.strictEqual(document.cellAt(0).metadata.inputCollapsed, true);
});
test('workspace edit API (replaceMetadata, event)', async function () {
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
const document = await vscode.workspace.openNotebookDocument(uri);
const edit = new vscode.WorkspaceEdit();
const event = utils.asPromise<vscode.NotebookCellMetadataChangeEvent>(vscode.notebooks.onDidChangeCellMetadata);
edit.replaceNotebookCellMetadata(document.uri, 0, { inputCollapsed: true });
const success = await vscode.workspace.applyEdit(edit);
assert.strictEqual(success, true);
const data = await event;
// check document
assert.strictEqual(document.cellAt(0).metadata.inputCollapsed, true);
// check event data
assert.strictEqual(data.document === document, true);
assert.strictEqual(data.cell.index, 0);
});
test('document save API', async function () {
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
const notebook = await vscode.workspace.openNotebookDocument(uri);
@ -372,4 +409,23 @@ suite('Notebook Document', function () {
await document.save();
assert.strictEqual(document.isDirty, false);
});
test('onDidOpenNotebookDocument - emit event only once when opened in two editors', async function () {
let counter = 0;
testDisposables.push(vscode.workspace.onDidOpenNotebookDocument(() => {
counter++;
}));
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
const notebook = await vscode.workspace.openNotebookDocument(uri);
assert.strictEqual(counter, 1);
await vscode.window.showNotebookDocument(notebook, { viewColumn: vscode.ViewColumn.Active });
assert.strictEqual(counter, 1);
assert.strictEqual(vscode.window.visibleNotebookEditors.length, 1);
await vscode.window.showNotebookDocument(notebook, { viewColumn: vscode.ViewColumn.Beside });
assert.strictEqual(counter, 1);
assert.strictEqual(vscode.window.visibleNotebookEditors.length, 2);
});
});

View file

@ -21,6 +21,7 @@ suite('Notebook Editor', function () {
};
const disposables: vscode.Disposable[] = [];
const testDisposables: vscode.Disposable[] = [];
suiteTeardown(async function () {
utils.assertNoRpc();
@ -38,6 +39,10 @@ suite('Notebook Editor', function () {
disposables.push(vscode.workspace.registerNotebookSerializer('notebook.nbdtest', contentSerializer));
});
teardown(async function () {
utils.disposeAll(testDisposables);
testDisposables.length = 0;
});
test('showNotebookDocment', async function () {
@ -74,4 +79,48 @@ suite('Notebook Editor', function () {
assert.ok(await openedEditor);
assert.strictEqual(editor.document.uri.toString(), resource.toString());
});
test('Active/Visible Editor', async function () {
const firstEditorOpen = utils.asPromise(vscode.window.onDidChangeActiveNotebookEditor);
const resource = await utils.createRandomFile(undefined, undefined, '.nbdtest');
const firstEditor = await vscode.window.showNotebookDocument(resource);
await firstEditorOpen;
assert.strictEqual(vscode.window.activeNotebookEditor, firstEditor);
assert.strictEqual(vscode.window.visibleNotebookEditors.includes(firstEditor), true);
const secondEditor = await vscode.window.showNotebookDocument(resource, { viewColumn: vscode.ViewColumn.Beside });
assert.strictEqual(secondEditor === vscode.window.activeNotebookEditor, true);
assert.notStrictEqual(firstEditor, secondEditor);
assert.strictEqual(vscode.window.visibleNotebookEditors.includes(secondEditor), true);
assert.strictEqual(vscode.window.visibleNotebookEditors.includes(firstEditor), true);
assert.strictEqual(vscode.window.visibleNotebookEditors.length, 2);
});
test('Notebook Editor Event - onDidChangeVisibleNotebookEditors on open/close', async function () {
const openedEditor = utils.asPromise(vscode.window.onDidChangeVisibleNotebookEditors);
const resource = await utils.createRandomFile(undefined, undefined, '.nbdtest');
await vscode.window.showNotebookDocument(resource);
assert.ok(await openedEditor);
const firstEditorClose = utils.asPromise(vscode.window.onDidChangeVisibleNotebookEditors);
await utils.closeAllEditors();
await firstEditorClose;
});
test('Notebook Editor Event - onDidChangeVisibleNotebookEditors on two editor groups', async function () {
const resource = await utils.createRandomFile(undefined, undefined, '.nbdtest');
let count = 0;
testDisposables.push(vscode.window.onDidChangeVisibleNotebookEditors(() => {
count = vscode.window.visibleNotebookEditors.length;
}));
await vscode.window.showNotebookDocument(resource, { viewColumn: vscode.ViewColumn.Active });
assert.strictEqual(count, 1);
await vscode.window.showNotebookDocument(resource, { viewColumn: vscode.ViewColumn.Beside });
assert.strictEqual(count, 2);
await utils.closeAllEditors();
assert.strictEqual(count, 0);
});
});

View file

@ -1,7 +1,7 @@
{
"name": "code-oss-dev",
"version": "1.58.0",
"distro": "33b93a117b5bff11c3fe9d4a6fa49e9895d38c08",
"distro": "3f43781e788d694f33746808cc5182852222f935",
"author": {
"name": "Microsoft Corporation"
},
@ -103,7 +103,8 @@
"@types/minimist": "^1.2.1",
"@types/mocha": "^8.2.0",
"@types/node": "14.x",
"@types/sinon": "^1.16.36",
"@types/sinon": "^10.0.2",
"@types/sinon-test": "^2.4.2",
"@types/trusted-types": "^1.0.6",
"@types/vscode-windows-registry": "^1.0.0",
"@types/webpack": "^4.41.25",
@ -183,20 +184,21 @@
"rcedit": "^1.1.0",
"request": "^2.85.0",
"rimraf": "^2.2.8",
"sinon": "^1.17.2",
"sinon": "^11.1.1",
"sinon-test": "^3.1.0",
"source-map": "0.6.1",
"source-map-support": "^0.3.2",
"style-loader": "^1.0.0",
"ts-loader": "^6.2.1",
"tsec": "0.1.4",
"typescript": "^4.4.0-dev.20210528",
"typescript": "^4.4.0-dev.20210607",
"typescript-formatter": "7.1.0",
"underscore": "^1.12.1",
"vinyl": "^2.0.0",
"vinyl-fs": "^3.0.0",
"vscode-debugprotocol": "1.47.0",
"vscode-nls-dev": "^3.3.1",
"vscode-telemetry-extractor": "^1.7.0",
"vscode-telemetry-extractor": "^1.8.0",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12",
"webpack-stream": "^5.2.1",

View file

@ -208,9 +208,9 @@ get-uri@^3.0.2:
ftp "^0.3.10"
glob-parent@~5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2"
integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
is-glob "^4.0.1"

View file

@ -423,9 +423,6 @@ async function handleRoot(req, res) {
const webConfigJSON = {
folderUri: folderUri,
staticExtensions,
settingsSyncOptions: {
enabled: args['enable-sync']
},
webWorkerExtensionHostIframeSrc: `${SCHEME}://${secondaryHost}/static/out/vs/workbench/services/extensions/worker/httpWebWorkerExtensionHostIframe.html`
};
if (args['wrap-iframe']) {

View file

@ -71,7 +71,12 @@ function code-wsl()
fi
}
if ! [ -z ${IN_WSL+x} ]; then
if [ "$IN_WSL" == "true" ] && [ -z "$DISPLAY" ]; then
code-wsl "$@"
elif [ -f /mnt/wslg/versions.txt ]; then
code --disable-gpu "$@"
else
code "$@"
fi
code "$@"
exit $?

View file

@ -46,7 +46,7 @@ if %errorlevel% neq 0 exit /b %errorlevel%
:: Tests in the extension host
set ALL_PLATFORMS_API_TESTS_EXTRA_ARGS=--disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --no-cached-data --disable-updates --disable-keytar --disable-extensions --disable-workspace-trust --user-data-dir=%VSCODEUSERDATADIR%
set ALL_PLATFORMS_API_TESTS_EXTRA_ARGS=--disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --no-sandbox --no-cached-data --disable-updates --disable-keytar --disable-extensions --disable-workspace-trust --user-data-dir=%VSCODEUSERDATADIR%
call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\singlefolder-tests %ALL_PLATFORMS_API_TESTS_EXTRA_ARGS%
if %errorlevel% neq 0 exit /b %errorlevel%

View file

@ -43,11 +43,11 @@ exports.load = function (entrypoint, onLoad, onError) {
return;
}
// cached data config
if (process.env['VSCODE_NODE_CACHED_DATA_DIR']) {
// code cache config
if (process.env['VSCODE_CODE_CACHE_PATH']) {
loader.config({
nodeCachedData: {
path: process.env['VSCODE_NODE_CACHED_DATA_DIR'],
path: process.env['VSCODE_CODE_CACHE_PATH'],
seed: entrypoint
}
});

View file

@ -147,10 +147,10 @@
loaderConfig.amdModulesPattern = /^vs\//;
}
// Cached data config
if (configuration.nodeCachedDataDir) {
// Cached data config (node.js loading only)
if (!useCustomProtocol && configuration.codeCachePath) {
loaderConfig.nodeCachedData = {
path: configuration.nodeCachedDataDir,
path: configuration.codeCachePath,
seed: modulePaths.join('')
};
}

View file

@ -40,6 +40,9 @@ const args = parseCLIArgs();
const userDataPath = getUserDataPath(args);
app.setPath('userData', userDataPath);
// Resolve code cache path
const codeCachePath = getCodeCachePath();
// Configure static command line arguments
const argvConfig = configureCommandlineSwitchesSync(args);
@ -71,9 +74,6 @@ protocol.registerSchemesAsPrivileged([
// Global app listeners
registerListeners();
// Cached data
const nodeCachedDataDir = getNodeCachedDir();
/**
* Support user defined locale: load it early before app('ready')
* to have more things running in parallel.
@ -108,14 +108,14 @@ app.once('ready', function () {
/**
* Main startup routine
*
* @param {string | undefined} cachedDataDir
* @param {string | undefined} codeCachePath
* @param {NLSConfiguration} nlsConfig
*/
function startup(cachedDataDir, nlsConfig) {
function startup(codeCachePath, nlsConfig) {
nlsConfig._languagePackSupport = true;
process.env['VSCODE_NLS_CONFIG'] = JSON.stringify(nlsConfig);
process.env['VSCODE_NODE_CACHED_DATA_DIR'] = cachedDataDir || '';
process.env['VSCODE_CODE_CACHE_PATH'] = codeCachePath || '';
// Load main in AMD
perf.mark('code/willLoadMainBundle');
@ -128,9 +128,9 @@ async function onReady() {
perf.mark('code/mainAppReady');
try {
const [cachedDataDir, nlsConfig] = await Promise.all([nodeCachedDataDir.ensureExists(), resolveNlsConfiguration()]);
const [, nlsConfig] = await Promise.all([mkdirpIgnoreError(codeCachePath), resolveNlsConfiguration()]);
startup(cachedDataDir, nlsConfig);
startup(codeCachePath, nlsConfig);
} catch (error) {
console.error(error);
}
@ -174,7 +174,7 @@ function configureCommandlineSwitchesSync(cliArgs) {
// Read argv config
const argvConfig = readArgvConfigSync();
let browserCodeLoadingStrategy = undefined;
let browserCodeLoadingStrategy = typeof codeCachePath === 'string' ? 'bypassHeatCheck' : 'none';
Object.keys(argvConfig).forEach(argvKey => {
const argvValue = argvConfig[argvKey];
@ -499,46 +499,28 @@ function registerListeners() {
}
/**
* @returns {{ ensureExists: () => Promise<string | undefined> }}
* @returns {string | undefined} the location to use for the code cache
* or `undefined` if disabled.
*/
function getNodeCachedDir() {
return new class {
function getCodeCachePath() {
constructor() {
this.value = this.compute();
}
// explicitly disabled via CLI args
if (process.argv.indexOf('--no-cached-data') > 0) {
return undefined;
}
async ensureExists() {
if (typeof this.value === 'string') {
try {
await mkdirp(this.value);
// running out of sources
if (process.env['VSCODE_DEV']) {
return undefined;
}
return this.value;
} catch (error) {
// ignore
}
}
}
// require commit id
const commit = product.commit;
if (!commit) {
return undefined;
}
compute() {
if (process.argv.indexOf('--no-cached-data') > 0) {
return undefined;
}
// IEnvironmentService.isBuilt
if (process.env['VSCODE_DEV']) {
return undefined;
}
// find commit id
const commit = product.commit;
if (!commit) {
return undefined;
}
return path.join(userDataPath, 'CachedData', commit);
}
};
return path.join(userDataPath, 'CachedData', commit);
}
/**
@ -553,6 +535,24 @@ function mkdirp(dir) {
});
}
/**
* @param {string | undefined} dir
* @returns {Promise<string | undefined>}
*/
async function mkdirpIgnoreError(dir) {
if (typeof dir === 'string') {
try {
await mkdirp(dir);
return dir;
} catch (error) {
// ignore
}
}
return undefined;
}
//#region NLS Support
/**

View file

@ -8,6 +8,8 @@
"noUnusedLocals": true,
"allowUnreachableCode": false,
"strict": true,
"strictOptionalProperties": false,
"useUnknownInCatchVariables": false,
"forceConsistentCasingInFileNames": true,
"baseUrl": ".",
"paths": {

View file

@ -193,6 +193,24 @@ export class ActionRunner extends Disposable implements IActionRunner {
export class Separator extends Action {
/**
* Joins all non-empty lists of actions with separators.
*/
public static join(...actionLists: readonly IAction[][]) {
let out: IAction[] = [];
for (const list of actionLists) {
if (!list.length) {
// skip
} else if (out.length) {
out = [...out, new Separator(), ...list];
} else {
out = list;
}
}
return out;
}
static readonly ID = 'vs.actions.separator';
constructor(label?: string) {

View file

@ -30,7 +30,7 @@ export namespace Iterable {
return iterable[Symbol.iterator]().next().value;
}
export function some<T>(iterable: Iterable<T>, predicate: (t: T) => boolean): boolean {
export function some<T>(iterable: Iterable<T>, predicate: (t: T) => unknown): boolean {
for (const element of iterable) {
if (predicate(element)) {
return true;

View file

@ -39,7 +39,7 @@ export enum RimRafMode {
* - `MOVE`: faster variant that first moves the target to temp dir and then
* deletes it in the background without waiting for that to finish.
*/
export async function rimraf(path: string, mode = RimRafMode.UNLINK): Promise<void> {
async function rimraf(path: string, mode = RimRafMode.UNLINK): Promise<void> {
if (isRootOrDriveLetter(path)) {
throw new Error('rimraf - will refuse to recursively delete root');
}
@ -179,7 +179,7 @@ function handleDirectoryChildren(children: (string | IDirent)[]): (string | IDir
* A convinience method to read all children of a path that
* are directories.
*/
export async function readDirsInDir(dirPath: string): Promise<string[]> {
async function readDirsInDir(dirPath: string): Promise<string[]> {
const children = await readdir(dirPath);
const directories: string[] = [];
@ -474,7 +474,7 @@ function ensureWriteOptions(options?: IWriteFileOptions): IEnsuredWriteFileOptio
* - updates the `mtime` of the `source` after the operation
* - allows to move across multiple disks
*/
export async function move(source: string, target: string): Promise<void> {
async function move(source: string, target: string): Promise<void> {
if (source === target) {
return; // simulate node.js behaviour here and do a no-op if paths match
}
@ -536,7 +536,7 @@ interface ICopyPayload {
* links should be handled when encountered. Set to
* `false` to not preserve them and `true` otherwise.
*/
export async function copy(source: string, target: string, options: { preserveSymlinks: boolean }): Promise<void> {
async function copy(source: string, target: string, options: { preserveSymlinks: boolean }): Promise<void> {
return doCopy(source, target, { root: { source, target }, options, handledSourcePaths: new Set<string>() });
}
@ -698,8 +698,15 @@ export const Promises = new class {
}
get readdir() { return readdir; }
get readDirsInDir() { return readDirsInDir; }
get writeFile() { return writeFile; }
get rm() { return rimraf; }
get move() { return move; }
get copy() { return copy; }
//#endregion
};

View file

@ -8,7 +8,7 @@ import * as path from 'vs/base/common/path';
import { createWriteStream, WriteStream } from 'fs';
import { Readable } from 'stream';
import { Sequencer, createCancelablePromise } from 'vs/base/common/async';
import { Promises, rimraf } from 'vs/base/node/pfs';
import { Promises } from 'vs/base/node/pfs';
import { open as _openZip, Entry, ZipFile } from 'yauzl';
import * as yazl from 'yazl';
import { CancellationToken } from 'vs/base/common/cancellation';
@ -218,7 +218,7 @@ export function extract(zipPath: string, targetPath: string, options: IExtractOp
let promise = openZip(zipPath, true);
if (options.overwrite) {
promise = promise.then(zipfile => rimraf(targetPath).then(() => zipfile));
promise = promise.then(zipfile => Promises.rm(targetPath).then(() => zipfile));
}
return promise.then(zipfile => extractZip(zipfile, targetPath, { sourcePathRegex }, token));

View file

@ -46,7 +46,7 @@ export interface ISandboxConfiguration {
zoomLevel?: number;
/**
* @deprecated to be removed soon
* Location of V8 code cache.
*/
nodeCachedDataDir?: string;
codeCachePath?: string;
}

View file

@ -8,7 +8,7 @@ import { Event } from 'vs/base/common/event';
import { timeout } from 'vs/base/common/async';
import { mapToString, setToString } from 'vs/base/common/map';
import { basename } from 'vs/base/common/path';
import { copy, Promises } from 'vs/base/node/pfs';
import { Promises } from 'vs/base/node/pfs';
import { IStorageDatabase, IStorageItemsChangeEvent, IUpdateRequest } from 'vs/base/parts/storage/common/storage';
interface IDatabaseConnection {
@ -216,7 +216,7 @@ export class SQLiteStorageDatabase implements IStorageDatabase {
private backup(): Promise<void> {
const backupPath = this.toBackupPath(this.path);
return copy(this.path, backupPath, { preserveSymlinks: false });
return Promises.copy(this.path, backupPath, { preserveSymlinks: false });
}
private toBackupPath(path: string): string {

View file

@ -8,7 +8,7 @@ import { Storage, IStorageDatabase, IStorageItemsChangeEvent } from 'vs/base/par
import { join } from 'vs/base/common/path';
import { tmpdir } from 'os';
import { strictEqual, ok } from 'assert';
import { rimraf, Promises } from 'vs/base/node/pfs';
import { Promises } from 'vs/base/node/pfs';
import { timeout } from 'vs/base/common/async';
import { Event, Emitter } from 'vs/base/common/event';
import { isWindows } from 'vs/base/common/platform';
@ -26,7 +26,7 @@ flakySuite('Storage Library', function () {
});
teardown(function () {
return rimraf(testDir);
return Promises.rm(testDir);
});
test('basics', async () => {
@ -299,7 +299,7 @@ flakySuite('SQLite Storage Library', function () {
});
teardown(function () {
return rimraf(testdir);
return Promises.rm(testdir);
});
async function testDBBasics(path: string, logError?: (error: Error | string) => void) {

View file

@ -161,7 +161,7 @@ suite('Decorators', () => {
clock.tick(200);
assert.deepStrictEqual(spy.args, [[1], [5]]);
spy.reset();
spy.resetHistory();
t.report(4);
t.report(5);

View file

@ -21,7 +21,7 @@ suite('Processes', () => {
VSCODE_NLS_CONFIG: 'x',
VSCODE_PORTABLE: 'x',
VSCODE_PID: 'x',
VSCODE_NODE_CACHED_DATA_DIR: 'x',
VSCODE_CODE_CACHE_PATH: 'x',
VSCODE_NEW_VAR: 'x',
GDK_PIXBUF_MODULE_FILE: 'x',
GDK_PIXBUF_MODULEDIR: 'x',

View file

@ -6,7 +6,7 @@
import { checksum } from 'vs/base/node/crypto';
import { join } from 'vs/base/common/path';
import { tmpdir } from 'os';
import { Promises, rimraf } from 'vs/base/node/pfs';
import { Promises } from 'vs/base/node/pfs';
import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils';
flakySuite('Crypto', () => {
@ -20,7 +20,7 @@ flakySuite('Crypto', () => {
});
teardown(function () {
return rimraf(testDir);
return Promises.rm(testDir);
});
test('checksum', async () => {

View file

@ -5,7 +5,7 @@
import * as assert from 'assert';
import { tmpdir } from 'os';
import { Promises, rimraf } from 'vs/base/node/pfs';
import { Promises } from 'vs/base/node/pfs';
import { realcaseSync, realpath, realpathSync } from 'vs/base/node/extpath';
import { flakySuite, getRandomTestPath } from 'vs/base/test/node/testUtils';
@ -19,7 +19,7 @@ flakySuite('Extpath', () => {
});
teardown(() => {
return rimraf(testDir);
return Promises.rm(testDir);
});
test('realcase', async () => {

View file

@ -8,7 +8,7 @@ import * as fs from 'fs';
import { tmpdir } from 'os';
import { join, sep } from 'vs/base/common/path';
import { generateUuid } from 'vs/base/common/uuid';
import { copy, move, Promises, readDirsInDir, rimraf, RimRafMode, rimrafSync, SymlinkSupport, writeFileSync } from 'vs/base/node/pfs';
import { Promises, RimRafMode, rimrafSync, SymlinkSupport, writeFileSync } from 'vs/base/node/pfs';
import { timeout } from 'vs/base/common/async';
import { canNormalize } from 'vs/base/common/normalization';
import { VSBuffer } from 'vs/base/common/buffer';
@ -26,7 +26,7 @@ flakySuite('PFS', function () {
});
teardown(() => {
return rimraf(testDir);
return Promises.rm(testDir);
});
test('writeFile', async () => {
@ -77,7 +77,7 @@ flakySuite('PFS', function () {
fs.writeFileSync(join(testDir, 'somefile.txt'), 'Contents');
fs.writeFileSync(join(testDir, 'someOtherFile.txt'), 'Contents');
await rimraf(testDir);
await Promises.rm(testDir);
assert.ok(!fs.existsSync(testDir));
});
@ -85,7 +85,7 @@ flakySuite('PFS', function () {
fs.writeFileSync(join(testDir, 'somefile.txt'), 'Contents');
fs.writeFileSync(join(testDir, 'someOtherFile.txt'), 'Contents');
await rimraf(testDir, RimRafMode.MOVE);
await Promises.rm(testDir, RimRafMode.MOVE);
assert.ok(!fs.existsSync(testDir));
});
@ -95,7 +95,7 @@ flakySuite('PFS', function () {
fs.mkdirSync(join(testDir, 'somefolder'));
fs.writeFileSync(join(testDir, 'somefolder', 'somefile.txt'), 'Contents');
await rimraf(testDir);
await Promises.rm(testDir);
assert.ok(!fs.existsSync(testDir));
});
@ -105,7 +105,7 @@ flakySuite('PFS', function () {
fs.mkdirSync(join(testDir, 'somefolder'));
fs.writeFileSync(join(testDir, 'somefolder', 'somefile.txt'), 'Contents');
await rimraf(testDir, RimRafMode.MOVE);
await Promises.rm(testDir, RimRafMode.MOVE);
assert.ok(!fs.existsSync(testDir));
});
@ -113,7 +113,7 @@ flakySuite('PFS', function () {
fs.writeFileSync(join(testDir, 'somefile.txt'), 'Contents');
fs.writeFileSync(join(testDir, 'someOtherFile.txt'), 'Contents');
await rimraf(testDir, RimRafMode.MOVE);
await Promises.rm(testDir, RimRafMode.MOVE);
assert.ok(!fs.existsSync(testDir));
});
@ -121,7 +121,7 @@ flakySuite('PFS', function () {
fs.writeFileSync(join(testDir, 'somefile.txt'), 'Contents');
fs.writeFileSync(join(testDir, 'someOtherFile.txt'), 'Contents');
await rimraf(`${testDir}${sep}`, RimRafMode.MOVE);
await Promises.rm(`${testDir}${sep}`, RimRafMode.MOVE);
assert.ok(!fs.existsSync(testDir));
});
@ -161,7 +161,7 @@ flakySuite('PFS', function () {
const targetDir = join(parentDir, id);
const targetDir2 = join(parentDir, id2);
await copy(sourceDir, targetDir, { preserveSymlinks: true });
await Promises.copy(sourceDir, targetDir, { preserveSymlinks: true });
assert.ok(fs.existsSync(targetDir));
assert.ok(fs.existsSync(join(targetDir, 'index.html')));
@ -170,7 +170,7 @@ flakySuite('PFS', function () {
assert.ok(fs.statSync(join(targetDir, 'examples')).isDirectory());
assert.ok(fs.existsSync(join(targetDir, 'examples', 'small.jxs')));
await move(targetDir, targetDir2);
await Promises.move(targetDir, targetDir2);
assert.ok(!fs.existsSync(targetDir));
assert.ok(fs.existsSync(targetDir2));
@ -180,12 +180,12 @@ flakySuite('PFS', function () {
assert.ok(fs.statSync(join(targetDir2, 'examples')).isDirectory());
assert.ok(fs.existsSync(join(targetDir2, 'examples', 'small.jxs')));
await move(join(targetDir2, 'index.html'), join(targetDir2, 'index_moved.html'));
await Promises.move(join(targetDir2, 'index.html'), join(targetDir2, 'index_moved.html'));
assert.ok(!fs.existsSync(join(targetDir2, 'index.html')));
assert.ok(fs.existsSync(join(targetDir2, 'index_moved.html')));
await rimraf(parentDir);
await Promises.rm(parentDir);
assert.ok(!fs.existsSync(parentDir));
});
@ -209,7 +209,7 @@ flakySuite('PFS', function () {
// Windows: this test does not work because creating symlinks
// requires priviledged permissions (admin).
if (!isWindows) {
await copy(symLink, copyTarget, { preserveSymlinks: true });
await Promises.copy(symLink, copyTarget, { preserveSymlinks: true });
assert.ok(fs.existsSync(copyTarget));
@ -222,8 +222,8 @@ flakySuite('PFS', function () {
// Copy does not preserve symlinks if configured as such
await rimraf(copyTarget);
await copy(symLink, copyTarget, { preserveSymlinks: false });
await Promises.rm(copyTarget);
await Promises.copy(symLink, copyTarget, { preserveSymlinks: false });
assert.ok(fs.existsSync(copyTarget));
@ -233,10 +233,10 @@ flakySuite('PFS', function () {
// Copy does not fail over dangling symlinks
await rimraf(copyTarget);
await rimraf(symbolicLinkTarget);
await Promises.rm(copyTarget);
await Promises.rm(symbolicLinkTarget);
await copy(symLink, copyTarget, { preserveSymlinks: true }); // this should not throw
await Promises.copy(symLink, copyTarget, { preserveSymlinks: true }); // this should not throw
if (!isWindows) {
const { symbolicLink } = await SymlinkSupport.stat(copyTarget);
@ -270,7 +270,7 @@ flakySuite('PFS', function () {
// Windows: this test does not work because creating symlinks
// requires priviledged permissions (admin).
if (!isWindows) {
await copy(sourceLinkTestFolder, targetLinkTestFolder, { preserveSymlinks: true });
await Promises.copy(sourceLinkTestFolder, targetLinkTestFolder, { preserveSymlinks: true });
assert.ok(fs.existsSync(targetLinkTestFolder));
assert.ok(fs.existsSync(targetLinkMD5JSFolder));
@ -285,7 +285,7 @@ flakySuite('PFS', function () {
}
// Copy with `preserveSymlinks: false` and verify result
await copy(sourceLinkTestFolder, targetLinkTestFolder, { preserveSymlinks: false });
await Promises.copy(sourceLinkTestFolder, targetLinkTestFolder, { preserveSymlinks: false });
assert.ok(fs.existsSync(targetLinkTestFolder));
assert.ok(fs.existsSync(targetLinkMD5JSFolder));
@ -301,7 +301,7 @@ flakySuite('PFS', function () {
fs.writeFileSync(join(testDir, 'somefile.txt'), 'Contents');
fs.writeFileSync(join(testDir, 'someOtherFile.txt'), 'Contents');
const result = await readDirsInDir(testDir);
const result = await Promises.readDirsInDir(testDir);
assert.strictEqual(result.length, 3);
assert.ok(result.indexOf('somefolder1') !== -1);
assert.ok(result.indexOf('somefolder2') !== -1);
@ -338,7 +338,7 @@ flakySuite('PFS', function () {
fs.symlinkSync(directory, symbolicLink, 'junction');
await rimraf(directory);
await Promises.rm(directory);
const statAndIsLink = await SymlinkSupport.stat(symbolicLink);
assert.ok(statAndIsLink?.symbolicLink);

View file

@ -7,7 +7,7 @@ import * as assert from 'assert';
import * as path from 'vs/base/common/path';
import { tmpdir } from 'os';
import { extract } from 'vs/base/node/zip';
import { rimraf, Promises } from 'vs/base/node/pfs';
import { Promises } from 'vs/base/node/pfs';
import { createCancelablePromise } from 'vs/base/common/async';
import { getRandomTestPath, getPathFromAmdModule } from 'vs/base/test/node/testUtils';
@ -22,7 +22,7 @@ suite('Zip', () => {
});
teardown(() => {
return rimraf(testDir);
return Promises.rm(testDir);
});
test('extract should handle directories', async () => {

View file

@ -0,0 +1,68 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { basename, dirname, join } from 'vs/base/common/path';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Disposable } from 'vs/base/common/lifecycle';
import { Promises } from 'vs/base/node/pfs';
import { IProductService } from 'vs/platform/product/common/productService';
import { RunOnceScheduler } from 'vs/base/common/async';
import { ILogService } from 'vs/platform/log/common/log';
export class CodeCacheCleaner extends Disposable {
private readonly _DataMaxAge = this.productService.quality !== 'stable'
? 1000 * 60 * 60 * 24 * 7 // roughly 1 week (insiders)
: 1000 * 60 * 60 * 24 * 30 * 3; // roughly 3 months (stable)
constructor(
currentCodeCachePath: string | undefined,
@IProductService private readonly productService: IProductService,
@ILogService private readonly logService: ILogService
) {
super();
// Cached data is stored as user data and we run a cleanup task everytime
// the editor starts. The strategy is to delete all files that are older than
// 3 months (1 week respectively)
if (currentCodeCachePath) {
const scheduler = this._register(new RunOnceScheduler(() => {
this.cleanUpCodeCaches(currentCodeCachePath);
}, 30 * 1000 /* after 30s */));
scheduler.schedule();
}
}
private async cleanUpCodeCaches(currentCodeCachePath: string): Promise<void> {
this.logService.info('[code cache cleanup]: Starting to clean up old code cache folders.');
try {
const now = Date.now();
// The folder which contains folders of cached data.
// Each of these folders is partioned per commit
const codeCacheRootPath = dirname(currentCodeCachePath);
const currentCodeCache = basename(currentCodeCachePath);
const codeCaches = await Promises.readdir(codeCacheRootPath);
await Promise.all(codeCaches.map(async codeCache => {
if (codeCache === currentCodeCache) {
return; // not the current cache folder
}
// Delete cache folder if old enough
const codeCacheEntryPath = join(codeCacheRootPath, codeCache);
const codeCacheEntryStat = await Promises.stat(codeCacheEntryPath);
if (codeCacheEntryStat.isDirectory() && (now - codeCacheEntryStat.mtime.getTime()) > this._DataMaxAge) {
this.logService.info(`[code cache cleanup]: Removing code cache folder ${codeCache}.`);
return Promises.rm(codeCacheEntryPath);
}
}));
} catch (error) {
onUnexpectedError(error);
}
}
}

View file

@ -3,16 +3,17 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as path from 'vs/base/common/path';
import * as pfs from 'vs/base/node/pfs';
import { join } from 'vs/base/common/path';
import { Promises } from 'vs/base/node/pfs';
import { IStringDictionary } from 'vs/base/common/collections';
import { IProductService } from 'vs/platform/product/common/productService';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { Disposable } from 'vs/base/common/lifecycle';
import { onUnexpectedError } from 'vs/base/common/errors';
import { ILogService } from 'vs/platform/log/common/log';
import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { RunOnceScheduler } from 'vs/base/common/async';
interface ExtensionEntry {
interface IExtensionEntry {
version: string;
extensionIdentifier: {
id: string;
@ -20,87 +21,88 @@ interface ExtensionEntry {
};
}
interface LanguagePackEntry {
interface ILanguagePackEntry {
hash: string;
extensions: ExtensionEntry[];
extensions: IExtensionEntry[];
}
interface LanguagePackFile {
[locale: string]: LanguagePackEntry;
interface ILanguagePackFile {
[locale: string]: ILanguagePackEntry;
}
export class LanguagePackCachedDataCleaner extends Disposable {
private readonly _DataMaxAge = this._productService.quality !== 'stable'
? 1000 * 60 * 60 * 24 * 7 // roughly 1 week
: 1000 * 60 * 60 * 24 * 30 * 3; // roughly 3 months
private readonly _DataMaxAge = this.productService.quality !== 'stable'
? 1000 * 60 * 60 * 24 * 7 // roughly 1 week (insiders)
: 1000 * 60 * 60 * 24 * 30 * 3; // roughly 3 months (stable)
constructor(
@INativeEnvironmentService private readonly _environmentService: INativeEnvironmentService,
@ILogService private readonly _logService: ILogService,
@IProductService private readonly _productService: IProductService
@INativeEnvironmentService private readonly environmentService: INativeEnvironmentService,
@ILogService private readonly logService: ILogService,
@IProductService private readonly productService: IProductService
) {
super();
// We have no Language pack support for dev version (run from source)
// So only cleanup when we have a build version.
if (this._environmentService.isBuilt) {
this._manageCachedDataSoon();
if (this.environmentService.isBuilt) {
const scheduler = this._register(new RunOnceScheduler(() => {
this.cleanUpLanguagePackCache();
}, 40 * 1000 /* after 40s */));
scheduler.schedule();
}
}
private _manageCachedDataSoon(): void {
let handle: any = setTimeout(async () => {
handle = undefined;
this._logService.info('Starting to clean up unused language packs.');
try {
const installed: IStringDictionary<boolean> = Object.create(null);
const metaData: LanguagePackFile = JSON.parse(await pfs.Promises.readFile(path.join(this._environmentService.userDataPath, 'languagepacks.json'), 'utf8'));
for (let locale of Object.keys(metaData)) {
const entry = metaData[locale];
installed[`${entry.hash}.${locale}`] = true;
private async cleanUpLanguagePackCache(): Promise<void> {
this.logService.info('[language pack cache cleanup]: Starting to clean up unused language packs.');
try {
const installed: IStringDictionary<boolean> = Object.create(null);
const metaData: ILanguagePackFile = JSON.parse(await Promises.readFile(join(this.environmentService.userDataPath, 'languagepacks.json'), 'utf8'));
for (let locale of Object.keys(metaData)) {
const entry = metaData[locale];
installed[`${entry.hash}.${locale}`] = true;
}
// Cleanup entries for language packs that aren't installed anymore
const cacheDir = join(this.environmentService.userDataPath, 'clp');
const cacheDirExists = await Promises.exists(cacheDir);
if (!cacheDirExists) {
return;
}
const entries = await Promises.readdir(cacheDir);
for (const entry of entries) {
if (installed[entry]) {
this.logService.info(`[language pack cache cleanup]: Skipping folder ${entry}. Language pack still in use.`);
continue;
}
// Cleanup entries for language packs that aren't installed anymore
const cacheDir = path.join(this._environmentService.userDataPath, 'clp');
const exists = await pfs.Promises.exists(cacheDir);
if (!exists) {
return;
}
for (let entry of await pfs.Promises.readdir(cacheDir)) {
if (installed[entry]) {
this._logService.info(`Skipping directory ${entry}. Language pack still in use.`);
this.logService.info(`[language pack cache cleanup]: Removing unused language pack: ${entry}`);
await Promises.rm(join(cacheDir, entry));
}
const now = Date.now();
for (const packEntry of Object.keys(installed)) {
const folder = join(cacheDir, packEntry);
const entries = await Promises.readdir(folder);
for (const entry of entries) {
if (entry === 'tcf.json') {
continue;
}
this._logService.info('Removing unused language pack:', entry);
await pfs.rimraf(path.join(cacheDir, entry));
}
const now = Date.now();
for (let packEntry of Object.keys(installed)) {
const folder = path.join(cacheDir, packEntry);
for (let entry of await pfs.Promises.readdir(folder)) {
if (entry === 'tcf.json') {
continue;
}
const candidate = path.join(folder, entry);
const stat = await pfs.Promises.stat(candidate);
if (stat.isDirectory()) {
const diff = now - stat.mtime.getTime();
if (diff > this._DataMaxAge) {
this._logService.info('Removing language pack cache entry: ', path.join(packEntry, entry));
await pfs.rimraf(candidate);
}
}
const candidate = join(folder, entry);
const stat = await Promises.stat(candidate);
if (stat.isDirectory() && (now - stat.mtime.getTime()) > this._DataMaxAge) {
this.logService.info(`[language pack cache cleanup]: Removing language pack cache folder: ${join(packEntry, entry)}`);
await Promises.rm(candidate);
}
}
} catch (error) {
onUnexpectedError(error);
}
}, 40 * 1000);
this._register(toDisposable(() => {
if (handle !== undefined) {
clearTimeout(handle);
}
}));
} catch (error) {
onUnexpectedError(error);
}
}
}

View file

@ -5,42 +5,46 @@
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { join, dirname, basename } from 'vs/base/common/path';
import { Promises as FSPromises, rimraf } from 'vs/base/node/pfs';
import { Promises } from 'vs/base/node/pfs';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { Promises } from 'vs/base/common/async';
import { Disposable } from 'vs/base/common/lifecycle';
import { RunOnceScheduler } from 'vs/base/common/async';
import { ILogService } from 'vs/platform/log/common/log';
export class LogsDataCleaner extends Disposable {
constructor(
@IEnvironmentService private readonly environmentService: IEnvironmentService
@IEnvironmentService private readonly environmentService: IEnvironmentService,
@ILogService private readonly logService: ILogService
) {
super();
this.cleanUpOldLogsSoon();
const scheduler = this._register(new RunOnceScheduler(() => {
this.cleanUpOldLogs();
}, 10 * 1000 /* after 10s */));
scheduler.schedule();
}
private cleanUpOldLogsSoon(): void {
let handle: NodeJS.Timeout | undefined = setTimeout(() => {
handle = undefined;
private async cleanUpOldLogs(): Promise<void> {
this.logService.info('[logs cleanup]: Starting to clean up old logs.');
try {
const currentLog = basename(this.environmentService.logsPath);
const logsRoot = dirname(this.environmentService.logsPath);
FSPromises.readdir(logsRoot).then(children => {
const allSessions = children.filter(name => /^\d{8}T\d{6}$/.test(name));
const oldSessions = allSessions.sort().filter((d, i) => d !== currentLog);
const toDelete = oldSessions.slice(0, Math.max(0, oldSessions.length - 9));
const logFiles = await Promises.readdir(logsRoot);
return Promises.settled(toDelete.map(name => rimraf(join(logsRoot, name))));
}).then(null, onUnexpectedError);
}, 10 * 1000);
const allSessions = logFiles.filter(logFile => /^\d{8}T\d{6}$/.test(logFile));
const oldSessions = allSessions.sort().filter(session => session !== currentLog);
const sessionsToDelete = oldSessions.slice(0, Math.max(0, oldSessions.length - 9));
this._register(toDisposable(() => {
if (handle) {
clearTimeout(handle);
handle = undefined;
if (sessionsToDelete.length > 0) {
this.logService.info(`[logs cleanup]: Removing log folders '${sessionsToDelete.join(', ')}'`);
await Promise.all(sessionsToDelete.map(sessionToDelete => Promises.rm(join(logsRoot, sessionToDelete))));
}
}));
} catch (error) {
onUnexpectedError(error);
}
}
}

View file

@ -1,86 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { basename, dirname, join } from 'vs/base/common/path';
import { onUnexpectedError } from 'vs/base/common/errors';
import { toDisposable, DisposableStore } from 'vs/base/common/lifecycle';
import { Promises, rimraf } from 'vs/base/node/pfs';
import { IProductService } from 'vs/platform/product/common/productService';
export class NodeCachedDataCleaner {
private readonly _DataMaxAge = this.productService.quality !== 'stable'
? 1000 * 60 * 60 * 24 * 7 // roughly 1 week
: 1000 * 60 * 60 * 24 * 30 * 3; // roughly 3 months
private readonly _disposables = new DisposableStore();
constructor(
private readonly nodeCachedDataDir: string | undefined,
@IProductService private readonly productService: IProductService
) {
this._manageCachedDataSoon();
}
dispose(): void {
this._disposables.dispose();
}
private _manageCachedDataSoon(): void {
// Cached data is stored as user data and we run a cleanup task everytime
// the editor starts. The strategy is to delete all files that are older than
// 3 months (1 week respectively)
if (!this.nodeCachedDataDir) {
return;
}
// The folder which contains folders of cached data. Each of these folder is per
// version
const nodeCachedDataRootDir = dirname(this.nodeCachedDataDir);
const nodeCachedDataCurrent = basename(this.nodeCachedDataDir);
let handle: NodeJS.Timeout | undefined = setTimeout(() => {
handle = undefined;
Promises.readdir(nodeCachedDataRootDir).then(entries => {
const now = Date.now();
const deletes: Promise<unknown>[] = [];
entries.forEach(entry => {
// name check
// * not the current cached data folder
if (entry !== nodeCachedDataCurrent) {
const path = join(nodeCachedDataRootDir, entry);
deletes.push(Promises.stat(path).then(stats => {
// stat check
// * only directories
// * only when old enough
if (stats.isDirectory()) {
const diff = now - stats.mtime.getTime();
if (diff > this._DataMaxAge) {
return rimraf(path);
}
}
return undefined;
}));
}
});
return Promise.all(deletes);
}).then(undefined, onUnexpectedError);
}, 30 * 1000);
this._disposables.add(toDisposable(() => {
if (handle) {
clearTimeout(handle);
handle = undefined;
}
}));
}
}

View file

@ -5,10 +5,12 @@
import { INativeEnvironmentService } from 'vs/platform/environment/common/environment';
import { join } from 'vs/base/common/path';
import { Promises, rimraf } from 'vs/base/node/pfs';
import { Promises } from 'vs/base/node/pfs';
import { onUnexpectedError } from 'vs/base/common/errors';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { Disposable } from 'vs/base/common/lifecycle';
import { IBackupWorkspacesFormat } from 'vs/platform/backup/node/backup';
import { RunOnceScheduler } from 'vs/base/common/async';
import { ILogService } from 'vs/platform/log/common/log';
export class StorageDataCleaner extends Disposable {
@ -17,52 +19,44 @@ export class StorageDataCleaner extends Disposable {
constructor(
private readonly backupWorkspacesPath: string,
@INativeEnvironmentService private readonly environmentService: INativeEnvironmentService
@INativeEnvironmentService private readonly environmentService: INativeEnvironmentService,
@ILogService private readonly logService: ILogService
) {
super();
this.cleanUpStorageSoon();
const scheduler = this._register(new RunOnceScheduler(() => {
this.cleanUpStorage();
}, 30 * 1000 /* after 30s */));
scheduler.schedule();
}
private cleanUpStorageSoon(): void {
let handle: NodeJS.Timeout | undefined = setTimeout(() => {
handle = undefined;
private async cleanUpStorage(): Promise<void> {
this.logService.info('[storage cleanup]: Starting to clean up storage folders.');
(async () => {
try {
// Leverage the backup workspace file to find out which empty workspace is currently in use to
// determine which empty workspace storage can safely be deleted
const contents = await Promises.readFile(this.backupWorkspacesPath, 'utf8');
try {
const workspaces = JSON.parse(contents) as IBackupWorkspacesFormat;
const emptyWorkspaces = workspaces.emptyWorkspaceInfos.map(info => info.backupFolder);
// Leverage the backup workspace file to find out which empty workspace is currently in use to
// determine which empty workspace storage can safely be deleted
const contents = await Promises.readFile(this.backupWorkspacesPath, 'utf8');
// Read all workspace storage folders that exist
const storageFolders = await Promises.readdir(this.environmentService.workspaceStorageHome.fsPath);
const deletes: Promise<void>[] = [];
const workspaces = JSON.parse(contents) as IBackupWorkspacesFormat;
const emptyWorkspaces = workspaces.emptyWorkspaceInfos.map(emptyWorkspace => emptyWorkspace.backupFolder);
storageFolders.forEach(storageFolder => {
if (storageFolder.length === StorageDataCleaner.NON_EMPTY_WORKSPACE_ID_LENGTH) {
return;
}
if (emptyWorkspaces.indexOf(storageFolder) === -1) {
deletes.push(rimraf(join(this.environmentService.workspaceStorageHome.fsPath, storageFolder)));
}
});
await Promise.all(deletes);
} catch (error) {
onUnexpectedError(error);
// Read all workspace storage folders that exist
const storageFolders = await Promises.readdir(this.environmentService.workspaceStorageHome.fsPath);
await Promise.all(storageFolders.map(async storageFolder => {
if (storageFolder.length === StorageDataCleaner.NON_EMPTY_WORKSPACE_ID_LENGTH) {
return;
}
})();
}, 30 * 1000);
this._register(toDisposable(() => {
if (handle) {
clearTimeout(handle);
handle = undefined;
}
}));
if (emptyWorkspaces.indexOf(storageFolder) === -1) {
this.logService.info(`[storage cleanup]: Deleting storage folder ${storageFolder}.`);
await Promises.rm(join(this.environmentService.workspaceStorageHome.fsPath, storageFolder));
}
}));
} catch (error) {
onUnexpectedError(error);
}
}
}

View file

@ -36,7 +36,7 @@ import { ILocalizationsService } from 'vs/platform/localizations/common/localiza
import { combinedDisposable, Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { DownloadService } from 'vs/platform/download/common/downloadService';
import { IDownloadService } from 'vs/platform/download/common/download';
import { NodeCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/nodeCachedDataCleaner';
import { CodeCacheCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/codeCacheCleaner';
import { LanguagePackCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/languagePackCachedDataCleaner';
import { StorageDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/storageDataCleaner';
import { LogsDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner';
@ -131,7 +131,7 @@ class SharedProcessMain extends Disposable {
// Instantiate Contributions
this._register(combinedDisposable(
instantiationService.createInstance(NodeCachedDataCleaner, this.configuration.nodeCachedDataDir),
instantiationService.createInstance(CodeCacheCleaner, this.configuration.codeCachePath),
instantiationService.createInstance(LanguagePackCachedDataCleaner),
instantiationService.createInstance(StorageDataCleaner, this.configuration.backupWorkspacesPath),
instantiationService.createInstance(LogsDataCleaner),

View file

@ -5,7 +5,7 @@
import { release, hostname } from 'os';
import { statSync } from 'fs';
import { app, ipcMain, systemPreferences, contentTracing, protocol, BrowserWindow, dialog, session } from 'electron';
import { app, ipcMain, systemPreferences, contentTracing, protocol, BrowserWindow, dialog, session, Session } from 'electron';
import { IProcessEnvironment, isWindows, isMacintosh, isLinux, isLinuxSnap } from 'vs/base/common/platform';
import { WindowsMainService } from 'vs/platform/windows/electron-main/windowsMainService';
import { IWindowOpenable } from 'vs/platform/windows/common/windows';
@ -113,9 +113,60 @@ export class CodeApplication extends Disposable {
) {
super();
this.configureSession();
this.registerListeners();
}
private configureSession(): void {
//#region Security related measures (https://electronjs.org/docs/tutorial/security)
//
// !!! DO NOT CHANGE without consulting the documentation !!!
//
const isUrlFromWebview = (requestingUrl: string) => requestingUrl.startsWith(`${Schemas.vscodeWebview}://`);
session.defaultSession.setPermissionRequestHandler((_webContents, permission /* 'media' | 'geolocation' | 'notifications' | 'midiSysex' | 'pointerLock' | 'fullscreen' | 'openExternal' */, callback, details) => {
if (isUrlFromWebview(details.requestingUrl)) {
return callback(permission === 'clipboard-read');
}
return callback(false);
});
session.defaultSession.setPermissionCheckHandler((_webContents, permission /* 'media' */, _origin, details) => {
if (isUrlFromWebview(details.requestingUrl)) {
return permission === 'clipboard-read';
}
return false;
});
//#endregion
//#region Code Cache
type SessionWithCodeCachePathSupport = typeof Session & {
/**
* Sets code cache directory. By default, the directory will be `Code Cache` under
* the respective user data folder.
*/
setCodeCachePath?(path: string): void;
};
const defaultSession = session.defaultSession as unknown as SessionWithCodeCachePathSupport;
if (typeof defaultSession.setCodeCachePath === 'function' && this.environmentMainService.codeCachePath) {
// Make sure to partition Chrome's code cache folder
// in the same way as our code cache path to help
// invalidate caches that we know are invalid
// (https://github.com/microsoft/vscode/issues/120655)
defaultSession.setCodeCachePath(join(this.environmentMainService.codeCachePath, 'chrome'));
}
//#endregion
}
private registerListeners(): void {
// We handle uncaught exceptions here to prevent electron from opening a dialog to the user
@ -196,24 +247,6 @@ export class CodeApplication extends Disposable {
return { action: 'deny' };
});
const isUrlFromWebview = (requestingUrl: string) => requestingUrl.startsWith(`${Schemas.vscodeWebview}://`);
session.defaultSession.setPermissionRequestHandler((_webContents, permission /* 'media' | 'geolocation' | 'notifications' | 'midiSysex' | 'pointerLock' | 'fullscreen' | 'openExternal' */, callback, details) => {
if (isUrlFromWebview(details.requestingUrl)) {
return callback(permission === 'clipboard-read');
}
return callback(false);
});
session.defaultSession.setPermissionCheckHandler((_webContents, permission /* 'media' */, _origin, details) => {
if (isUrlFromWebview(details.requestingUrl)) {
return permission === 'clipboard-read';
}
return false;
});
});
//#endregion

View file

@ -209,7 +209,7 @@ class CodeMain {
// Environment service (paths)
Promise.all<string | undefined>([
environmentMainService.extensionsPath,
environmentMainService.nodeCachedDataDir,
environmentMainService.codeCachePath,
environmentMainService.logsPath,
environmentMainService.globalStorageHome.fsPath,
environmentMainService.workspaceStorageHome.fsPath,

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