private async setupCustomOutputChannels()

in src/extension/src/lspclient.ts [389:446]


  private async setupCustomOutputChannels(): Promise<void> {
    // Clean up any existing output channels and tailed files.
    this.cleanupCustomOutput()

    const infoFileJson: {string: string} = await this.readServerInfoFile()
    for (const [key, outputFilePath] of Object.entries(infoFileJson)) {
      // Only watch files that are specified in the info file and have a key in the format of "output:sample".
      if (!key.startsWith('output:') || outputFilePath == undefined) {
        continue
      }

      // Extract the display name from the key and set up the channel.
      const channelID = key?.split(':')[1] ?? key
      const outputChannelName = `Uber LSP Output: ${channelID}`
      const channel = vscode.window.createOutputChannel(outputChannelName)
      channel.appendLine(`INFO: Output from file: ${outputFilePath}`)
      const currentEntry: customOutputChannel = {
        channel: channel,
        id: channelID,
      }
      this.customOutputChannels.push(currentEntry)

      this.outputChannelClient?.appendLine(
        `INFO: Added ${channelID} channel to watch output from ${outputFilePath}.`
      )

      // Begin tailing the file, and append any new lines to the output channel.
      // For memory usage and ease of navigation, limit the number of lines shown in the output panel to CUSTOM_OUTPUT_MAX_LINES.
      try {
        currentEntry.tail = new Tail(outputFilePath)
        let lines = 0
        currentEntry.tail.on('line', async (line: string) => {
          if (lines > CUSTOM_OUTPUT_MAX_LINES) {
            channel.clear()
            channel.appendLine(
              `INFO: Showing most recent lines. See prior output in: ${outputFilePath}`
            )
            lines = 0
          }
          channel.appendLine(line)
          lines++
        })

        // Stop watching on error or deleted file.
        // The output channel will remain available until the next time the client is restarted.
        currentEntry.tail.on('error', async (err: Error) => {
          channel.appendLine(`ERROR: ${err.message}`)
          currentEntry.tail!.unwatch()
        })
      } catch (err) {
        const errMsg = err instanceof Error ? err.message : String(err)
        currentEntry.channel.appendLine(
          `ERROR: Unable to display output in this channel. ${errMsg}`
        )
      }
    }
    return
  }