/********************************************************************************
 * Copyright (C) 2018 Red Hat, Inc. and others.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the Eclipse
 * Public License v. 2.0 are satisfied: GNU General Public License, version 2
 * with the GNU Classpath Exception which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 ********************************************************************************/ import { LanguagesExt , PLUGIN_RPC_CONTEXT , LanguagesMain , SerializedLanguageConfiguration , SerializedRegExp , SerializedOnEnterRule , SerializedIndentationRule , Position , Selection , RawColorInfo , WorkspaceEditDto , PluginInfo } from '../common/plugin-api-rpc' ; import { RPCProtocol } from '../common/rpc-protocol' ; import * as theia from '@theia/plugin' ; import { DocumentsExtImpl } from './documents' ; import { PluginModel } from '../common/plugin-protocol' ; import { Disposable , URI } from './types-impl' ; import { UriComponents } from '../common/uri-components' ; import { CompletionContext , CompletionResultDto , Completion , SerializedDocumentFilter , SignatureHelp , Hover , DocumentHighlight , Range , TextEdit , FormattingOptions , Definition , DocumentLink , CodeLensSymbol , DocumentSymbol , ReferenceContext , Location , ColorPresentation , RenameLocation , SignatureHelpContext , CodeActionContext , CodeAction , FoldingRange , SelectionRange , CallHierarchyDefinition , CallHierarchyReference , ChainedCacheId } from '../common/plugin-api-rpc-model' ; import { CompletionAdapter } from './languages/completion' ; import { Diagnostics } from './languages/diagnostics' ; import { SignatureHelpAdapter } from './languages/signature' ; import { HoverAdapter } from './languages/hover' ; import { DocumentHighlightAdapter } from './languages/document-highlight' ; import { DocumentFormattingAdapter } from './languages/document-formatting' ; import { RangeFormattingAdapter } from './languages/range-formatting' ; import { OnTypeFormattingAdapter } from './languages/on-type-formatting' ; import { DefinitionAdapter } from './languages/definition' ; import { ImplementationAdapter } from './languages/implementation' ; import { TypeDefinitionAdapter } from './languages/type-definition' ; import { CodeActionAdapter } from './languages/code-action' ; import { LinkProviderAdapter } from './languages/link-provider' ; import { CodeLensAdapter } from './languages/lens' ; import { OutlineAdapter } from './languages/outline' ; import { ReferenceAdapter } from './languages/reference' ; import { WorkspaceSymbolAdapter } from './languages/workspace-symbol' ; import { SymbolInformation } from '@theia/core/shared/vscode-languageserver-protocol' ; import { FoldingProviderAdapter } from './languages/folding' ; import { SelectionRangeProviderAdapter } from './languages/selection-range' ; import { ColorProviderAdapter } from './languages/color' ; import { RenameAdapter } from './languages/rename' ; import { Event } from '@theia/core/lib/common/event' ; import { CommandRegistryImpl } from './command-registry' ; import { DeclarationAdapter } from './languages/declaration' ; import { CallHierarchyAdapter } from './languages/call-hierarchy' ; import { BinaryBuffer } from '@theia/core/lib/common/buffer' ; import { DocumentSemanticTokensAdapter , DocumentRangeSemanticTokensAdapter } from './languages/semantic-highlighting' ; import { isReadonlyArray } from '../common/arrays' ; type Adapter = CompletionAdapter | SignatureHelpAdapter | HoverAdapter | DocumentHighlightAdapter | DocumentFormattingAdapter | RangeFormattingAdapter | OnTypeFormattingAdapter | DefinitionAdapter | DeclarationAdapter | ImplementationAdapter | TypeDefinitionAdapter | LinkProviderAdapter | CodeLensAdapter | CodeActionAdapter | OutlineAdapter | ReferenceAdapter | WorkspaceSymbolAdapter | FoldingProviderAdapter | SelectionRangeProviderAdapter | ColorProviderAdapter | RenameAdapter | CallHierarchyAdapter | DocumentRangeSemanticTokensAdapter | DocumentSemanticTokensAdapter ; export class LanguagesExtImpl implements LanguagesExt { private proxy : LanguagesMain ; private readonly diagnostics : Diagnostics ; private callId = 0 ; private adaptersMap = new Map < number , Adapter > ( ) ; constructor ( rpc , private readonly documents , private readonly commands ) { this . proxy = rpc . getProxy ( PLUGIN_RPC_CONTEXT . LANGUAGES_MAIN ) ; this . diagnostics = new Diagnostics ( rpc ) ; } get onDidChangeDiagnostics ( ) : Event < theia . DiagnosticChangeEvent > { return this . diagnostics . onDidChangeDiagnostics ; } getLanguages ( ) { return this . proxy . $getLanguages ( ) ; } changeLanguage ( uri , languageId ) { return this . proxy . $changeLanguage ( uri , languageId ) . then ( ( ) => { const doc = this . documents . getDocumentData ( uri ) ; if ( ! doc ) { throw new Error ( 'No document found by URI ' + uri . toString ( ) ) ; } return doc . document ; } ) ; } setLanguageConfiguration ( language , configuration ) { const { wordPattern } = configuration ; if ( wordPattern ) { this . documents . setWordDefinitionFor ( language , wordPattern ) ; } else { this . documents . setWordDefinitionFor ( language , null ) ; } const callId = this . nextCallId ( ) ; const config = { brackets : configuration . brackets , comments : configuration . comments , onEnterRules : serializeEnterRules ( configuration . onEnterRules ) , wordPattern : serializeRegExp ( configuration . wordPattern ) , indentationRules : serializeIndentation ( configuration . indentationRules ) } ; this . proxy . $setLanguageConfiguration ( callId , language , config ) ; return this . createDisposable ( callId ) ; } private nextCallId ( ) { return this . callId ++ ; } private createDisposable ( callId ) { return new Disposable ( ( ) => { this . adaptersMap . delete ( callId ) ; this . proxy . $unregister ( callId ) ; } ) ; } private addNewAdapter ( adapter ) { const callId = this . nextCallId ( ) ; this . adaptersMap . set ( callId , adapter ) ; return callId ; } private async withAdapter < A , R > ( handle , ctor , callback , fallbackValue ) { const adapter = this . adaptersMap . get ( handle ) ; if ( ! adapter ) { return fallbackValue ; } if ( adapter instanceof ctor ) { return callback ( adapter ) ; } throw new Error ( 'no adapter found' ) ; } private transformDocumentSelector ( selector ) { if ( isReadonlyArray ( selector ) ) { return selector . map ( sel => this . doTransformDocumentSelector ( sel ) ! ) ; } return [ this . doTransformDocumentSelector ( selector ) ! ] ; } private doTransformDocumentSelector ( selector ) { if ( typeof selector === 'string' ) { return { $serialized : true , language : selector } ; } if ( selector ) { return { $serialized : true , language : selector . language , scheme : selector . scheme , pattern : selector . pattern } ; } return undefined ; } $provideCompletionItems ( handle , resource , position , context , token ) { return this . withAdapter ( handle , CompletionAdapter , adapter => adapter . provideCompletionItems ( URI . revive ( resource ) , position , context , token ) , undefined ) ; } $resolveCompletionItem ( handle , chainedId , token ) { return this . withAdapter ( handle , CompletionAdapter , adapter => adapter . resolveCompletionItem ( chainedId , token ) , undefined ) ; } $releaseCompletionItems ( handle , id ) { this . withAdapter ( handle , CompletionAdapter , async ( adapter ) => adapter . releaseCompletionItems ( id ) , undefined ) ; } registerCompletionItemProvider ( selector , provider , triggerCharacters , pluginInfo ) { const callId = this . addNewAdapter ( new CompletionAdapter ( provider , this . documents , this . commands ) ) ; this . proxy . $registerCompletionSupport ( callId , pluginInfo , this . transformDocumentSelector ( selector ) , triggerCharacters , CompletionAdapter . hasResolveSupport ( provider ) ) ; return this . createDisposable ( callId ) ; } $provideDefinition ( handle , resource , position , token ) { return this . withAdapter ( handle , DefinitionAdapter , adapter => adapter . provideDefinition ( URI . revive ( resource ) , position , token ) , undefined ) ; } registerDefinitionProvider ( selector , provider , pluginInfo ) { const callId = this . addNewAdapter ( new DefinitionAdapter ( provider , this . documents ) ) ; this . proxy . $registerDefinitionProvider ( callId , pluginInfo , this . transformDocumentSelector ( selector ) ) ; return this . createDisposable ( callId ) ; } $provideDeclaration ( handle , resource , position , token ) { return this . withAdapter ( handle , DeclarationAdapter , adapter => adapter . provideDeclaration ( URI . revive ( resource ) , position , token ) , undefined ) ; } registerDeclarationProvider ( selector , provider , pluginInfo ) { const callId = this . addNewAdapter ( new DeclarationAdapter ( provider , this . documents ) ) ; this . proxy . $registerDeclarationProvider ( callId , pluginInfo , this . transformDocumentSelector ( selector ) ) ; return this . createDisposable ( callId ) ; } $provideSignatureHelp ( handle , resource , position , context , token ) { return this . withAdapter ( handle , SignatureHelpAdapter , adapter => adapter . provideSignatureHelp ( URI . revive ( resource ) , position , token , context ) , undefined ) ; } $releaseSignatureHelp ( handle , id ) { this . withAdapter ( handle , SignatureHelpAdapter , async ( adapter ) => adapter . releaseSignatureHelp ( id ) , undefined ) ; } registerSignatureHelpProvider ( selector , provider , metadata , pluginInfo ) { const callId = this . addNewAdapter ( new SignatureHelpAdapter ( provider , this . documents ) ) ; this . proxy . $registerSignatureHelpProvider ( callId , pluginInfo , this . transformDocumentSelector ( selector ) , metadata ) ; return this . createDisposable ( callId ) ; } getDiagnostics ( resource ? ) { return this . diagnostics . getDiagnostics ( resource ! ) ; } createDiagnosticCollection ( name ? ) { return this . diagnostics . createDiagnosticCollection ( name ) ; } $provideImplementation ( handle , resource , position , token ) { return this . withAdapter ( handle , ImplementationAdapter , adapter => adapter . provideImplementation ( URI . revive ( resource ) , position , token ) , undefined ) ; } registerImplementationProvider ( selector , provider , pluginInfo ) { const callId = this . addNewAdapter ( new ImplementationAdapter ( provider , this . documents ) ) ; this . proxy . $registerImplementationProvider ( callId , pluginInfo , this . transformDocumentSelector ( selector ) ) ; return this . createDisposable ( callId ) ; } $provideTypeDefinition ( handle , resource , position , token ) { return this . withAdapter ( handle , TypeDefinitionAdapter , adapter => adapter . provideTypeDefinition ( URI . revive ( resource ) , position , token ) , undefined ) ; } registerTypeDefinitionProvider ( selector , provider , pluginInfo ) { const callId = this . addNewAdapter ( new TypeDefinitionAdapter ( provider , this . documents ) ) ; this . proxy . $registerTypeDefinitionProvider ( callId , pluginInfo , this . transformDocumentSelector ( selector ) ) ; return this . createDisposable ( callId ) ; } registerHoverProvider ( selector , provider , pluginInfo ) { const callId = this . addNewAdapter ( new HoverAdapter ( provider , this . documents ) ) ; this . proxy . $registerHoverProvider ( callId , pluginInfo , this . transformDocumentSelector ( selector ) ) ; return this . createDisposable ( callId ) ; } $provideHover ( handle , resource , position , token ) { return this . withAdapter ( handle , HoverAdapter , adapter => adapter . provideHover ( URI . revive ( resource ) , position , token ) , undefined ) ; } registerDocumentHighlightProvider ( selector , provider , pluginInfo ) { const callId = this . addNewAdapter ( new DocumentHighlightAdapter ( provider , this . documents ) ) ; this . proxy . $registerDocumentHighlightProvider ( callId , pluginInfo , this . transformDocumentSelector ( selector ) ) ; return this . createDisposable ( callId ) ; } $provideDocumentHighlights ( handle , resource , position , token ) { return this . withAdapter ( handle , DocumentHighlightAdapter , adapter => adapter . provideDocumentHighlights ( URI . revive ( resource ) , position , token ) , undefined ) ; } registerWorkspaceSymbolProvider ( provider , pluginInfo ) { const callId = this . addNewAdapter ( new WorkspaceSymbolAdapter ( provider ) ) ; this . proxy . $registerWorkspaceSymbolProvider ( callId , pluginInfo ) ; return this . createDisposable ( callId ) ; } $provideWorkspaceSymbols ( handle , query , token ) { return this . withAdapter ( handle , WorkspaceSymbolAdapter , adapter => adapter . provideWorkspaceSymbols ( query , token ) , [ ] ) ; } $resolveWorkspaceSymbol ( handle , symbol , token ) { return this . withAdapter ( handle , WorkspaceSymbolAdapter , adapter => adapter . resolveWorkspaceSymbol ( symbol , token ) , undefined ) ; } registerDocumentFormattingEditProvider ( selector , provider , pluginInfo ) { const callId = this . addNewAdapter ( new DocumentFormattingAdapter ( provider , this . documents ) ) ; this . proxy . $registerDocumentFormattingSupport ( callId , pluginInfo , this . transformDocumentSelector ( selector ) ) ; return this . createDisposable ( callId ) ; } $provideDocumentFormattingEdits ( handle , resource , options , token ) { return this . withAdapter ( handle , DocumentFormattingAdapter , adapter => adapter . provideDocumentFormattingEdits ( URI . revive ( resource ) , options , token ) , undefined ) ; } registerDocumentRangeFormattingEditProvider ( selector , provider , pluginInfo ) { const callId = this . addNewAdapter ( new RangeFormattingAdapter ( provider , this . documents ) ) ; this . proxy . $registerRangeFormattingSupport ( callId , pluginInfo , this . transformDocumentSelector ( selector ) ) ; return this . createDisposable ( callId ) ; } $provideDocumentRangeFormattingEdits ( handle , resource , range , options , token ) { return this . withAdapter ( handle , RangeFormattingAdapter , adapter => adapter . provideDocumentRangeFormattingEdits ( URI . revive ( resource ) , range , options , token ) , undefined ) ; } registerOnTypeFormattingEditProvider ( selector , provider , triggerCharacters , pluginInfo ) { const callId = this . addNewAdapter ( new OnTypeFormattingAdapter ( provider , this . documents ) ) ; this . proxy . $registerOnTypeFormattingProvider ( callId , pluginInfo , this . transformDocumentSelector ( selector ) , triggerCharacters ) ; return this . createDisposable ( callId ) ; } $provideOnTypeFormattingEdits ( handle , resource , position , ch , options , token ) { return this . withAdapter ( handle , OnTypeFormattingAdapter , adapter => adapter . provideOnTypeFormattingEdits ( URI . revive ( resource ) , position , ch , options , token ) , undefined ) ; } $provideDocumentLinks ( handle , resource , token ) { return this . withAdapter ( handle , LinkProviderAdapter , adapter => adapter . provideLinks ( URI . revive ( resource ) , token ) , undefined ) ; } $resolveDocumentLink ( handle , link , token ) { return this . withAdapter ( handle , LinkProviderAdapter , adapter => adapter . resolveLink ( link , token ) , undefined ) ; } registerDocumentLinkProvider ( selector , provider , pluginInfo ) { const callId = this . addNewAdapter ( new LinkProviderAdapter ( provider , this . documents ) ) ; this . proxy . $registerDocumentLinkProvider ( callId , pluginInfo , this . transformDocumentSelector ( selector ) ) ; return this . createDisposable ( callId ) ; } $releaseDocumentLinks ( handle , ids ) { this . withAdapter ( handle , LinkProviderAdapter , async ( adapter ) => adapter . releaseDocumentLinks ( ids ) , undefined ) ; } registerCodeActionsProvider ( selector , provider , pluginModel , pluginInfo , metadata ? ) { const callId = this . addNewAdapter ( new CodeActionAdapter ( provider , this . documents , this . diagnostics , pluginModel ? pluginModel . id : '' , this . commands ) ) ; this . proxy . $registerQuickFixProvider ( callId , pluginInfo , this . transformDocumentSelector ( selector ) , metadata && metadata . providedCodeActionKinds ? metadata . providedCodeActionKinds . map ( kind => kind . value ! ) : undefined ) ; return this . createDisposable ( callId ) ; } $provideCodeActions ( handle , resource , rangeOrSelection , context , token ) { return this . withAdapter ( handle , CodeActionAdapter , adapter => adapter . provideCodeAction ( URI . revive ( resource ) , rangeOrSelection , context , token ) , undefined ) ; } registerCodeLensProvider ( selector , provider , pluginInfo ) { const callId = this . addNewAdapter ( new CodeLensAdapter ( provider , this . documents , this . commands ) ) ; const eventHandle = typeof provider . onDidChangeCodeLenses === 'function' ? this . nextCallId ( ) : undefined ; this . proxy . $registerCodeLensSupport ( callId , pluginInfo , this . transformDocumentSelector ( selector ) , eventHandle ) ; let result = this . createDisposable ( callId ) ; if ( eventHandle !== undefined && provider . onDidChangeCodeLenses ) { const subscription = provider . onDidChangeCodeLenses ( e => this . proxy . $emitCodeLensEvent ( eventHandle ) ) ; result = Disposable . from ( result , subscription ) ; } return result ; } $provideCodeLenses ( handle , resource , token ) { return this . withAdapter ( handle , CodeLensAdapter , adapter => adapter . provideCodeLenses ( URI . revive ( resource ) , token ) , undefined ) ; } $resolveCodeLens ( handle , resource , symbol , token ) { return this . withAdapter ( handle , CodeLensAdapter , adapter => adapter . resolveCodeLens ( URI . revive ( resource ) , symbol , token ) , undefined ) ; } $releaseCodeLenses ( handle , ids ) { this . withAdapter ( handle , CodeLensAdapter , async ( adapter ) => adapter . releaseCodeLenses ( ids ) , undefined ) ; } $provideReferences ( handle , resource , position , context , token ) { return this . withAdapter ( handle , ReferenceAdapter , adapter => adapter . provideReferences ( URI . revive ( resource ) , position , context , token ) , undefined ) ; } registerReferenceProvider ( selector , provider , pluginInfo ) { const callId = this . addNewAdapter ( new ReferenceAdapter ( provider , this . documents ) ) ; this . proxy . $registerReferenceProvider ( callId , pluginInfo , this . transformDocumentSelector ( selector ) ) ; return this . createDisposable ( callId ) ; } registerDocumentSymbolProvider ( selector , provider , pluginInfo ) { const callId = this . addNewAdapter ( new OutlineAdapter ( this . documents , provider ) ) ; this . proxy . $registerOutlineSupport ( callId , pluginInfo , this . transformDocumentSelector ( selector ) ) ; return this . createDisposable ( callId ) ; } $provideDocumentSymbols ( handle , resource , token ) { return this . withAdapter ( handle , OutlineAdapter , adapter => adapter . provideDocumentSymbols ( URI . revive ( resource ) , token ) , undefined ) ; } registerColorProvider ( selector , provider , pluginInfo ) { const callId = this . addNewAdapter ( new ColorProviderAdapter ( this . documents , provider ) ) ; this . proxy . $registerDocumentColorProvider ( callId , pluginInfo , this . transformDocumentSelector ( selector ) ) ; return this . createDisposable ( callId ) ; } $provideDocumentColors ( handle , resource , token ) { return this . withAdapter ( handle , ColorProviderAdapter , adapter => adapter . provideColors ( URI . revive ( resource ) , token ) , [ ] ) ; } $provideColorPresentations ( handle , resource , colorInfo , token ) { return this . withAdapter ( handle , ColorProviderAdapter , adapter => adapter . provideColorPresentations ( URI . revive ( resource ) , colorInfo , token ) , [ ] ) ; } registerFoldingRangeProvider ( selector , provider , pluginInfo ) { const callId = this . addNewAdapter ( new FoldingProviderAdapter ( provider , this . documents ) ) ; this . proxy . $registerFoldingRangeProvider ( callId , pluginInfo , this . transformDocumentSelector ( selector ) ) ; return this . createDisposable ( callId ) ; } $provideFoldingRange ( callId , resource , context , token ) { return this . withAdapter ( callId , FoldingProviderAdapter , adapter => adapter . provideFoldingRanges ( URI . revive ( resource ) , context , token ) , undefined ) ; } registerSelectionRangeProvider ( selector , provider , pluginInfo ) { const callId = this . addNewAdapter ( new SelectionRangeProviderAdapter ( provider , this . documents ) ) ; this . proxy . $registerSelectionRangeProvider ( callId , pluginInfo , this . transformDocumentSelector ( selector ) ) ; return this . createDisposable ( callId ) ; } $provideSelectionRanges ( handle , resource , positions , token ) { return this . withAdapter ( handle , SelectionRangeProviderAdapter , adapter => adapter . provideSelectionRanges ( URI . revive ( resource ) , positions , token ) , [ ] ) ; } registerRenameProvider ( selector , provider , pluginInfo ) { const callId = this . addNewAdapter ( new RenameAdapter ( provider , this . documents ) ) ; this . proxy . $registerRenameProvider ( callId , pluginInfo , this . transformDocumentSelector ( selector ) , RenameAdapter . supportsResolving ( provider ) ) ; return this . createDisposable ( callId ) ; } $provideRenameEdits ( handle , resource , position , newName , token ) { return this . withAdapter ( handle , RenameAdapter , adapter => adapter . provideRenameEdits ( URI . revive ( resource ) , position , newName , token ) , undefined ) ; } $resolveRenameLocation ( handle , resource , position , token ) { return this . withAdapter ( handle , RenameAdapter , adapter => adapter . resolveRenameLocation ( URI . revive ( resource ) , position , token ) , undefined ) ; } registerCallHierarchyProvider ( selector , provider ) { const callId = this . addNewAdapter ( new CallHierarchyAdapter ( provider , this . documents ) ) ; this . proxy . $registerCallHierarchyProvider ( callId , this . transformDocumentSelector ( selector ) ) ; return this . createDisposable ( callId ) ; } $provideRootDefinition ( handle , resource , location , token ) { return this . withAdapter ( handle , CallHierarchyAdapter , adapter => adapter . provideRootDefinition ( URI . revive ( resource ) , location , token ) , undefined ) ; } $provideCallers ( handle , definition , token ) { return this . withAdapter ( handle , CallHierarchyAdapter , adapter => adapter . provideCallers ( definition , token ) , undefined ) ; } $provideCallees ( handle , definition , token ) { return this . withAdapter ( handle , CallHierarchyAdapter , adapter => adapter . provideCallees ( definition , token ) , undefined ) ; } registerDocumentSemanticTokensProvider ( selector , provider , legend , pluginInfo ) { const eventHandle = ( typeof provider . onDidChangeSemanticTokens === 'function' ? this . nextCallId ( ) : undefined ) ; const handle = this . addNewAdapter ( new DocumentSemanticTokensAdapter ( this . documents , provider ) ) ; this . proxy . $registerDocumentSemanticTokensProvider ( handle , pluginInfo , this . transformDocumentSelector ( selector ) , legend , eventHandle ) ; let result = this . createDisposable ( handle ) ; if ( eventHandle ) { const subscription = provider . onDidChangeSemanticTokens ! ( _ => this . proxy . $emitDocumentSemanticTokensEvent ( eventHandle ) ) ; result = Disposable . from ( result , subscription ) ; } return result ; } $provideDocumentSemanticTokens ( handle , resource , previousResultId , token ) { return this . withAdapter ( handle , DocumentSemanticTokensAdapter , adapter => adapter . provideDocumentSemanticTokens ( URI . revive ( resource ) , previousResultId , token ) , null ) ; } $releaseDocumentSemanticTokens ( handle , semanticColoringResultId ) { this . withAdapter ( handle , DocumentSemanticTokensAdapter , adapter => adapter . releaseDocumentSemanticColoring ( semanticColoringResultId ) , undefined ) ; } registerDocumentRangeSemanticTokensProvider ( selector , provider , legend , pluginInfo ) { const handle = this . addNewAdapter ( new DocumentRangeSemanticTokensAdapter ( this . documents , provider ) ) ; this . proxy . $registerDocumentRangeSemanticTokensProvider ( handle , pluginInfo , this . transformDocumentSelector ( selector ) , legend ) ; return this . createDisposable ( handle ) ; } $provideDocumentRangeSemanticTokens ( handle , resource , range , token ) { return this . withAdapter ( handle , DocumentRangeSemanticTokensAdapter , adapter => adapter . provideDocumentRangeSemanticTokens ( URI . revive ( resource ) , range , token ) , null ) ; } } function serializeEnterRules ( rules ? ) { if ( typeof rules === 'undefined' || rules === null ) { return undefined ; } return rules . map ( r => ( { action : r . action , beforeText : serializeRegExp ( r . beforeText ) , afterText : serializeRegExp ( r . afterText ) } as SerializedOnEnterRule ) ) ; } function serializeRegExp ( regexp ? ) { if ( typeof regexp === 'undefined' || regexp === null ) { return undefined ; } return { pattern : regexp . source , flags : ( regexp . global ? 'g' : '' ) + ( regexp . ignoreCase ? 'i' : '' ) + ( regexp . multiline ? 'm' : '' ) } ; } function serializeIndentation ( indentationRules ? ) { if ( typeof indentationRules === 'undefined' || indentationRules === null ) { return undefined ; } return { increaseIndentPattern : serializeRegExp ( indentationRules . increaseIndentPattern ) , decreaseIndentPattern : serializeRegExp ( indentationRules . decreaseIndentPattern ) , indentNextLinePattern : serializeRegExp ( indentationRules . indentNextLinePattern ) , unIndentedLinePattern : serializeRegExp ( indentationRules . unIndentedLinePattern ) } ; }