vscode-languageclient/node#LanguageClient TypeScript Examples

The following examples show how to use vscode-languageclient/node#LanguageClient. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: doctorCommand.ts    From coffeesense with MIT License 6 votes vote down vote up
export function generateDoctorCommand(client: LanguageClient) {
  return async () => {
    const LANGUAGE_ID = 'coffeescript'
    if(vscode.window.activeTextEditor?.document.languageId !== LANGUAGE_ID) {
      return vscode.window.showInformationMessage(`Failed to showGeneratedJavascript. Make sure the current file is a ${LANGUAGE_ID} file.`);
    }
    const active_filename = vscode.window.activeTextEditor!.document.fileName

    const result = (await client.sendRequest('$/doctor', { fileName: active_filename })) as string;
    const showText = result.slice(0, 1000) + '....';
    const action = await vscode.window.showInformationMessage(showText, { modal: true }, 'Ok', 'Copy', 'Show JS');
    if (action === 'Copy') {
      await vscode.env.clipboard.writeText(result);
    } else if (action === 'Show JS') {
      const new_doc = await vscode.workspace.openTextDocument({ language: 'javascript' })
      const new_editor = await vscode.window.showTextDocument(new_doc)
      const js = JSON.parse(result).js
      await new_editor.edit(t => t.insert(new vscode.Position(0, 0), js), { undoStopBefore: true, undoStopAfter: false })
    }
  };
}
Example #2
Source File: hoverProvider.ts    From vscode-stripe with MIT License 6 votes vote down vote up
async function provideHoverCommand(
  languageClient: LanguageClient,
  params: TextDocumentPositionParams,
  token: CancellationToken,
): Promise<Command[] | undefined> {
  const response = await languageClient.sendRequest(
    FindLinks.type,
    {
      type: 'superImplementation',
      position: params,
    },
    token,
  );
  if (response && response.length) {
    const location = response[0];
    let tooltip;
    if (location.kind === 'method') {
      tooltip = `Go to super method '${location.displayName}'`;
    } else {
      tooltip = `Go to super implementation '${location.displayName}'`;
    }

    return [
      {
        title: 'Go to Super Implementation',
        command: javaCommands.NAVIGATE_TO_SUPER_IMPLEMENTATION_COMMAND,
        tooltip,
        arguments: [
          {
            uri: encodeBase64(location.uri),
            range: location.range,
          },
        ],
      },
    ];
  }
}
Example #3
Source File: lsp.ts    From vscode-sql-notebook with MIT License 6 votes vote down vote up
start(config: LspConfig) {
    let serverOptions: ServerOptions = {
      command: config.binPath,
      args: [],
    };

    let clientOptions: LanguageClientOptions = {
      documentSelector: [{ language: 'sql' }],
      initializationOptions: {
        disableCodeAction: true,
        connectionConfig: {
          driver: config.driver,
          user: config.user,
          passwd: config.password,

          host: config.host,
          port: config.port,

          dbName: config.database,

          proto: 'tcp',
        },
      },
      outputChannel: vscode.window.createOutputChannel('sqls'),
    };

    this.client = new LanguageClient('sqls', serverOptions, clientOptions);
    this.client.start();
  }
Example #4
Source File: hoverProvider.ts    From vscode-stripe with MIT License 6 votes vote down vote up
async provideHover(
    document: TextDocument,
    position: Position,
    token: CancellationToken,
  ): Promise<Hover | undefined> {
    const languageClient: LanguageClient | undefined = await getActiveJavaLanguageClient();

    if (!languageClient) {
      return undefined;
    }

    if (javaServerMode === ServerMode.STANDARD) {
      if (!this.delegateProvider) {
        this.delegateProvider = createClientHoverProvider(languageClient);
      }
      return this.delegateProvider.provideHover(document, position, token);
    } else {
      const params = {
        textDocument: languageClient.code2ProtocolConverter.asTextDocumentIdentifier(document),
        position: languageClient.code2ProtocolConverter.asPosition(position),
      };
      const hoverResponse = await languageClient.sendRequest(HoverRequest.type, params, token);
      return languageClient.protocol2CodeConverter.asHover(hoverResponse);
    }
  }
Example #5
Source File: CompiledCodeContentProvider.ts    From language-tools with MIT License 6 votes vote down vote up
constructor(private getLanguageClient: () => LanguageClient) {
        this.subscriptions.push(
            workspace.onDidChangeTextDocument(
                debounce(async (changeEvent) => {
                    if (changeEvent.document.languageId !== 'svelte') {
                        return;
                    }

                    const srcUri = changeEvent.document.uri.toString();
                    if (this.watchedSourceUri.has(srcUri)) {
                        this.didChangeEmitter.fire(toSvelteSchemeUri(srcUri));
                    }
                }, 500)
            )
        );

        window.onDidChangeVisibleTextEditors((editors) => {
            const previewEditors = editors.filter(
                (editor) => editor?.document?.uri?.scheme === SVELTE_URI_SCHEME
            );
            this.watchedSourceUri = new Set(
                previewEditors.map((editor) => fromSvelteSchemeUri(editor.document.uri, true))
            );
        });
    }
Example #6
Source File: languageServerClient.ts    From vscode-stripe with MIT License 6 votes vote down vote up
static activateUniversalServer(
    context: ExtensionContext,
    outputChannel: OutputChannel,
    serverOptions: ServerOptions,
    telemetry: Telemetry,
  ) {
    outputChannel.appendLine('Starting universal language server');
    const universalClientOptions: LanguageClientOptions = {
      // Register the server for stripe-supported languages. dotnet is not yet supported.
      documentSelector: [
        {scheme: 'file', language: 'javascript'},
        {scheme: 'file', language: 'typescript'},
        {scheme: 'file', language: 'go'},
        // {scheme: 'file', language: 'java'},
        {scheme: 'file', language: 'php'},
        {scheme: 'file', language: 'python'},
        {scheme: 'file', language: 'ruby'},
      ],
      synchronize: {
        fileEvents: workspace.createFileSystemWatcher('**/.clientrc'),
      },
    };

    const universalClient = new LanguageClient(
      'stripeLanguageServer',
      'Stripe Language Server',
      serverOptions,
      universalClientOptions,
    );

    universalClient.onTelemetry((data: any) => {
      const eventData = data.data || null;
      telemetry.sendEvent(data.name, eventData);
    });

    universalClient.start();
    outputChannel.appendLine('Universal language server is running');
    telemetry.sendEvent('universalLanguageServerStarted');
  }
