vscode#HoverProvider TypeScript Examples

The following examples show how to use vscode#HoverProvider. 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: gcodeHoverProvider.ts    From vscode-gcode with MIT License 6 votes vote down vote up
export class gcodeHoverProvider implements HoverProvider {

    private dictionary: IDictionary
    
    constructor(dictionary: IDictionary){
        this.dictionary = dictionary
    }

    provideHover(document: TextDocument, position: Position, token: CancellationToken): ProviderResult<Hover> {
        const code = document.getText(document.getWordRangeAtPosition(position));
        const definition = this.dictionary.lookup(code);
        return definition == null ? null : new Hover(definition);
    }
}
Example #2
Source File: hoverProvider.ts    From vscode-stripe with MIT License 6 votes vote down vote up
class ClientHoverProvider implements HoverProvider {
  private delegateProvider: any;

  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 #3
Source File: ALHoverProvider.ts    From vscode-alxmldocumentation with MIT License 5 votes vote down vote up
export class ALHoverProvider implements HoverProvider {
    async provideHover(document: TextDocument, position: Position, token: CancellationToken) {   
        let result: MarkdownString = new MarkdownString();

        // retrieve source code from language server
        let alLangServerProxy = new ALLangServerProxy();     
        const alDefinition = await alLangServerProxy.GetALObjectFromDefinition(document.uri.toString(), position);
        if ((alDefinition === undefined) || (alDefinition.ALObject === null)) {
            return;
        }

        // find AL procedure by line no.
        let alProcedure: ALProcedure | undefined = alDefinition.ALObject.Procedures?.find(procedure => procedure.LineNo === alDefinition.Position.line);
        if ((alProcedure === undefined) || (alProcedure.ALDocumentation.Exists === ALDocumentationExists.No)) {
            return; // not found
        }

        let jsonDocumentation: any = await alDefinition.ALObject.GetDocumentationAsJsonObject(alProcedure);                
        // AL Language Version 6.x is providing simple XML Documentation capabilities. Do not push procedure summary in this case.
        if ((alLangServerProxy.GetALExtension()?.packageJSON.version < '6.0.0') || (alProcedure.ALDocumentation.Exists === ALDocumentationExists.Inherit)) {
            // add Summary to hover message.
            if ((jsonDocumentation.summary) && (jsonDocumentation.summary !== '')) {
                result.appendMarkdown(`${jsonDocumentation.summary} \n`);
            } else {
                return; // don't show w/o summary
            }
        }
        // add Remarks to hover message.
        if ((jsonDocumentation.remarks) && (jsonDocumentation.remarks.trim() !== '')) {
            result.appendMarkdown(`*${jsonDocumentation.remarks}*  \n`);
        } 

        // add Return to hover message.
        if ((alProcedure.Return !== undefined) && (alProcedure.Return.ALDocumentation.Exists === ALDocumentationExists.Yes)) {
            // convert XML Documentation to more readable JSON object.
            let returnDocumentation = ALDocCommentUtil.GetJsonFromALDocumentation(alProcedure.Return.ALDocumentation.Documentation);
            if ((returnDocumentation.returns) && (returnDocumentation.returns.trim() !== '')) {
                result.appendMarkdown(`${returnDocumentation.returns} \n`);
            }
        }
        
        // add Example to hover message.
        if (jsonDocumentation.example) {
            result.appendMarkdown(`#### Example \n`);
            result.appendMarkdown(`${jsonDocumentation.example.value} \n`);
            result.appendCodeblock(jsonDocumentation.example.code);
        }

        if (result.value !== '') {
            return new Hover(result);
        }
    }
}
Example #4
Source File: ahkHoverProvider.ts    From vscode-autohotkey with MIT License 5 votes vote down vote up
export class AhkHoverProvider implements HoverProvider {

    private snippetCache: Map<string, Snippet>;
    public constructor(context: ExtensionContext) {
        this.initSnippetCache(context);
    }

    public async provideHover(document: TextDocument, position: Position, token: CancellationToken) {

        const context = this.buildContext(document, position)

        const snippetHover = this.tryGetSnippetHover(context)
        if (snippetHover) {
            return snippetHover;
        }

        const method = await Parser.getMethodByName(document, context.word)
        if (method) {
            const markdonw = new MarkdownString("", true).appendCodeblock(method.full)
            if (method.comment) {
                markdonw.appendText(method.comment)
            }
            return new Hover(markdonw)
        }

        return null
    }

