import * as path from "path" ; import { commands , Disposable , FileSystemWatcher , RelativePattern , Uri , workspace } from "vscode" ; import { instrumentOperation } from "vscode-extension-telemetry-wrapper" ; import { Commands } from "./commands" ; import { NodeKind } from "./java/nodeData" ; import { Settings } from "./settings" ; import { DataNode } from "./views/dataNode" ; import { ExplorerNode } from "./views/explorerNode" ; import { explorerNodeCache } from "./views/nodeCache/explorerNodeCache" ; const ENABLE_AUTO_REFRESH = "java.view.package.enableAutoRefresh" ; const DISABLE_AUTO_REFRESH = "java.view.package.disableAutoRefresh" ; class SyncHandler implements Disposable { private disposables : Disposable [ ] = [ ] ; public updateFileWatcher ( autoRefresh ? ) { this . dispose ( ) ; if ( autoRefresh ) { instrumentOperation ( ENABLE_AUTO_REFRESH , ( ) => this . enableAutoRefresh ( ) ) ( ) ; } else { instrumentOperation ( DISABLE_AUTO_REFRESH , ( ) => { } ) ( ) ; } } public dispose ( ) { for ( const disposable of this . disposables ) { if ( disposable ) { disposable . dispose ( ) ; } } this . disposables = [ ] ; } private async enableAutoRefresh ( ) { this . disposables . push ( workspace . onDidChangeWorkspaceFolders ( ( ) => { this . refresh ( ) ; } ) ) ; try { const result = await commands . executeCommand < IListCommandResult > ( Commands . EXECUTE_WORKSPACE_COMMAND , Commands . JAVA_PROJECT_LIST_SOURCE_PATHS ) ; if ( ! result || ! result . status || ! result . data || result . data . length === 0 ) { throw new Error ( "Failed to list the source paths" ) ; } for ( const sourcePathData of result . data ) { const normalizedPath = Uri . file ( sourcePathData . path ) . fsPath ; const pattern = new RelativePattern ( normalizedPath , "**/*" ) ; const watcher = workspace . createFileSystemWatcher ( pattern ) ; this . disposables . push ( watcher ) ; this . setupWatchers ( watcher ) ; } } catch ( e ) { const fileSystemWatcher = workspace . createFileSystemWatcher ( "**/{*.java,src/**}" ) ; this . disposables . push ( fileSystemWatcher ) ; this . setupWatchers ( fileSystemWatcher ) ; } } private setupWatchers ( watcher ) { this . disposables . push ( watcher . onDidChange ( ( uri ) => { if ( path . extname ( uri . fsPath ) !== ".java" || ! Settings . showMembers ( ) ) { return ; } const node = explorerNodeCache . getDataNode ( uri ) ; this . refresh ( node ) ; } ) ) ; this . disposables . push ( watcher . onDidCreate ( ( uri ) => { this . refresh ( this . getParentNodeInExplorer ( uri ) ) ; } ) ) ; this . disposables . push ( watcher . onDidDelete ( ( uri ) => { this . refresh ( this . getParentNodeInExplorer ( uri ) ) ; } ) ) ; } private getParentNodeInExplorer ( uri ) { let node = explorerNodeCache . findBestMatchNodeByUri ( uri ) ; if ( ! node ) { return undefined ; } if ( Settings . isHierarchicalView ( ) ) { while ( node && node . nodeData . kind !== NodeKind . PackageRoot ) { node = < DataNode > node . getParent ( ) ; } return node ; } else { if ( path . extname ( uri . fsPath ) === ".java" && node . uri && Uri . parse ( node . uri ) . fsPath === path . dirname ( uri . fsPath ) ) { return node ; } else { while ( node && node . nodeData . kind > NodeKind . PackageRoot ) { node = < DataNode > node . getParent ( ) ; } return node ; } } } private refresh ( node ? ) { commands . executeCommand ( Commands . VIEW_PACKAGE_REFRESH , true , node ) ; } } interface ISourcePath { path : string ; displayPath : string ; projectName : string ; projectType : string ; } interface IListCommandResult { status : boolean ; message : string ; data ? : ISourcePath [ ] ; } export const syncHandler = new SyncHandler ( ) ;