Example #7
Source File: coffeescriptMain.ts    From coffeesense with MIT License 6 votes vote down vote up
function registerRestartLSPCommand(context: vscode.ExtensionContext, client: LanguageClient) {
  context.subscriptions.push(
    vscode.commands.registerCommand('coffeesense.restartLSP', () =>
      displayInitProgress(
        client
          .stop()
          .then(() => client.start())
          .then(() => client.onReady())
      )
    )
  );
}
Example #8
Source File: extension.ts    From language-tools with MIT License 6 votes vote down vote up
export function activate(context: ExtensionContext) {
    // The extension is activated on TS/JS/Svelte files because else it might be too late to configure the TS plugin:
    // If we only activate on Svelte file and the user opens a TS file first, the configuration command is issued too late.
    // We wait until there's a Svelte file open and only then start the actual language client.
    const tsPlugin = new TsPlugin(context);
    let lsApi: { getLS(): LanguageClient } | undefined;

    if (workspace.textDocuments.some((doc) => doc.languageId === 'svelte')) {
        lsApi = activateSvelteLanguageServer(context);
        tsPlugin.askToEnable();
    } else {
        const onTextDocumentListener = workspace.onDidOpenTextDocument((doc) => {
            if (doc.languageId === 'svelte') {
                lsApi = activateSvelteLanguageServer(context);
                tsPlugin.askToEnable();
                onTextDocumentListener.dispose();
            }
        });

        context.subscriptions.push(onTextDocumentListener);
    }

    // This API is considered private and only exposed for experimenting.
    // Interface may change at any time. Use at your own risk!
    return {
        /**
         * As a function, because restarting the server
         * will result in another instance.
         */
        getLanguageServer() {
            if (!lsApi) {
                lsApi = activateSvelteLanguageServer(context);
            }

            return lsApi.getLS();
        }
    };
}
Example #9
Source File: syntaxLanguageClient.ts    From vscode-stripe with MIT License 5 votes vote down vote up
public initialize(
    clientOptions: LanguageClientOptions,
    serverOptions: ServerOptions,
  ) {
    if (!serverOptions) {
      return;
    }

    const newClientOptions: LanguageClientOptions = Object.assign({}, clientOptions, {
      errorHandler: {
        error: (error: string, message: string) => {
          console.log(message);
          console.log(error);

          return ErrorAction.Continue;
        },
        closed: () => CloseAction.DoNotRestart,
      },
    });

    this.languageClient = new LanguageClient(
      'java',
      EXTENSION_NAME_SYNTAX,
      serverOptions,
      newClientOptions,
    );

    this.languageClient.onReady().then(() => {
      if (this.languageClient) {
        this.languageClient.onNotification(StatusNotification.type, (report: {type: any}) => {
          switch (report.type) {
            case 'Started':
              this.status = ClientStatus.Started;
              break;
            case 'Error':
              this.status = ClientStatus.Error;
              break;
            default:
              break;
          }
        });
      }
    });

    this.status = ClientStatus.Initialized;
  }
Example #10
Source File: extension.ts    From language-tools with MIT License 5 votes vote down vote up
function createLanguageServer(serverOptions: ServerOptions, clientOptions: LanguageClientOptions) {
    return new LanguageClient('svelte', 'Svelte', serverOptions, clientOptions);
}
Example #11
Source File: extension.ts    From vscode-teal with MIT License 5 votes vote down vote up
export function activate(context: ExtensionContext) {
	// The server is implemented in node
	let serverModule = context.asAbsolutePath(path.join('out', 'server', 'server.js'));

	// The debug options for the server
	// --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging
	let debugOptions = { execArgv: ['--nolazy', '--inspect=6009'] };

	// If the extension is launched in debug mode then the debug server options are used
	// Otherwise the run options are used
	let serverOptions: ServerOptions = {
		run: { module: serverModule, transport: TransportKind.ipc },
		debug: {
			module: serverModule,
			transport: TransportKind.ipc,
			options: debugOptions
		}
	};

	// Options to control the language client
	let clientOptions: LanguageClientOptions = {
		// Register the server for .tl files and tlconfig.lua
		documentSelector: [
			{ scheme: 'file', language: 'teal' },
			{ scheme: 'file', language: 'lua', pattern: '**/tlconfig.lua' }
		],
		synchronize: {
			// Notify the server about file changes to .tl and .lua files contained in the workspace
			fileEvents: workspace.createFileSystemWatcher('**/*.{tl,lua}')
		},
		outputChannelName: 'Teal Language Server'
	};

	// Create the language client and start the client.
	client = new LanguageClient(
		'TealLanguageServer',
		'Teal Language Server',
		serverOptions,
		clientOptions
	);

	// Start the client. This will also launch the server
	client.start();
}
Example #12
Source File: client.ts    From vala-vscode with MIT License 5 votes vote down vote up
constructor(_context: ExtensionContext) {
        this.config = workspace.getConfiguration('vala', window.activeTextEditor?.document.uri);
        let serverModule = this.languageServerPath;

        if (serverModule == null)
            return;

        let clientOptions: LanguageClientOptions = {
            documentSelector: ['vala', 'genie'],
            revealOutputChannelOn: RevealOutputChannelOn.Info
        };

        // default environment in non-debug mode
        let runEnvironment = { ...process.env };
        
        if (this.config.debugMode)
            runEnvironment['G_MESSAGES_DEBUG'] = 'all';
        if (this.config.failOnCriticals)
            runEnvironment['G_DEBUG'] = 'fatal-criticals';

        let serverOptions: ServerOptions = {
            run: {
                command: serverModule,
                transport: TransportKind.stdio,
                options: {
                    env: runEnvironment
                }
            },
            debug: {
                command: serverModule,
                options: {
                    env: {
                        ...process.env,
                        G_MESSAGES_DEBUG: 'all'
                    }
                },
                transport: TransportKind.stdio
            }
        };

        this.ls = new LanguageClient('Vala Language Server', serverOptions, clientOptions);

        commands.registerTextEditorCommand('vala.showBaseSymbol', this.peekSymbol);
        commands.registerTextEditorCommand('vala.showHiddenSymbol', this.peekSymbol);

        this.ls.start();
    }
Example #13
Source File: extension.ts    From vscode-css-variables with MIT License 5 votes vote down vote up
export function activate(context: ExtensionContext) {
  // The server is implemented in node
  const serverModule = context.asAbsolutePath(
    path.join('server', 'out', 'server.js')
  );
  // The debug options for the server
  // --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging
  const debugOptions = { execArgv: ['--nolazy', '--inspect=6009'] };

  // If the extension is launched in debug mode then the debug server options are used
  // Otherwise the run options are used
  const serverOptions: ServerOptions = {
    run: { module: serverModule, transport: TransportKind.ipc },
    debug: {
      module: serverModule,
      transport: TransportKind.ipc,
      options: debugOptions,
    },
  };

  // Options to control the language client
  const clientOptions: LanguageClientOptions = {
    // Register the server for plain text documents
    documentSelector: [
      'onLanguage:svelte',
      'onLanguage:vue',
      'onLanguage:vue-html',
      'onLanguage:vue-postcss',
      'onLanguage:scss',
      'onLanguage:postcss',
      'onLanguage:less',
      'onLanguage:css',
      'onLanguage:html',
      'onLanguage:javascript',
      'onLanguage:javascriptreact',
      'onLanguage:typescript',
      'onLanguage:typescriptreact',
      'onLanguage:source.css.styled',
    ].map((event) => ({
      scheme: 'file',
      language: event.split(':')[1],
    })),
    synchronize: {
      // Notify the server about file changes to '.clientrc files contained in the workspace
      fileEvents: [
        workspace.createFileSystemWatcher('**/*.css'),
        workspace.createFileSystemWatcher('**/*.scss'),
        workspace.createFileSystemWatcher('**/*.sass'),
        workspace.createFileSystemWatcher('**/*.less'),
      ],
    },
  };

  // Create the language client and start the client.
  client = new LanguageClient(
    'cssVariables',
    'CSS Variables Language Server',
    serverOptions,
    clientOptions
  );

  // Start the client. This will also launch the server
  client.start();
}
Example #14
Source File: extension.ts    From zls-vscode with MIT License 5 votes vote down vote up
export function activate(context: ExtensionContext) {
  const zlsPath = workspace.getConfiguration('zigLanguageClient').get('path', '');
  const debugLog = workspace.getConfiguration('zigLanguageClient').get('debugLog', false);
  
  if (!zlsPath) {
    window.showErrorMessage("Failed to find zls executable! Please specify its path in your settings with `zigLanguageClient.path`.");
    return;
  }

  let serverOptions: ServerOptions = {
    command: zlsPath,
    args: debugLog ? [ "--debug-log" ] : []
  };

  // Options to control the language client
  let clientOptions: LanguageClientOptions = {
    documentSelector: [{ scheme: 'file', language: 'zig' }],
    outputChannel: window.createOutputChannel("Zig Language Server")
  };  

  // Create the language client and start the client.
  client = new LanguageClient(
    'zigLanguageClient',
    'Zig Language Server Client',
    serverOptions,
    clientOptions
  );

  client.start();

  vscode.commands.registerCommand("zls.start", () => {
    client.start();
  });

  vscode.commands.registerCommand("zls.stop", async () => {
    await client.stop();
  });

  vscode.commands.registerCommand("zls.restart", async () => {
    await client.stop();
    client.start();
  });
}
Example #15
Source File: leanclient.ts    From vscode-lean4 with Apache License 2.0 5 votes vote down vote up
private client: LanguageClient | undefined
Example #16
Source File: lsp.ts    From vscode-sql-notebook with MIT License 5 votes vote down vote up
private client: LanguageClient | null;
Example #17
Source File: dafnyLanguageClient.ts    From ide-vscode with MIT License 5 votes vote down vote up
export class DafnyLanguageClient extends LanguageClient {
  private readonly diagnosticsListeners: DiagnosticListener[];