    private tryGetSnippetHover(context: Context): Hover {
        let snippetKey = context.word.toLowerCase();
        if (context.nextChart == "(") {
            snippetKey += "()"
        }
        const snippet = this.snippetCache.get(snippetKey)
        if (snippet) {
            const content = new MarkdownString(null, true)
                .appendCodeblock(snippet.body, 'ahk')
            if (snippet.description) {
                 content.appendText(snippet.description)
            }
            return new Hover(content)
        }
    }

    private buildContext(document: TextDocument, position: Position): Context {
        const line = position.line;
        const wordRange = document.getWordRangeAtPosition(position)
        let word = document.getText(wordRange);
        if (wordRange.start.character > 0) {
            const preChart = document.getText(new Range(line, wordRange.start.character - 1, line, wordRange.start.character))
            if (preChart == "#") {
                word = "#" + word;
            }
        }
        const nextChart = document.getText(new Range(line, wordRange.end.character, line, wordRange.end.character + 1))
        return { word, nextChart }
    }

    private initSnippetCache(context: ExtensionContext) {
        const ahk = JSON.parse(readFileSync(join(context.extensionPath, "snippets", "ahk.json"), "UTF8"));
        this.snippetCache = new Map<string, Snippet>();
        // tslint:disable-next-line: forin
        for (const key in ahk) {
            const snip = ahk[key] as Snippet;
            if (typeof snip.body === 'string') {
                snip.body = snip.body?.replace(/\d{1}:/g, "");
            }
            this.snippetCache.set(key.toLowerCase(), snip);
        }
    }

}
Example #5
Source File: gopExtraInfo.ts    From vscode-goplus with Apache License 2.0 5 votes vote down vote up
export class GoHoverProvider implements HoverProvider {
	private goPlusConfig: WorkspaceConfiguration | undefined;

	constructor(goPlusConfig?: WorkspaceConfiguration) {
		this.goPlusConfig = goPlusConfig;
	}
	
	public provideHover(document: TextDocument, position: Position, token: CancellationToken): Thenable<Hover> {
		if (!this.goPlusConfig) {
			this.goPlusConfig = getGoPlusConfig(document.uri);
		}
		let goPlusConfig = this.goPlusConfig;

		// Temporary fix to fall back to godoc if guru is the set docsTool
		if (goPlusConfig['docsTool'] === 'guru') {
			goPlusConfig = Object.assign({}, goPlusConfig, { docsTool: 'godoc' });
		}
		return definitionLocation(document, position, goPlusConfig, true, token).then(
			(definitionInfo) => {
				if (definitionInfo == null) {
					return null;
				}
				const lines = definitionInfo.declarationlines
					.filter((line) => line !== '')
					.map((line) => line.replace(/\t/g, '    '));
				let text;
				text = lines.join('\n').replace(/\n+$/, '');
				const hoverTexts = new vscode.MarkdownString();
				hoverTexts.appendCodeblock(text, 'go');
				if (definitionInfo.doc != null) {
					hoverTexts.appendMarkdown(definitionInfo.doc);
				}
				const hover = new Hover(hoverTexts);
				return hover;
			},
			() => {
				return null;
			}
		);
	}
}
Example #6
Source File: AbbreviationHoverProvider.ts    From vscode-lean4 with Apache License 2.0 5 votes vote down vote up
/**
 * Adds hover behaviour for getting translations of unicode characters.
 * Eg: "Type ⊓ using \glb or \sqcap"
 */
export class AbbreviationHoverProvider implements HoverProvider {
	constructor(
		private readonly config: AbbreviationConfig,
		private readonly abbreviations: AbbreviationProvider
	) {}

