/******************************************************************************
 * Copyright 2021 TypeFox GmbH
 * This program and the accompanying materials are made available under the
 * terms of the MIT License, which is available in the project root.
 ******************************************************************************/ import { CancellationToken , DocumentHighlight , DocumentHighlightKind , DocumentHighlightParams } from 'vscode-languageserver' ; import { NameProvider } from '../references/naming' ; import { References } from '../references/references' ; import { LangiumServices } from '../services' ; import { AstNode , CstNode , Reference } from '../syntax-tree' ; import { findLeafNodeAtOffset , findLocalReferences , getDocument } from '../utils/ast-util' ; import { MaybePromise } from '../utils/promise-util' ; import { LangiumDocument } from '../workspace/documents' ; export interface DocumentHighlighter { throws throws findHighlights ( document , params , cancelToken ? ) : MaybePromise < DocumentHighlight [ ] | undefined > ; } export class DefaultDocumentHighlighter implements DocumentHighlighter { protected readonly references : References ; protected readonly nameProvider : NameProvider ; constructor ( services ) { this . references = services . references . References ; this . nameProvider = services . references . NameProvider ; } findHighlights ( document , params ) { const rootNode = document . parseResult . value . $cstNode ; if ( ! rootNode ) { return undefined ; } const selectedNode = findLeafNodeAtOffset ( rootNode , document . textDocument . offsetAt ( params . position ) ) ; if ( ! selectedNode ) { return undefined ; } const targetAstNode = this . references . findDeclaration ( selectedNode ) ?. element ; if ( targetAstNode ) { const refs = [ ] ; if ( getDocument ( targetAstNode ) . uri . toString ( ) === document . uri . toString ( ) ) { const nameNode = this . findNameNode ( targetAstNode ) ; if ( nameNode ) { refs . push ( [ nameNode , this . getHighlightKind ( nameNode ) ] ) ; } } findLocalReferences ( targetAstNode , rootNode . element ) . forEach ( ref => { refs . push ( [ ref . $refNode , this . getHighlightKind ( ref . $refNode , ref ) ] ) ; } ) ; return refs . map ( ( [ node , kind ] ) => DocumentHighlight . create ( node . range , kind ) ) ; } return undefined ; } protected findNameNode ( node ) { const nameNode = this . nameProvider . getNameNode ( node ) ; if ( nameNode ) return nameNode ; return node . $cstNode ; } /**
     * Override this method to determine the highlight kind of the given CST node.
     */ protected getHighlightKind ( node , reference ? ) { if ( reference ) { return DocumentHighlightKind . Read ; } else { return DocumentHighlightKind . Text ; } } }