  // eslint-disable-next-line max-params
  private constructor(id: string, name: string, serverOptions: ServerOptions, clientOptions: LanguageClientOptions, diagnosticsListeners: DiagnosticListener[], forceDebug?: boolean) {
    super(id, name, serverOptions, clientOptions, forceDebug);
    this.diagnosticsListeners = diagnosticsListeners;
  }

  public getCounterExamples(param: ICounterExampleParams): Promise<ICounterExampleItem[]> {
    return this.sendRequest<ICounterExampleItem[]>('dafny/counterExample', param);
  }

  public static argumentsToCommandLine(launchArguments: string[]): string {
    return launchArguments.map(oneArgument =>
      (/\s|"|\\/.exec(oneArgument))
        ? '"' + oneArgument.replace(/\\/g, '\\\\').replace(/"/g, '\\"') + '"'
        : oneArgument
    ).join(' ');
  }

  public static async create(context: ExtensionContext, statusOutput: OutputChannel): Promise<DafnyLanguageClient> {
    const { path: dotnetExecutable } = await getDotnetExecutablePath();
    const launchArguments = [ getLanguageServerRuntimePath(context), ...getLanguageServerLaunchArgs() ];
    statusOutput.appendLine(`Language server arguments: ${DafnyLanguageClient.argumentsToCommandLine(launchArguments)}`);
    const serverOptions: ServerOptions = {
      run: { command: dotnetExecutable, args: launchArguments },
      debug: { command: dotnetExecutable, args: launchArguments }
    };
    const diagnosticsListeners: ((uri: Uri, diagnostics: Diagnostic[]) => void)[] = [];
    const clientOptions: LanguageClientOptions = {
      documentSelector: [ DafnyDocumentFilter ],
      diagnosticCollectionName: LanguageServerId,
      middleware: {
        handleDiagnostics: (uri: Uri, diagnostics: Diagnostic[], next: HandleDiagnosticsSignature) => {
          for(const handler of diagnosticsListeners) {
            handler(uri, diagnostics);
          }
          next(uri, diagnostics);
        }
      }
    };
    return new DafnyLanguageClient(LanguageServerId, LanguageServerName, serverOptions, clientOptions, diagnosticsListeners);
  }

  public onGhostDiagnostics(callback: (params: IGhostDiagnosticsParams) => void): Disposable {
    return this.onNotification('dafny/ghost/diagnostics', callback);
  }

  public onVerificationStatusGutter(callback: (params: IVerificationGutterStatusParams) => void): Disposable {
    return this.onNotification('dafny/verification/status/gutter', callback);
  }

  public onCompilationStatus(callback: (params: ICompilationStatusParams) => void): Disposable {
    return this.onNotification('dafny/compilation/status', callback);
  }

  public onServerVersion(callback: (version: string) => void): Disposable {
    return this.onNotification('dafnyLanguageServerVersionReceived', callback);
  }

  public onPublishDiagnostics(callback: (uri: Uri, diagnostics: Diagnostic[]) => void): void {
    this.diagnosticsListeners.push(callback);
  }

  // TODO Legacy verification status messages
  public onVerificationStarted(callback: (params: IVerificationStartedParams) => void): Disposable {
    return this.onNotification('dafny/verification/started', callback);
  }

  public onVerificationCompleted(callback: (params: IVerificationCompletedParams) => void): Disposable {
    return this.onNotification('dafny/verification/completed', callback);
  }
}
Example #18
Source File: extension.ts    From fower with MIT License 5 votes vote down vote up
export function activate(context: ExtensionContext) {
  // The server is implemented in node
  const serverModule = context.asAbsolutePath(path.join('server', 'out', 'server.js'))

  // The debug options for the server
  const debugOptions = { execArgv: ['--nolazy', '--inspect=6011'] }

  // If the extension is launched in debug mode then the debug server options are used
  // Otherwise the run options are used
  const serverOptions: ServerOptions = {
    run: { module: serverModule, transport: TransportKind.ipc },
    debug: {
      module: serverModule,
      transport: TransportKind.ipc,
      options: debugOptions,
    },
  }

  // Options to control the language client
  const clientOptions: LanguageClientOptions = {
    // Register the server for plain text documents
    // documentSelector: [{ scheme: 'file', language: 'plaintext' }],
    documentSelector: [
      { scheme: 'file', language: 'vue' },
      {
        scheme: 'file',
        language: 'svelte',
      },
    ],
    middleware: {
      provideCompletionItem: async (document, position, context, token, next) => {
        return await next(document, position, context, token)
      },
    },
    synchronize: {
      // Notify the server about file changes to '.clientrc files contained in the workspace
      fileEvents: workspace.createFileSystemWatcher('**/.clientrc'),
    },
  }

  // Create the language client and start the client.
  client = new LanguageClient(CLIENT_ID, CLIENT_NAME, serverOptions, clientOptions)

  // Start the client. This will also launch the server
  client.start()
}
Example #19
Source File: extension.ts    From macro-executor with MIT License 5 votes vote down vote up
client: LanguageClient
Example #20
Source File: extension.ts    From svlangserver with MIT License 5 votes vote down vote up
export function activate(context: ExtensionContext) {
    let serverModule = context.asAbsolutePath(path.join('dist', 'svlangserver.js'));

    let serverOptions: ServerOptions = {
        run: {module: serverModule, transport: TransportKind.ipc},
        debug: {module: serverModule, transport: TransportKind.ipc}
    }

    let clientOptions: LanguageClientOptions = {
        outputChannelName: "SVLangServer",
        documentSelector: selector as string[]
    }

    client = new LanguageClient('systemverilog', "svlangserver LSP", serverOptions, clientOptions);

    // For debugging only
    //client.trace = Trace.Verbose;

    let getHierCmdHandler = () => {
        let selectedText: string;
        let editor = window.activeTextEditor;
        if (!!editor) {
            selectedText = editor.document.getText(editor.selection);
        }

        window.showInputBox({
            placeHolder: "Module/interface Name",
            prompt: "Hierarchy to be reported for module/interface",
            value: selectedText
        }).then((cntnrName: string) => {
            if (!!cntnrName) {
                client.sendRequest('workspace/executeCommand', {'command': 'systemverilog.report_hierarchy', 'arguments': [cntnrName]});
            }
        });
    };

    context.subscriptions.push(commands.registerCommand('systemverilog.get_hierarchy', getHierCmdHandler));
    context.subscriptions.push(client.start());

    client.onReady().then(() => {
        workspace.onDidChangeConfiguration(() => {
            client.sendNotification('workspace/didChangeConfiguration', getSettings(client));
        });
    });
}
Example #21
Source File: standardLanguageClient.ts    From vscode-stripe with MIT License 5 votes vote down vote up
public initialize(
    clientOptions: LanguageClientOptions,
    serverOptions: ServerOptions,
  ) {
    if (!serverOptions || this.status !== ClientStatus.Uninitialized) {
      return;
    }

    this.languageClient = new LanguageClient(
      'java',
      EXTENSION_NAME_STANDARD,
      serverOptions,
      clientOptions,
    );

    this.languageClient.onReady().then(() => {
      if (!this.languageClient) {
        return;
      }

      this.languageClient.onNotification(StatusNotification.type, (report: StatusReport) => {
        switch (report.type) {
          case 'ServiceReady':
            updateServerMode(ServerMode.STANDARD);
            break;
          case 'Started':
            this.status = ClientStatus.Started;
            break;
          case 'Error':
            this.status = ClientStatus.Error;
            break;
          case 'Starting':
          case 'Message':
            // message goes to progress report instead
            break;
        }
      });
    });

    this.status = ClientStatus.Initialized;
  }
Example #22
Source File: language-server.ts    From vscode-cadence with Apache License 2.0 5 votes vote down vote up
constructor (ctx: ExtensionContext, config: Config, emulatorState: EmulatorState, activeAccount: Account | null) {
    // Init running state with false and update, when client is connected to server
    this.running = false

    const activeAccountName = (activeAccount != null) ? activeAccount.name : ''
    const activeAccountAddress = (activeAccount != null) ? activeAccount.address : ''
    const { configPath } = config

    this.client = new LanguageClient(
      'cadence',
      'Cadence',
      {
        command: config.flowCommand,
        args: START_LANGUAGE_SERVER_ARGS
      },
      {
        documentSelector: [{ scheme: 'file', language: 'cadence' }],
        synchronize: {
          configurationSection: 'cadence'
        },
        initializationOptions: {
          accessCheckMode: config.accessCheckMode,
          configPath,
          emulatorState,
          activeAccountName,
          activeAccountAddress
        }
      }
    )

    this.client
      .onReady()
      .then(() =>
        window.showInformationMessage('Cadence language server started')
      )
      .catch((err: Error) =>
        window.showErrorMessage(`Cadence language server failed to start: ${err.message}`)
      )

    this.client.onDidChangeState((e: StateChangeEvent) => {
      this.running = e.newState === State.Running
    })

    const clientDisposable = this.client.start()
    ctx.subscriptions.push(clientDisposable)
  }
Example #23
Source File: client.ts    From coffeesense with MIT License 5 votes vote down vote up
export function initializeLanguageClient(lspModulePath: string): LanguageClient {
  const debugOptions = { execArgv: ['--nolazy', '--inspect=6005'] };

  const documentSelector: DocumentFilter[] = [{ language: 'coffeescript', scheme: 'file' }];
  const config = vscode.workspace.getConfiguration();

  let serverPath;

  const devLspPackagePath = config.get('coffeesense.dev.lspPath', '');
  if (devLspPackagePath && devLspPackagePath !== '' && existsSync(devLspPackagePath)) {
    serverPath = resolve(devLspPackagePath, 'dist/coffeescriptServerMain.js');
  } else {
    serverPath = lspModulePath;
  }

  const runExecArgv: string[] = [];
  const lspPort = config.get('coffeesense.dev.lspPort');
  if (lspPort !== -1) {
    runExecArgv.push(`--inspect=${lspPort}`);
    console.log(`Will launch LSP in port: ${lspPort}`);
  }

  const serverOptions: ServerOptions = {
    run: { module: serverPath, transport: TransportKind.ipc, options: { execArgv: runExecArgv } },
    debug: { module: serverPath, transport: TransportKind.ipc, options: debugOptions }
  };

  const clientOptions: LanguageClientOptions = {
    documentSelector,
    synchronize: {
      configurationSection: ['coffeesense', 'javascript', 'typescript', 'files.associations'],
      fileEvents: vscode.workspace.createFileSystemWatcher('{**/*.js,**/*.ts,**/*.json}', false, false, true)
    },
    initializationOptions: {
    },
    revealOutputChannelOn: RevealOutputChannelOn.Never
  };

  return new LanguageClient('coffeesense', 'CoffeeSense Language Server', serverOptions, clientOptions);
}
Example #24
Source File: extension.ts    From vscode-microprofile with Apache License 2.0 5 votes vote down vote up
languageClient: LanguageClient
Example #25
Source File: extension.ts    From language-tools with MIT License 4 votes vote down vote up
function addRenameFileListener(getLS: () => LanguageClient) {
    workspace.onDidRenameFiles(async (evt) => {
        const oldUri = evt.files[0].oldUri.toString(true);
        const parts = oldUri.split(/\/|\\/);
        const lastPart = parts[parts.length - 1];
        // If user moves/renames a folder, the URI only contains the parts up to that folder,
        // and not files. So in case the URI does not contain a '.', check for imports to update.
        if (
            lastPart.includes('.') &&
            !['.ts', '.js', '.json', '.svelte'].some((ending) => lastPart.endsWith(ending))
        ) {
            return;
        }

        window.withProgress(
            { location: ProgressLocation.Window, title: 'Updating Imports..' },
            async () => {
                const editsForFileRename = await getLS().sendRequest<LSWorkspaceEdit | null>(
                    '$/getEditsForFileRename',
                    // Right now files is always an array with a single entry.
                    // The signature was only designed that way to - maybe, in the future -
                    // have the possibility to change that. If that ever does, update this.
                    // In the meantime, just assume it's a single entry and simplify the
                    // rest of the logic that way.
                    {
                        oldUri,
                        newUri: evt.files[0].newUri.toString(true)
                    }
                );
                const edits = editsForFileRename?.documentChanges?.filter(TextDocumentEdit.is);
                if (!edits) {
                    return;
                }

                const workspaceEdit = new WorkspaceEdit();
                // We need to take into account multiple cases:
                // - A Svelte file is moved/renamed
                //      -> all updates will be related to that Svelte file, do that here. The TS LS won't even notice the update
                // - A TS/JS file is moved/renamed
                //      -> all updates will be related to that TS/JS file
                //      -> let the TS LS take care of these updates in TS/JS files, do Svelte file updates here
                // - A folder with TS/JS AND Svelte files is moved/renamed
                //      -> all Svelte file updates are handled here
                //      -> all TS/JS file updates that consist of only TS/JS import updates are handled by the TS LS
                //      -> all TS/JS file updates that consist of only Svelte import updates are handled here
                //      -> all TS/JS file updates that are mixed are handled here, but also possibly by the TS LS
                //         if the TS plugin doesn't prevent it. This trades risk of broken updates with certainty of missed updates
                edits.forEach((change) => {
                    const isTsOrJsFile =
                        change.textDocument.uri.endsWith('.ts') ||
                        change.textDocument.uri.endsWith('.js');
                    const containsSvelteImportUpdate = change.edits.some((edit) =>
                        edit.newText.endsWith('.svelte')
                    );
                    if (isTsOrJsFile && !containsSvelteImportUpdate) {
                        return;
                    }

                    change.edits.forEach((edit) => {
                        if (
                            isTsOrJsFile &&
                            !TsPlugin.isEnabled() &&
                            !edit.newText.endsWith('.svelte')
                        ) {
                            // TS plugin enabled -> all mixed imports are handled here
                            // TS plugin disabled -> let TS/JS path updates be handled by the TS LS, Svelte here
                            return;
                        }

                        // Renaming a file should only result in edits of existing files
                        workspaceEdit.replace(
                            Uri.parse(change.textDocument.uri),
                            new Range(
                                new Position(edit.range.start.line, edit.range.start.character),
                                new Position(edit.range.end.line, edit.range.end.character)
                            ),
                            edit.newText
                        );
                    });
                });
                workspace.applyEdit(workspaceEdit);
            }
        );
    });
}
Example #26
Source File: leanclient.ts    From vscode-lean4 with Apache License 2.0 4 votes vote down vote up
async restart(): Promise<void> {
        const startTime = Date.now()

        console.log('Restarting Lean Language Server')
        if (this.isStarted()) {
            await this.stop()
        }

        this.restartingEmitter.fire(undefined)
        this.toolchainPath = this.storageManager.getLeanPath();
        if (!this.toolchainPath) this.toolchainPath = toolchainPath();
        const version = this.storageManager.getLeanVersion();
        const env = addServerEnvPaths(process.env);
        if (serverLoggingEnabled()) {
            env.LEAN_SERVER_LOG_DIR = serverLoggingPath()
        }

        let executable = (this.toolchainPath) ? join(this.toolchainPath, 'bin', 'lake') : 'lake';

        // check if the lake process will start (skip it on scheme: 'untitled' files)
        let useLake = lakeEnabled() && this.folderUri && this.folderUri.scheme === 'file';
        if (useLake) {
            let knownDate = false;
            const lakefile = Uri.joinPath(this.folderUri, 'lakefile.lean')
            if (!await fileExists(new URL(lakefile.toString()))) {
                useLake = false;
            }
            else {
                // see if we can avoid the more expensive checkLakeVersion call.
                const date = await this.checkToolchainVersion(this.folderUri);
                if (date){
                    // Feb 16 2022 is when the 3.1.0.pre was released.
                    useLake = date >= new Date(2022, 1, 16);
                    knownDate = true;
                }
                if (useLake && !knownDate){
                    useLake = await this.checkLakeVersion(executable, version);
                }
            }
        }

        if (!useLake) {
            executable = (this.toolchainPath) ? join(this.toolchainPath, 'bin', 'lean') : 'lean';
        }

        let options = version ? ['+' + version] :[]
        if (useLake) {
            options = options.concat(['serve', '--'])
        } else{
            options = options.concat(['--server'])
        }

        // Add folder name to command-line so that it shows up in `ps aux`.
        if (this.folderUri) {
            options.push('' + this.folderUri.fsPath)
        } else {
            options.push('untitled')
        }

        const serverOptions: ServerOptions = {
            command: executable,
            args: options.concat(serverArgs()),
            options: {
                cwd: this.folderUri?.fsPath,
                env
            }
        }

        const documentSelector: DocumentFilter = {
            language: 'lean4'
        }

        if (this.folderUri){
            documentSelector.scheme = this.folderUri.scheme
            if (this.folderUri.scheme !== 'untitled') {
                documentSelector.pattern = `${this.folderUri.fsPath}/**/*`
            }
        }

        const clientOptions: LanguageClientOptions = {
            outputChannel: this.outputChannel,
            documentSelector: [documentSelector],
            workspaceFolder: this.workspaceFolder,
            initializationOptions: {
                editDelay: getElaborationDelay(), hasWidgets: true,
            },
            connectionOptions: {
                maxRestartCount: 0,
                cancellationStrategy: undefined as any,
            },
            middleware: {
                handleDiagnostics: (uri, diagnostics, next) => {
                    next(uri, diagnostics);
                    if (!this.client) return;
                    const uri_ = c2pConverter.asUri(uri);
                    const diagnostics_ = [];
                    for (const d of diagnostics) {
                        const d_: ls.Diagnostic = {
                            ...c2pConverter.asDiagnostic(d),
                        };
                        diagnostics_.push(d_);
                    }
                    this.diagnosticsEmitter.fire({uri: uri_, diagnostics: diagnostics_});
                },

                didOpen: async () => {
                    // Note: as per the LSP spec: An open notification must not be sent more than once
                    // without a corresponding close notification send before. This means open and close
                    // notification must be balanced and the max open count for a particular textDocument
                    // is one.  So this even does nothing the notification is handled by the
                    // openLean4Document method below after the 'lean4' languageId is established and
                    // it has weeded out documents opened to invisible editors (like 'git:' schemes and
                    // invisible editors created for Ctrl+Hover events.  A side effect of unbalanced
                    // open/close notification is leaking 'lean --worker' processes.
                    // See https://github.com/microsoft/vscode/issues/78453).
                    return;
                },

                didChange: async (data, next) => {
                    await next(data);
                    if (!this.running || !this.client) return; // there was a problem starting lean server.
                    const params = c2pConverter.asChangeTextDocumentParams(data);
                    this.didChangeEmitter.fire(params);
                },

                didClose: async (doc, next) => {
                    if (!this.isOpen.delete(doc.uri.toString())) {
                        return;
                    }
                    await next(doc);
                    if (!this.running || !this.client) return; // there was a problem starting lean server.
                    const params = c2pConverter.asCloseTextDocumentParams(doc);
                    this.didCloseEmitter.fire(params);
                },

                provideDocumentHighlights: async (doc, pos, ctok, next) => {
                    const leanHighlights = await next(doc, pos, ctok);
                    if (leanHighlights?.length) return leanHighlights;

                    // vscode doesn't fall back to textual highlights,
                    // so we need to do that manually
                    await new Promise((res) => setTimeout(res, 250));
                    if (ctok.isCancellationRequested) return;

                    const wordRange = doc.getWordRangeAtPosition(pos);
                    if (!wordRange) return;
                    const word = doc.getText(wordRange);

                    const highlights: DocumentHighlight[] = [];
                    const text = doc.getText();
                    const nonWordPattern = '[`~@$%^&*()-=+\\[{\\]}⟨⟩⦃⦄⟦⟧⟮⟯‹›\\\\|;:\",./\\s]|^|$'
                    const regexp = new RegExp(`(?<=${nonWordPattern})${escapeRegExp(word)}(?=${nonWordPattern})`, 'g')
                    for (const match of text.matchAll(regexp)) {
                        const start = doc.positionAt(match.index ?? 0)
                        highlights.push({
                            range: new Range(start, start.translate(0, match[0].length)),
                            kind: DocumentHighlightKind.Text,
                        })
                    }

                    return highlights;
                }
            },
        }
        this.client = new LanguageClient(
            'lean4',
            'Lean 4',
            serverOptions,
            clientOptions
        )
        let insideRestart = true;
        patchConverters(this.client.protocol2CodeConverter, this.client.code2ProtocolConverter)
        try {
            this.client.onDidChangeState(async (s) => {
                // see https://github.com/microsoft/vscode-languageserver-node/issues/825
                if (s.newState === State.Starting) {
                    console.log('client starting');
                } else if (s.newState === State.Running) {
                    const end = Date.now()
                    console.log('client running, started in ', end - startTime, 'ms');
                    this.running = true; // may have been auto restarted after it failed.
                    if (!insideRestart) {
                        this.restartedEmitter.fire(undefined)
                    }
                } else if (s.newState === State.Stopped) {
                    this.stoppedEmitter.fire('Lean language server has stopped. ');
                    console.log('client has stopped or it failed to start');
                    this.running = false;
                    if (!this.noPrompt){
                        await this.showRestartMessage();
                    }
                }
            })
            this.client.start()
            await this.client.onReady();
            // tell the new client about the documents that are already open!
            for (const key of this.isOpen.keys()) {
                const doc = this.isOpen.get(key);
                if (doc) this.notifyDidOpen(doc);
            }
            // if we got this far then the client is happy so we are running!
            this.running = true;
        } catch (error) {
            this.outputChannel.appendLine('' + error);
            this.serverFailedEmitter.fire('' + error);
            insideRestart = false;
            return;
        }

        // HACK(WN): Register a default notification handler to fire on custom notifications.
        // A mechanism to do this is provided in vscode-jsonrpc. One can register a `StarNotificationHandler`
        // here: https://github.com/microsoft/vscode-languageserver-node/blob/b2fc85d28a1a44c22896559ee5f4d3ba37a02ef5/jsonrpc/src/common/connection.ts#L497
        // which fires on any LSP notifications not in the standard, for example the `$/lean/..` ones.
        // However this mechanism is not exposed in vscode-languageclient, so we hack around its implementation.
        const starHandler = (method: string, params_: any) => {
            if (method === '$/lean/fileProgress' && this.client) {
                const params = params_ as LeanFileProgressParams;
                const uri = p2cConverter.asUri(params.textDocument.uri)
                this.progressChangedEmitter.fire([uri.toString(), params.processing]);
                // save the latest progress on this Uri in case infoview needs it later.
                this.progress.set(uri, params.processing);
            }

            this.customNotificationEmitter.fire({method, params: params_});
        };
        // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
        this.client.onNotification(starHandler as any, () => {});

        // Reveal the standard error output channel when the server prints something to stderr.
        // The vscode-languageclient library already takes care of writing it to the output channel.
        (this.client as any)._serverProcess.stderr.on('data', () => {
            this.client?.outputChannel.show(true);
        });

        this.restartedEmitter.fire(undefined)
        insideRestart = false;
    }
Example #27
Source File: client.ts    From vscode-q with MIT License 4 votes vote down vote up
export function activate(context: ExtensionContext): void {

    // extra language configurations
    languages.setLanguageConfiguration('q', {
        onEnterRules: [
            {
                // eslint-disable-next-line no-useless-escape
                beforeText: /^(?!\s+).*[\(\[{].*$/,
                afterText: /^[)}\]]/,
                action: {
                    indentAction: IndentAction.None,
                    appendText: '\n '
                }
            },
            {
                // eslint-disable-next-line no-useless-escape
                beforeText: /^\s[)}\]];?$/,
                action: {
                    indentAction: IndentAction.Outdent
                }
            },
            {
                // eslint-disable-next-line no-useless-escape
                beforeText: /^\/.*$/,
                action: {
                    indentAction: IndentAction.None,
                    appendText: '/ '
                }
            }
        ]
    });

    // append space to start [,(,{
    languages.registerDocumentFormattingEditProvider('q', {
        provideDocumentFormattingEdits(document: TextDocument): TextEdit[] {
            const textEdit: TextEdit[] = [];
            for (let i = 0; i < document.lineCount; i++) {
                const line = document.lineAt(i);
                if (line.isEmptyOrWhitespace) {
                    continue;
                }

                if (line.text.match('^[)\\]}]')) {
                    textEdit.push(TextEdit.insert(line.range.start, ' '));
                }
            }
            return textEdit;
        }
    });

    // <-- init
    QStatusBarManager.create(context);
    QStatusBarManager.updateConnStatus(undefined);
    // q-server-explorer
    const qServers = new QServerTree('root', null);
    const qRoot = new QDictTreeItem('root', null);
    const qHistory = HistoryTreeItem.createHistoryTree();
    window.registerTreeDataProvider('q-servers', qServers);
    qServers.refresh();
    window.registerTreeDataProvider('q-explorer', qRoot);
    window.registerTreeDataProvider('q-history', qHistory);
    qHistory.refresh();
    QueryConsole.createOrGet();
    QueryView.setExtensionPath(context.extensionPath);
    QueryGrid.setExtensionPath(context.extensionPath);
    AddServer.setExtensionPath(context.extensionPath);
    ChartView.setExtensionPath(context.extensionPath);
    // --> init


    // <-- configuration
    const queryMode = workspace.getConfiguration().get('q-client.queryMode');
    QConnManager.setQueryMode(queryMode as string);
    // -->

    commands.registerCommand(
        'q-client.refreshEntry', () => qServers.refresh());

    commands.registerCommand(
        'q-explorer.toggleAutoRefresh', () => {
            QConnManager.autoRefreshExplorer = !QConnManager.autoRefreshExplorer;
            window.showInformationMessage(`Auto Refresh Explorer ${QConnManager.autoRefreshExplorer ? 'On' : 'Off'}`);
        });

    // q cfg input
    commands.registerCommand(
        'q-client.addEntry',
        () => {
            AddServer.createOrShow();
        });

    commands.registerCommand(
        'q-client.editEntry',
        (qConn: QConn) => {
            AddServer.createOrShow();
            AddServer.update(qConn);
        });

    commands.registerCommand(
        'q-client.deleteEntry',
        (qConn: QConn) => {
            window.showInputBox(
                { prompt: `Confirm to Remove Server '${qConn.uniqLabel.replace(',', '-')}' (Y/n)` }
            ).then(value => {
                if (value === 'Y') {
                    QConnManager.current?.removeCfg(qConn.uniqLabel);

                }
            });
        });

    commands.registerCommand(
        'q-client.reactions',
        async () => {
            const option = await window.showQuickPick(
                ['1 - Raising an Issue', '2 - Writing a Review', '3 - Creating a Pull Request', '4 - Buying Me a Beer', '5 - Q & A'],
                { placeHolder: 'Contribute to vscode-q by' });
            switch (option?.[0]) {
                case '1':
                    env.openExternal(Uri.parse('https://github.com/jshinonome/vscode-q/issues'));
                    break;
                case '2':
                    env.openExternal(Uri.parse('https://marketplace.visualstudio.com/items?itemName=jshinonome.vscode-q&ssr=false#review-details'));
                    break;
                case '3':
                    env.openExternal(Uri.parse('https://github.com/jshinonome/vscode-q/blob/master/CONTRIBUTING.md'));
                    break;
                case '4':
                    env.openExternal(Uri.parse('https://www.buymeacoffee.com/jshinonome'));
                    break;
                case '5':
                    env.openExternal(Uri.parse('https://github.com/jshinonome/vscode-q/discussions'));
            }
        });

    commands.registerCommand(
        'q-client.connectEntry',
        async () => {
            const connManager = QConnManager.current;
            if (connManager) {
                const quickPickItems: QuickPickItem[] = connManager.qCfg.map(qcfg => {
                    return {
                        label: qcfg.uniqLabel,
                        description: `\`:${qcfg.host}:${qcfg.port}`
                    };
                });
                const recentlyUsedItems: QuickPickItem[] = Array.from(connManager.qConnPool.values())
                    .filter(qConn => !(qConn.conn == undefined))
                    .map(qConn => {
                        return {
                            label: qConn.uniqLabel,
                            description: `\`:${qConn.host}:${qConn.port}`
                        };
                    });
                const allItems: QuickPickItem[] = [
                    {
                        label: 'Connected',
                        kind: QuickPickItemKind.Separator
                    },
                    ...recentlyUsedItems,
                    {
                        label: 'Process',
                        kind: QuickPickItemKind.Separator
                    },
                    ...quickPickItems
                ];
                const item = await window.showQuickPick(
                    allItems,
                    { placeHolder: 'Connect to a q process' });
                if (item) {
                    commands.executeCommand('q-client.connect', item.label);
                    return item.label;
                }
            }
        });

    commands.registerCommand(
        'q-client.connect',
        uniqLabel => {
            QConnManager.current?.connect(uniqLabel);
        });

    commands.registerCommand(
        'q-client.tagEntry',
        async (qConn: QConn) => {
            qConn.tags = await window.showInputBox({
                prompt: `Tags for '${qConn.label}' separate by ',' (e.g. 'dev,quant,tca')`
            }) ?? '';
            QConnManager.current?.addCfg(qConn);
        });

    commands.registerCommand(
        'q-client.switchMode',
        async () => {
            const mode = await window.showQuickPick(['Console', 'Grid', 'Visualization'],
                { placeHolder: 'Please choose a query mode from the list below' });
            if (mode) {
                window.showInformationMessage(`Switch to Query ${mode} Mode`);
                QConnManager.setQueryMode(mode);
                QStatusBarManager.updateQueryModeStatus();
            }
        });

    commands.registerCommand(
        'q-client.toggleLimitQuery',
        () => {
            QConnManager.current?.toggleLimitQuery();
        });

    commands.registerCommand(
        'q-client.abortQuery',
        () => {
            QConnManager.current?.abortQuery();
        });

    commands.registerCommand(
        'q-client.exportServers',
        () => {
            QConnManager.current?.exportCfg();
        });

    commands.registerCommand(
        'q-client.importServers',
        () => {
            QConnManager.current?.importCfg();
        });


    commands.registerCommand(
        'q-explorer.refreshEntry', () => qRoot.refresh());

    const previewQueryLimit = workspace.getConfiguration().get('q-client.expl.prevQueryLimit');

    commands.registerCommand('q-explorer.preview', (item: TreeItem) => {
        switch (item.contextValue) {
            case 'qtable':
                QConnManager.current?.sync(
                    `{[t;l]$[@[{x in value \`.Q.pt};t;{'"preview feature requires v3.5+ kdb"}];select from t where date=last date, i<l;select from t where i<l]}[\`${item.label};${previewQueryLimit}]`);
                break;
            case 'qfunction':
                QueryConsole.current?.append((item as QFunctionTreeItem).getBody(), 0, 'cached');
                break;
            default:
                if (item.label)
                    QConnManager.current?.sync(item.label as string);
        }
    });

    commands.registerCommand('q-explorer.click', label => {
        console.log(label);
    });

    context.subscriptions.push(
        commands.registerCommand('q-history.rerun', (history) => {
            if (QConnManager.current?.activeConn?.uniqLabel === history.uniqLabel)
                QConnManager.current?.sync(history.query);
            else
                QConnManager.current?.connect(history.uniqLabel, history.query);
        })
    );

    enum QueryCodeType {
        Line,
        Selection,
        Block
    }

    enum QueryTarget {
        Process,
        Terminal
    }

    async function queryCode(code: QueryCodeType, target: QueryTarget): Promise<void> {
        const editor = window.activeTextEditor;
        if (editor) {
            let n = 0;
            let query = '';
            const params = {
                textDocument: {
                    uri: editor.document.uri.toString(),
                },
                position: editor.selection.active,
            };
            switch (code) {
                case QueryCodeType.Line:
                    n = editor.selection.active.line;
                    query = editor.document.lineAt(n).text;
                    n = 0;
                    break;
                case QueryCodeType.Selection:
                    query = editor?.document.getText(
                        new Range(editor.selection.start, editor.selection.end)
                    );
                    break;
                case QueryCodeType.Block:
                    ({ query, n } = await client.sendRequest('onQueryBlock', params));
                    break;
            }
            if (query) {
                if (code === QueryCodeType.Line && query.startsWith('/<=>')) {
                    const uniqLabel = query.substring(4).trim();
                    commands.executeCommand('q-client.connect', uniqLabel);
                } else {
                    switch (target) {
                        case QueryTarget.Process:
                            QConnManager.current?.sync(query);
                            break;
                        case QueryTarget.Terminal:
                            sendToCurrentTerm(query.replace(/(\r\n|\n|\r)/gm, ''));
                            break;
                    }
                }
            }
            if (n > 0) {
                let line = editor.document.lineAt(n).text;
                while (n < editor.document.lineCount && (line === '' || line.startsWith('/'))) {
                    n++;
                    line = editor.document.lineAt(n).text;
                }
                const range = editor.document.lineAt(n).range;
                editor.selection = new Selection(range.start, range.start);
                editor.revealRange(new Range(range.start, range.start));
            }
        }
    }

    context.subscriptions.push(
        commands.registerCommand('q-client.queryCurrentLine', async () => {
            queryCode(QueryCodeType.Line, QueryTarget.Process);
        })
    );

    context.subscriptions.push(
        commands.registerCommand('q-client.querySelection', () => {
            queryCode(QueryCodeType.Selection, QueryTarget.Process);
        })
    );

    context.subscriptions.push(
        commands.registerCommand('q-client.queryBlock', () => {
            queryCode(QueryCodeType.Block, QueryTarget.Process);
        })
    );

    context.subscriptions.push(
        commands.registerCommand('q-term.sendCurrentLine', () => {
            queryCode(QueryCodeType.Line, QueryTarget.Terminal);
        })
    );

    context.subscriptions.push(
        commands.registerCommand('q-term.sendSelection', () => {
            queryCode(QueryCodeType.Selection, QueryTarget.Terminal);
        })
    );

    context.subscriptions.push(
        commands.registerCommand('q-term.sendBlock', () => {
            queryCode(QueryCodeType.Block, QueryTarget.Terminal);
        })
    );

    context.subscriptions.push(
        commands.registerCommand('q-client.terminal.run', () => {
            const filepath = window.activeTextEditor?.document.fileName;
            if (filepath)
                runQFile(filepath);
        })
    );

    context.subscriptions.push(
        commands.registerCommand('q-client.insertActiveConnLabel', () => {
            const editor = window.activeTextEditor;
            if (editor) {
                editor.edit(editBuilder => {
                    if (QConnManager.current?.activeConn?.uniqLabel) {
                        editBuilder.insert(editor.selection.active, '/<=>' + QConnManager.current?.activeConn?.uniqLabel);
                    }
                });
            }
        })
    );

    if (window.registerWebviewPanelSerializer) {
        // Make sure we register a serializer in activation event
        window.registerWebviewPanelSerializer(QueryView.viewType, {
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            async deserializeWebviewPanel(webviewPanel: WebviewPanel) {
                QueryView.revive(webviewPanel, context.extensionPath);
            }
        });
    }

    workspace.onDidChangeConfiguration(e => {
        if (e.affectsConfiguration('q-client') && !e.affectsConfiguration('q-client.term')) {
            window.showInformationMessage('Reload/Restart vscode to Make the Configuration Take Effect.');
        } else if (e.affectsConfiguration('q-server')) {
            const cfg = workspace.getConfiguration('q-server.sourceFiles');
            client.sendNotification('analyzeSourceCode', { globsPattern: cfg.get('globsPattern'), ignorePattern: cfg.get('ignorePattern') });
        }
    });

    // q language server
    const qls = path.join(context.extensionPath, 'dist', 'server.js');

    // The debug options for the server
    // runs the server in Node's Inspector mode for debugging
    const debugOptions = { execArgv: ['--nolazy', '--inspect=6018'] };

    // If launched in debug mode then the debug server options are used
    // Otherwise the run options are used
    const serverOptions: ServerOptions = {
        run: { module: qls, transport: TransportKind.ipc },
        debug: {
            module: qls,
            transport: TransportKind.ipc,
            options: debugOptions
        }
    };

    // Options to control the language client
    const clientOptions: LanguageClientOptions = {
        // Register the server for plain text documents
        documentSelector: [{ scheme: 'file', language: 'q' }],
        synchronize: {
            // Notify the server about q file changes
            fileEvents: workspace.createFileSystemWatcher('**/*.q')
        }
    };

    // Create the language client and start the client.
    const client = new LanguageClient(
        'qLangServer',
        'q Language Server',
        serverOptions,
        clientOptions
    );

    context.subscriptions.push(
        commands.registerCommand('q-client.sendServerCache', code => {
            client.sendNotification('analyzeServerCache', code);
        })
    );

    context.subscriptions.push(
        commands.registerCommand('q-client.sendOnHover', hoverItems => {
            client.sendNotification('prepareOnHover', hoverItems);
        })
    );

    client.start().then(() => {
        const cfg = workspace.getConfiguration('q-server.sourceFiles');
        client.sendNotification('analyzeSourceCode', { globsPattern: cfg.get('globsPattern'), ignorePattern: cfg.get('ignorePattern') });
    });
}
Example #28
Source File: hoverProvider.test.ts    From vscode-stripe with MIT License 4 votes vote down vote up
suite('JavaHoverProvider', () => {
  let sandbox: sinon.SinonSandbox;

  setup(() => {
    sandbox = sinon.createSandbox();
  });

  teardown(() => {
    sandbox.restore();
  });

  suite('provideHover', () => {
    let languageClient: LanguageClient;
    let document: TextDocument;
    let position: Position;
    let token: CancellationToken;

    setup(() => {
      languageClient = new LanguageClient(
        'java',
        'Test Language Client',
        getMockJavaServerOptions(),
        mocks.javaClientOptions,
      );
      sandbox.stub(languageClient.code2ProtocolConverter, 'asTextDocumentIdentifier');
      sandbox.stub(languageClient.code2ProtocolConverter, 'asPosition');
    });

    test('retrieve api deep link for stripe java method', async () => {
      const javaHoverProvider = new JavaHoverProvider(languageClient);
      const expectedApiDocLink = 'https://stripe.com/docs/api/file_links/create';

      sandbox.stub(languageClient, 'sendRequest').returns(Promise.resolve(getServerResponse(true)));
      sandbox.stub(javaClientUtils, 'getJavaApiDocLink').returns(expectedApiDocLink);
      sandbox.stub(javaHoverProvider, 'getContributedHoverCommands').returns(Promise.resolve([]));
      sandbox.stub(languageClient.protocol2CodeConverter, 'asHover').returns({contents: []});
      const hoverContent = await javaHoverProvider.provideHover(document, position, token);

      if (!!hoverContent) {
        const contentMarktdown: MarkdownString = hoverContent.contents[0] as MarkdownString;
        assert.strictEqual(
          contentMarktdown.value,
          `See this method in the [Stripe API Reference](${expectedApiDocLink})`,
        );
      } else {
        throw new assert.AssertionError();
      }
    });

    test('no api deep link for internal stripe method', async () => {
      const javaHoverProvider = new JavaHoverProvider(languageClient);
      const apiDocLink = 'https://stripe.com/docs/api/file_links/create';

      sandbox
        .stub(languageClient, 'sendRequest')
        .returns(Promise.resolve(getServerResponse(false)));
      sandbox.stub(javaClientUtils, 'getJavaApiDocLink').returns(apiDocLink);
      sandbox.stub(javaHoverProvider, 'getContributedHoverCommands').returns(Promise.resolve([]));
      sandbox.stub(languageClient.protocol2CodeConverter, 'asHover').returns({contents: []});
      const hoverContent = await javaHoverProvider.provideHover(document, position, token);

      if (!!hoverContent) {
        assert.strictEqual(hoverContent.contents.length, 0);
      } else {
        throw new assert.AssertionError();
      }
    });

    test('no api deep link for unknown stripe method', async () => {
        const javaHoverProvider = new JavaHoverProvider(languageClient);

        sandbox
          .stub(languageClient, 'sendRequest')
          .returns(Promise.resolve(getServerResponse(true)));
        sandbox.stub(javaClientUtils, 'getJavaApiDocLink').returns('');
        sandbox.stub(javaHoverProvider, 'getContributedHoverCommands').returns(Promise.resolve([]));
        sandbox.stub(languageClient.protocol2CodeConverter, 'asHover').returns({contents: []});
        const hoverContent = await javaHoverProvider.provideHover(document, position, token);

        if (!!hoverContent) {
          assert.strictEqual(hoverContent.contents.length, 0);
        } else {
          throw new assert.AssertionError();
        }
      });
  });
});
Example #29
Source File: extension.ts    From macro-executor with MIT License 4 votes vote down vote up
export function activate(context: ExtensionContext) {

	// The server is implemented in node
	let serverModule = context.asAbsolutePath(
		path.join('server', 'out', 'server.js')
	);

	let debugOptions = { execArgv: ['--nolazy', '--inspect=6011'], cwd: process.cwd() };
	let serverOptions: ServerOptions = {
		run: { module: serverModule, transport: TransportKind.ipc, options: { cwd: process.cwd() } },
		debug: {
			module: serverModule,
			transport: TransportKind.ipc,
			options: debugOptions
		}
	};

	let clientOptions: LanguageClientOptions = {
		documentSelector: [{ language: 'macro', scheme: 'file' }],
		initializationOptions: workspace.getConfiguration('macro'),
		synchronize: {
			fileEvents: workspace.createFileSystemWatcher('**/*.{[sS][rR][cC],[dD][eE][fF],[lL][nN][kK]}')
		},		
		diagnosticCollectionName: 'macro',
		progressOnInitialization: true,
		revealOutputChannelOn: RevealOutputChannelOn.Never,	
		middleware: {

			executeCommand: async (command:string, args:any[], next:ExecuteCommandSignature) => {
				if (command === 'macro.codelens.references') {
					const arg:CodeLensReferenceArgument = args[0];


					const position = client.protocol2CodeConverter.asPosition(arg.position);
					const locations:Location[] = [];
					for (const location of arg.locations){
						locations.push(client.protocol2CodeConverter.asLocation(location));
					}

					if (Window.activeTextEditor) {
						commands.executeCommand('editor.action.showReferences', Window.activeTextEditor.document.uri, position, locations);
					}
				}
				else if (command === 'macro.action.refactorsequeces' || command === 'macro.action.addsequeces') {
					function validate(input:string): string | null {
						return Number.isInteger(Number(input)) ? null : 'Integer expected';
					}

					const config = workspace.getConfiguration('macro');
					let start = undefined;
					if (command === 'macro.action.refactorsequeces') {
						start = await Window.showInputBox({
							prompt: 'Start sequence number',
							value: config.sequence.base,
							validateInput: validate
						});
					}
		
					const increment = await Window.showInputBox({
						prompt: 'Sequence number increment',
						value: config.sequence.increment,
						validateInput: validate
					});

					if (Window.activeTextEditor) {
						if (command === 'macro.action.addsequeces' && increment) {
							return next(command, [Window.activeTextEditor.document.uri.toString(), Window.activeTextEditor.selection.start, increment]);
						} 
						else if (command === 'macro.action.refactorsequeces' && start && increment) {
							return next(command, [Window.activeTextEditor.document.uri.toString(), Window.activeTextEditor.selection.start, start, increment]);
						}
					}
				}
			},
			workspace : {
				configuration: async (params, _token, _next): Promise<any[]> => {
					if (params.items === undefined) {
						return [];
					}
					const result: (ConfigurationSettings | null)[] = [];
					for (const item of params.items) {
						if (item.section || !item.scopeUri) {
							result.push(null);
							continue;
						}
						const resource = client.protocol2CodeConverter.asUri(item.scopeUri);
						const workspaceFolder = Workspace.getWorkspaceFolder(resource);
						const config = workspace.getConfiguration('macro', workspaceFolder);
						const settings: ConfigurationSettings = {
							codelens: config.get('codelens'),
							lint:config.get('lint', {}),
							sequence: config.get('sequence'),
							validate: config.get('validate'),
							keywords: config.get('keywords'),
						};
		
						if (workspaceFolder !== undefined) {
							settings.workspaceFolder = {
								name: workspaceFolder.name,
								uri: client.code2ProtocolConverter.asUri(workspaceFolder.uri),
							};
						}
						result.push(settings);
					}
					return result;
				}
			}
		} as any
	};


	// Create the language client and start the client.
	client = new LanguageClient(
		'macroLanguageServer',
		'Macro Language Server',
		serverOptions,
		clientOptions
	);

	disposables.add(registerCommands());
	context.subscriptions.push(disposables);
	context.subscriptions.push(client.start());
}