	provideHover(document: TextDocument, pos: Position): Hover | undefined {
		const context = document.lineAt(pos.line).text.substr(pos.character);
		const symbolsAtCursor = this.abbreviations.findSymbolsIn(context);
		const allAbbrevs = symbolsAtCursor.map((symbol) => ({
			symbol,
			abbrevs: this.abbreviations.getAllAbbreviations(symbol),
		}));

		if (
			allAbbrevs.length === 0 ||
			allAbbrevs.every((a) => a.abbrevs.length === 0)
		) {
			return undefined;
		}

		const leader = this.config.abbreviationCharacter.get();

		const hoverMarkdown = allAbbrevs
			.map(
				({ symbol, abbrevs }) =>
					`Type ${symbol} using ${abbrevs
						.map((a) => '`' + leader + a + '`')
						.join(' or ')}`
			)
			.join('\n\n');

		const maxSymbolLength = Math.max(
			...allAbbrevs.map((a) => a.symbol.length)
		);
		const hoverRange = new Range(pos, pos.translate(0, maxSymbolLength));

		return new Hover(hoverMarkdown, hoverRange);
	}
}
Example #7
Source File: element-hover-provider.ts    From element-ui-helper with MIT License 4 votes vote down vote up
export class ElementHoverProvier implements HoverProvider {
  private _position!: Position
  private _document!: TextDocument
  private _token!: CancellationToken
  private tagReg: RegExp = /<([\w-]+)\s*/g
  private attrReg: RegExp = /(?:\(|\s*)([\w-]+)=?/

  provideHover(document: TextDocument, position: Position, token: CancellationToken): ProviderResult<Hover> {
    this._document = document
    this._position = position
    this._token = token

    const tag: TagObject | undefined = this.getTag()

    if (!/^[E|e]l/.test(tag?.text || '')) {
      // 如果不是element的标签(E|el开头) 则返回 null 表示没有hover
      return null
    }

    const attr = this.getAttr()
    const range = this.getHoverRange(attr)

    return this.getHoverInstance(tag, attr, range)
  }

  /**
   * 获取标签
   */
  getTag(): TagObject | undefined {
    let line = this._position.line
    let tag: TagObject | string | undefined
    let txt = this.getTextAfterPosition(this._position)

    // 向前搜索 最多十行 搜索标签
    while (this._position.line - line < 10 && line >= 0) {
      if (line !== this._position.line) {
        txt = this._document.lineAt(line).text
      }
      tag = this.matchTag(this.tagReg, txt, line)
      if (tag === 'break') {
        return undefined
      }
      if (tag) {
        return <TagObject>tag
      }
      line--
    }
    return undefined
  }

  /**
   * 获取属性
   */
  getAttr(): string {
    const txt = this.getTextAfterPosition(this._position)
    let end = txt.length
    let start = txt.lastIndexOf(' ', this._position.character) + 1
    let parsedTxt = this._document.getText(new Range(this._position.line, start, this._position.line, end))
    return this.matchAttr(this.attrReg, parsedTxt)
  }

  /**
   * 获取高亮范围
   * @param attr 属性名称
   */
  getHoverRange(attr: string): Range {
    const line = this._document.lineAt(this._position.line).text
    const start = line.indexOf(attr)
    const end = start + attr.length
    const range = new Range(this._position.line, start, this._position.line, end)
    return range
  }

  /**
   * 匹配标签
   * @param reg 匹配模式串
   * @param txt 待匹配字符
   * @param line 匹配行
   */
  matchTag(reg: RegExp, txt: string, line: number): TagObject | string | undefined {
    let match: RegExpExecArray | null
    let arr: TagObject[] = []

    if (/<\/?[-\w]+[^<>]*>[\s\w]*<?\s*[\w-]*$/.test(txt) || (this._position.line === line && (/^\s*[^<]+\s*>[^</>]*$/.test(txt) || /[^<>]*<$/.test(txt[txt.length - 1])))) {
      return 'break'
    }
    while ((match = reg.exec(txt))) {
      arr.push({
        text: match[1],
        offset: this._document.offsetAt(new Position(line, match.index))
      })
    }
    return arr.pop()
  }

  /**
   * 匹配标签
   *
   * @param reg 匹配模式
   * @param txt 待匹配字符
   */
  matchAttr(reg: RegExp, txt: string): string {
    let match: RegExpExecArray | null
    match = reg.exec(txt)
    if (!/"[^"]*"/.test(txt) && match) {
      return match[1]
    }
    return ''
  }

  /**
   * 获取前置内容
   * @param position 位置信息
   */
  getTextBeforePosition(position: Position): string {
    const wordRange = this._document.getWordRangeAtPosition(position)
    const start = new Position(position.line, 0)
    const end = wordRange?.end || position
    const range = new Range(start, end)
    return this._document.getText(range)
  }

  /**
   * 获取当前位置直到单词结束的内容
   *
   * @param position 文档位置
   */
  getTextAfterPosition(position: Position): string {
    const wordRange = this._document.getWordRangeAtPosition(position)
    const start = new Position(position.line, 0)
    let endIndex = (wordRange?.end || position).character
    const text = this._document.lineAt(position).text
    while (endIndex < text.length && /[\w-]/.test(text.charAt(endIndex))) {
      endIndex++
    }
    const end = new Position(position.line, endIndex)
    const range = new Range(start, end)
    return this._document.getText(range)
  }

