license import { InMemoryOverlayUrlLoader , ResolvedUrl , UrlLoader } from 'polymer-analyzer' ; import { FsUrlLoader } from 'polymer-analyzer/lib/url-loader/fs-url-loader' ; import { FileChangeType , FileEvent , IConnection , TextDocuments } from 'vscode-languageserver' ; import AnalyzerLSPConverter from './converter' ; import { Logger } from './logger' ; import { AutoDisposable , EventStream } from './util' ; /**
 * Handles synchronizing and firing events for changes to files, either in
 * open text editors or on disk.
 *
 * This class is responsible for maintaining a URL Loader that always returns
 * the latest known content for a given url when requested, and for exposing an
 * EventStream of FileEvents.
 */ export default class FileSynchronizer extends AutoDisposable { /** This maps workspace path to content of our in-memory documents. */ private inMemoryDocuments : Map < ResolvedUrl , string > ; readonly urlLoader : UrlLoader ; fileChanges : EventStream < FileEvent [ ] > ; constructor ( connection , documents , baseDir , converter , logger ) { super ( ) ; const fileLoader = new FsUrlLoader ( baseDir ) ; const inMemoryOverlayLoader = new InMemoryOverlayUrlLoader ( fileLoader ) ; this . inMemoryDocuments = inMemoryOverlayLoader . urlContentsMap ; this . urlLoader = inMemoryOverlayLoader ; const { fire , stream } = EventStream . create < FileEvent [ ] > ( ) ; this . fileChanges = stream ; documents . onDidOpen ( ( change ) => { logger . log ( `Opened: ${ change . document . uri }` ) ; } ) ; this . disposables . push ( documents . onDidChangeContent ( ( change ) => { logger . log ( `Changed in memory: ${ change . document . uri }` ) ; const url = converter . getAnalyzerUrl ( change . document ) ; if ( ! url ) { return ; } this . inMemoryDocuments . set ( url , change . document . getText ( ) ) ; fire ( [ { type : FileChangeType . Changed , uri : change . document . uri } ] ) ; } ) ) ; this . disposables . push ( documents . onDidClose ( ( event ) => { logger . log ( `Closed: ${ event . document . uri }` ) ; const url = converter . getAnalyzerUrl ( event . document ) ; if ( url === undefined ) { return ; } this . inMemoryDocuments . delete ( url ) ; fire ( [ { type : FileChangeType . Changed , uri : event . document . uri } ] ) ; } ) ) ; connection . onDidChangeWatchedFiles ( ( req ) => { for ( const change of req . changes ) { logger . log ( `Changed on disk: ${ change . uri }` ) ; } const inMemoryURIs = new Set ( documents . keys ( ) ) ; const diskBackedChanges = req . changes . filter ( ch => ! inMemoryURIs . has ( ch . uri ) ) ; fire ( diskBackedChanges ) ; } ) ; } }