Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,4 @@ debugpy*.log
pydevd*.log
nodeLanguageServer/**
nodeLanguageServer.*/**
dist/**
74 changes: 74 additions & 0 deletions build/webpack/webpack.extension.browser.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

// @ts-check

'use strict';

const path = require('path');

const packageRoot = path.resolve(__dirname, '..', '..');
const outDir = path.resolve(packageRoot, 'dist');

/** @type {(env: any, argv: { mode: 'production' | 'development' | 'none' }) => import('webpack').Configuration} */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const nodeConfig = (_, { mode }) => ({
context: packageRoot,
entry: {
extension: './src/client/browser/extension.ts',
},
target: 'webworker',
output: {
filename: '[name].browser.js',
path: outDir,
libraryTarget: 'commonjs2',
devtoolModuleFilenameTemplate: '../../[resource-path]',
},
devtool: 'source-map',
// stats: {
// all: false,
// errors: true,
// warnings: true,
// },
resolve: {
extensions: ['.ts', '.js'],
},
externals: {
vscode: 'commonjs vscode',

// These dependencies are ignored because we don't use them, and App Insights has try-catch protecting their loading if they don't exist
// See: https://github.com/microsoft/vscode-extension-telemetry/issues/41#issuecomment-598852991
'applicationinsights-native-metrics': 'commonjs applicationinsights-native-metrics',
'@opentelemetry/tracing': 'commonjs @opentelemetry/tracing',
},
module: {
rules: [
{
test: /\.ts$/,
loader: 'ts-loader',
options: {
configFile: 'tsconfig.browser.json',
},
},
{
test: /\.node$/,
loader: 'node-loader',
},
],
},
// optimization: {
// usedExports: true,
// splitChunks: {
// cacheGroups: {
// defaultVendors: {
// name: 'vendor',
// test: /[\\/]node_modules[\\/]/,
// chunks: 'all',
// priority: -10,
// },
// },
// },
// },
});

module.exports = nodeConfig;
3 changes: 3 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ gulp.task('webpack', async () => {
// Build node_modules.
await buildWebPackForDevOrProduction('./build/webpack/webpack.extension.dependencies.config.js', 'production');
await buildWebPackForDevOrProduction('./build/webpack/webpack.extension.config.js', 'extension');
await buildWebPackForDevOrProduction('./build/webpack/webpack.extension.browser.config.js', 'browser');
});

gulp.task('addExtensionPackDependencies', async () => {
Expand Down Expand Up @@ -191,6 +192,8 @@ function getAllowedWarningsForWebPack(buildConfig) {
'WARNING in ./node_modules/diagnostic-channel-publishers/dist/src/azure-coretracing.pub.js',
'WARNING in ./node_modules/applicationinsights/out/AutoCollection/NativePerformance.js',
];
case 'browser':
return [];
default:
throw new Error('Unknown WebPack Configuration');
}
Expand Down
1 change: 1 addition & 0 deletions news/1 Enhancements/16869.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add a basic web extension bundle.
1 change: 1 addition & 0 deletions news/1 Enhancements/16870.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add basic Pylance support to the web extension.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
"workspaceContains:app.py"
],
"main": "./out/client/extension",
"browser": "./dist/extension.browser.js",
"contributes": {
"walkthroughs": [
{
Expand Down Expand Up @@ -197,7 +198,7 @@
"light": "resources/walkthrough/open-folder-light.png",
"dark": "resources/walkthrough/open-folder-dark.png",
"hc": "resources/walkthrough/open-folder-hc.png"
},
},
"altText": "Open a folder"
},
"completionEvents": [
Expand All @@ -214,7 +215,7 @@
"light": "resources/walkthrough/open-folder-light.png",
"dark": "resources/walkthrough/open-folder-dark.png",
"hc": "resources/walkthrough/open-folder-hc.png"
},
},
"altText": "Open a folder"
},
"completionEvents": [
Expand Down
61 changes: 61 additions & 0 deletions src/client/browser/extension.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

import * as vscode from 'vscode';
import { LanguageClientOptions } from 'vscode-languageclient';
import { LanguageClient } from 'vscode-languageclient/browser';
import { ILSExtensionApi } from '../activation/node/languageServerFolderService';
import { PYLANCE_EXTENSION_ID } from '../common/constants';

interface BrowserConfig {
distUrl: string; // URL to Pylance's dist folder.
}

export async function activate(context: vscode.ExtensionContext): Promise<void> {
// Run in a promise and return early so that VS Code can go activate Pylance.
runPylance(context);
}

async function runPylance(context: vscode.ExtensionContext): Promise<void> {
const pylanceExtension = vscode.extensions.getExtension<ILSExtensionApi>(PYLANCE_EXTENSION_ID);
const pylanceApi = await pylanceExtension?.activate();
if (!pylanceApi?.languageServerFolder) {
throw new Error('Could not find Pylance extension');
}

const { path: distUrl } = await pylanceApi.languageServerFolder();

try {
const worker = new Worker(`${distUrl}/browser.server.bundle.js`);

// Pass the configuration as the first message to the worker so it can
// have info like the URL of the dist folder early enough.
//
// This is the same method used by the TS worker:
// https://github.com/microsoft/vscode/blob/90aa979bb75a795fd8c33d38aee263ea655270d0/extensions/typescript-language-features/src/tsServer/serverProcess.browser.ts#L55
const config: BrowserConfig = {
distUrl,
};
worker.postMessage(config);

const clientOptions: LanguageClientOptions = {
// Register the server for python source files.
documentSelector: [
{
language: 'python',
},
],
synchronize: {
// Synchronize the setting section to the server.
configurationSection: ['python'],
},
};

const languageClient = new LanguageClient('python', 'Python Language Server', clientOptions, worker);
const disposable = languageClient.start();

context.subscriptions.push(disposable);
} catch (e) {
console.log(e);
}
}
6 changes: 6 additions & 0 deletions tsconfig.browser.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": "./tsconfig.json",
"include": [
"./src/client/browser"
]
}
8 changes: 8 additions & 0 deletions typings/webworker.fix.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

// Fake interfaces that are required for web workers to work around
// tsconfig's DOM and WebWorker lib options being mutally exclusive.
// https://github.com/microsoft/TypeScript/issues/20595

interface DedicatedWorkerGlobalScope {}