  /**
   * 获取Hover实例
   *
   * @param tag 标签
   * @param attr 属性
   * @param range 区域
   */
  getHoverInstance(tag: TagObject | undefined, attr: string, range: Range) {
    const config = workspace.getConfiguration().get<ExtensionConfigutation>('element-ui-helper')
    const language = config?.language || ExtensionLanguage.cn

    const kebabCaseTag = toKebabCase(tag?.text)
    const kebabCaseAttr = toKebabCase(attr)

    return this.createHoverInstance(language, kebabCaseTag, kebabCaseAttr, range)
  }

  /**
   * 创建Hover实例
   *
   * @param language 语言
   * @param tag 标签
   * @param attr 属性
   * @param range 范围
   */
  createHoverInstance(language: ExtensionLanguage, tag: string, attr: string, range: Range): null | Hover {
    let document: Record<string, any> = localDocument[language]
    if (tag === attr) {
      attr = ''
    }
    if (Object.prototype.hasOwnProperty.call(document, tag)) {
      const tagDocument = document[tag]
      const hoverMarkdownStrings: MarkdownString[] = []
      Object.keys(tagDocument).forEach((key: string) => {
        const hoverMarkdownString: MarkdownString = HoverDocumentGenerator.getInstance().generate<ElDocument>(tagDocument, key, tag, attr, language)
        if (hoverMarkdownString) {
          hoverMarkdownStrings.push(hoverMarkdownString)
        }
      })
      return new Hover(hoverMarkdownStrings, range)
    } else {
      return null
    }
  }
}
Example #8
Source File: hoverProvider.ts    From vscode-stripe with MIT License 4 votes vote down vote up
export class JavaHoverProvider implements HoverProvider {
  constructor(readonly languageClient: LanguageClient) {
    this.languageClient = languageClient;
  }

  async provideHover(
    document: TextDocument,
    position: Position,
    token: CancellationToken,
  ): Promise<Hover | undefined> {
    let contents: any[] = [];
    let range;

    const params = {
      textDocument: this.languageClient.code2ProtocolConverter.asTextDocumentIdentifier(document),
      position: this.languageClient.code2ProtocolConverter.asPosition(position),
    };

    // get javs doc convent from server
    const hoverResponse = await this.languageClient.sendRequest(HoverRequest.type, params, token);

    // parse for stripe api hover content
    let stripeApiHoverContent;
    if (hoverResponse && hoverResponse.contents && Array.isArray(hoverResponse.contents)) {
      const stripeFullClassPath = Object.entries(hoverResponse.contents[0])
        .filter((item) => item[0] === 'value')
        .filter((item) => item[1].includes('com.stripe.model'));
      if (stripeFullClassPath.length > 0) {
        const stripeMethod = stripeFullClassPath[0][1].split(' ')[1].split('(')[0];
        const url = getJavaApiDocLink(stripeMethod);
        if (url) {
          stripeApiHoverContent = new MarkdownString(
            'See this method in the [Stripe API Reference](' + url + ')',
          );
          stripeApiHoverContent.isTrusted = true;
        }
      }
    }

    if (!!stripeApiHoverContent) {
      contents = contents.concat([stripeApiHoverContent]);
    }

    // get contributed hover commands from third party extensions.
    const contributedCommands: Command[] = await this.getContributedHoverCommands(params, token);

    if (contributedCommands.length > 0) {
      const contributedContent = new MarkdownString(
        contributedCommands.map((command) => this.convertCommandToMarkdown(command)).join(' | '),
      );
      contributedContent.isTrusted = true;
      contents = contents.concat([contributedContent]);
    }

    // combine all hover contents with java docs from server
    const serverHover = this.languageClient.protocol2CodeConverter.asHover(hoverResponse);
    if (serverHover && serverHover.contents) {
      contents = contents.concat(serverHover.contents);
      range = serverHover.range;
    }

    return new Hover(contents, range);
  }

  async getContributedHoverCommands(
    params: TextDocumentPositionParams,
    token: CancellationToken,
  ): Promise<Command[]> {
    const contributedCommands: Command[] = [];
    for (const provideFn of hoverCommandRegistry) {
      try {
        if (token.isCancellationRequested) {
          break;
        }

        // eslint-disable-next-line no-await-in-loop
        const commands = (await provideFn(params, token)) || [];
        commands.forEach((command: Command) => {
          contributedCommands.push(command);
        });
      } catch (error) {
        return [];
      }
    }

    return contributedCommands;
  }

  private convertCommandToMarkdown(command: Command): string {
    return `[${command.title}](command:${command.command}?${encodeURIComponent(
      JSON.stringify(command.arguments || []),
    )} "${command.tooltip || command.command}")`;
  }
}