<commit_before>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { workspace, WorkspaceSymbolProvider, SymbolInformation, TextDocument, Disposable } from 'vscode';
import { isMarkdownFile } from '../util/file';
import MDDocumentSymbolProvider from './documentSymbolProvider';
import { Dictionary, flatMap } from 'lodash';

export default class MarkdownWorkspaceSymbolProvider implements WorkspaceSymbolProvider {
	private symbolProvider: MDDocumentSymbolProvider;
	private symbolCache: Dictionary<SymbolInformation[]> = {};
	private symbolCachePopulated: boolean;
	private deRegisterOnSaveEvent: Disposable;

	public constructor(symbolProvider: MDDocumentSymbolProvider) {
		this.symbolProvider = symbolProvider;
		this.symbolCachePopulated = false;
		this.deRegisterOnSaveEvent = this.registerOnSaveEvent();
	}

	public async provideWorkspaceSymbols(query: string): Promise<SymbolInformation[]> {
		if (!this.symbolCachePopulated) {
			await this.populateSymbolCache();
			this.symbolCachePopulated = true;
		}

		return flatMap(this.symbolCache)
			.filter(symbolInformation => symbolInformation.name.toLowerCase().indexOf(query.toLowerCase()) !== -1);
	}

	public async populateSymbolCache(): Promise<void> {
		const markDownDocumentUris = await workspace.findFiles('**/*.md');
		for (const uri of markDownDocumentUris) {
			const document = await workspace.openTextDocument(uri);
			if (isMarkdownFile(document)) {
				const symbols = await this.getSymbol(document);
				this.symbolCache[document.fileName] = symbols;
			}
		}
	}

	public dispose(): void {
		this.deRegisterOnSaveEvent.dispose();
	}

	private async getSymbol(document: TextDocument): Promise<SymbolInformation[]> {
		return this.symbolProvider.provideDocumentSymbols(document);
	}

	private registerOnSaveEvent(): Disposable {
		return workspace.onDidSaveTextDocument(async document => {
			if (isMarkdownFile(document)) {
				const symbols = await this.getSymbol(document);
				this.symbolCache[document.fileName] = symbols;
			}
		});
	}

}<commit_msg>Don't depend on lodash<commit_after>/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

import { workspace, WorkspaceSymbolProvider, SymbolInformation, TextDocument, Disposable } from 'vscode';
import { isMarkdownFile } from '../util/file';
import MDDocumentSymbolProvider from './documentSymbolProvider';

export default class MarkdownWorkspaceSymbolProvider implements WorkspaceSymbolProvider {
	private symbolProvider: MDDocumentSymbolProvider;
	private symbolCache = new Map<string, SymbolInformation[]>();
	private symbolCachePopulated: boolean;
	private deRegisterOnSaveEvent: Disposable;

	public constructor(symbolProvider: MDDocumentSymbolProvider) {
		this.symbolProvider = symbolProvider;
		this.symbolCachePopulated = false;
		this.deRegisterOnSaveEvent = this.registerOnSaveEvent();
	}

	public async provideWorkspaceSymbols(query: string): Promise<SymbolInformation[]> {
		if (!this.symbolCachePopulated) {
			await this.populateSymbolCache();
			this.symbolCachePopulated = true;
		}

		return Array.prototype.concat.apply([], Array.from(this.symbolCache.values())
			.filter(symbols => symbols.filter(symbolInformation => symbolInformation.name.toLowerCase().indexOf(query.toLowerCase()) !== -1)));
	}

	public async populateSymbolCache(): Promise<void> {
		const markDownDocumentUris = await workspace.findFiles('**/*.md');
		for (const uri of markDownDocumentUris) {
			const document = await workspace.openTextDocument(uri);
			if (isMarkdownFile(document)) {
				const symbols = await this.getSymbol(document);
				this.symbolCache.set(document.fileName, symbols);
			}
		}
	}

	public dispose(): void {
		this.deRegisterOnSaveEvent.dispose();
	}

	private async getSymbol(document: TextDocument): Promise<SymbolInformation[]> {
		return this.symbolProvider.provideDocumentSymbols(document);
	}

	private registerOnSaveEvent(): Disposable {
		return workspace.onDidSaveTextDocument(async document => {
			if (isMarkdownFile(document)) {
				const symbols = await this.getSymbol(document);
				this.symbolCache.set(document.fileName, symbols);
			}
		});
	}

}
{'fraction_non_alphanumeric': 0.1773064687168611, 'fraction_numerical': 0.0004241781548250265, 'mean_word_length': 3.6190009794319296, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 16, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1091736', 'n_tokens_mistral': 1271, 'n_tokens_neox': 1171, 'n_words': 274}