import * as commands from "./commands" ; import { ENABLEMENT_FLAG , EXTENSION_NS } from "./constants" ; import { DenoTextDocumentContentProvider , SCHEME } from "./content_provider" ; import { DenoDebugConfigurationProvider } from "./debug_config_provider" ; import { DenoStatusBar } from "./status_bar" ; import { activateTaskProvider } from "./tasks" ; import { getTsApi } from "./ts_api" ; import type { DenoExtensionContext , Settings } from "./types" ; import { assert } from "./util" ; import * as path from "path" ; import * as vscode from "vscode" ; /** The language IDs we care about. */ const LANGUAGES = [ "typescript" , "javascript" , "typescriptreact" , "javascriptreact" , ] ; /** These are keys of settings that have a scope of window or machine. */ const workspaceSettingsKeys = [ "cache" , "codeLens" , "config" , "importMap" , "internalDebug" , "lint" , "suggest" , "unstable" , ] ; /** These are keys of settings that can apply to an individual resource, like
 * a file or folder. */ const resourceSettingsKeys = [ "enable" , "codeLens" , ] ; /** Convert a workspace configuration to `Settings` for a workspace. */ function configToWorkspaceSettings ( config ) { const workspaceSettings = Object . create ( null ) ; for ( const key of workspaceSettingsKeys ) { workspaceSettings [ key ] = config . get ( key ) ; } for ( const key of resourceSettingsKeys ) { workspaceSettings [ key ] = config . get ( key ) ; } return workspaceSettings ; } /** Convert a workspace configuration to settings that apply to a resource. */ function configToResourceSettings ( config ) { const resourceSettings = Object . create ( null ) ; for ( const key of resourceSettingsKeys ) { const value = config . inspect ( key ) ; assert ( value ) ; resourceSettings [ key ] = value . workspaceFolderLanguageValue ?? value . workspaceFolderValue ?? value . workspaceLanguageValue ?? value . workspaceValue ?? value . globalValue ?? value . defaultValue ; } return resourceSettings ; } function getWorkspaceSettings ( ) { const config = vscode . workspace . getConfiguration ( EXTENSION_NS ) ; return configToWorkspaceSettings ( config ) ; } function handleConfigurationChange ( event ) { if ( event . affectsConfiguration ( EXTENSION_NS ) ) { extensionContext . client ?. sendNotification ( "workspace/didChangeConfiguration" , { settings : null } ) ; extensionContext . workspaceSettings = getWorkspaceSettings ( ) ; for ( const [ key , { scope } ] of Object . entries ( extensionContext . documentSettings ) ) { extensionContext . documentSettings [ key ] = { scope , settings : configToResourceSettings ( vscode . workspace . getConfiguration ( EXTENSION_NS , scope ) ) , } ; } extensionContext . tsApi . refresh ( ) ; extensionContext . statusBar . refresh ( extensionContext ) ; if ( event . affectsConfiguration ( "deno.path" ) ) { vscode . commands . executeCommand ( "deno.restart" ) ; } } } function handleDocumentOpen ( ... documents ) { let didChange = false ; for ( const doc of documents ) { if ( ! LANGUAGES . includes ( doc . languageId ) ) { continue ; } const { languageId , uri } = doc ; extensionContext . documentSettings [ path . normalize ( doc . uri . fsPath ) ] = { scope : { languageId , uri } , settings : configToResourceSettings ( vscode . workspace . getConfiguration ( EXTENSION_NS , { languageId , uri } ) ) , } ; didChange = true ; } if ( didChange ) { extensionContext . tsApi . refresh ( ) ; } } const extensionContext = { } as DenoExtensionContext ; /** When the extension activates, this function is called with the extension
 * context, and the extension bootstraps itself. */ export async function activate ( context ) { extensionContext . clientOptions = { documentSelector : [ { scheme : "file" , language : "javascript" } , { scheme : "file" , language : "javascriptreact" } , { scheme : "file" , language : "typescript" } , { scheme : "file" , language : "typescriptreact" } , { scheme : "deno" , language : "javascript" } , { scheme : "deno" , language : "javascriptreact" } , { scheme : "deno" , language : "typescript" } , { scheme : "deno" , language : "typescriptreact" } , { scheme : "file" , language : "json" } , { scheme : "file" , language : "jsonc" } , { scheme : "file" , language : "markdown" } , ] , diagnosticCollectionName : "deno" , initializationOptions : getWorkspaceSettings ( ) , } ; vscode . workspace . onDidOpenTextDocument ( handleDocumentOpen , extensionContext , context . subscriptions ) ; vscode . workspace . onDidChangeConfiguration ( handleConfigurationChange , extensionContext , context . subscriptions ) ; extensionContext . statusBar = new DenoStatusBar ( ) ; context . subscriptions . push ( extensionContext . statusBar ) ; context . subscriptions . push ( vscode . workspace . registerTextDocumentContentProvider ( SCHEME , new DenoTextDocumentContentProvider ( extensionContext ) ) ) ; context . subscriptions . push ( vscode . debug . registerDebugConfigurationProvider ( "deno" , new DenoDebugConfigurationProvider ( getWorkspaceSettings ) ) ) ; context . subscriptions . push ( activateTaskProvider ( ) ) ; const registerCommand = createRegisterCommand ( context ) ; registerCommand ( "cache" , commands . cache ) ; registerCommand ( "initializeWorkspace" , commands . initializeWorkspace ) ; registerCommand ( "restart" , commands . startLanguageServer ) ; registerCommand ( "reloadImportRegistries" , commands . reloadImportRegistries ) ; registerCommand ( "showReferences" , commands . showReferences ) ; registerCommand ( "status" , commands . status ) ; registerCommand ( "test" , commands . test ) ; registerCommand ( "welcome" , commands . welcome ) ; extensionContext . tsApi = getTsApi ( ( ) => ( { documents : extensionContext . documentSettings , workspace : extensionContext . workspaceSettings , } ) ) ; extensionContext . documentSettings = { } ; extensionContext . workspaceSettings = getWorkspaceSettings ( ) ; handleDocumentOpen ( ... vscode . workspace . textDocuments ) ; await commands . startLanguageServer ( context , extensionContext ) ( ) ; } export function deactivate ( ) { if ( ! extensionContext . client ) { return undefined ; } const client = extensionContext . client ; extensionContext . client = undefined ; extensionContext . statusBar . refresh ( extensionContext ) ; vscode . commands . executeCommand ( "setContext" , ENABLEMENT_FLAG , false ) ; return client . stop ( ) ; } /** Internal function factory that returns a registerCommand function that is
 * bound to the extension context. */ function createRegisterCommand ( context ) { return function registerCommand ( name , factory ) : void { const fullName = `${ EXTENSION_NS }.${ name }` ; const command = factory ( context , extensionContext ) ; context . subscriptions . push ( vscode . commands . registerCommand ( fullName , command ) ) ; } ; }