"use strict";
/**
 * @license
 * Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at
 * http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at
 * http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at
 * http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at
 * http://polymer.github.io/PATENTS.txt
 */
Object.defineProperty(exports, "__esModule", { value: true });
const async_work_cache_1 = require("./async-work-cache");
const dependency_graph_1 = require("./dependency-graph");
class AnalysisCache {
    /**
     * @param from Another AnalysisCache to copy the caches from. The new
     *   AnalysisCache will have an independent copy of everything but from's
     *   dependency graph, which is passed in separately.
     * @param newDependencyGraph If given, use this dependency graph. We pass
     *   this in like this purely as an optimization. See `invalidatePaths`.
     */
    constructor(from, newDependencyGraph) {
        const f = from || {};
        this.parsedDocumentPromises = new async_work_cache_1.AsyncWorkCache(f.parsedDocumentPromises);
        this.scannedDocumentPromises =
            new async_work_cache_1.AsyncWorkCache(f.scannedDocumentPromises);
        this.analyzedDocumentPromises =
            new async_work_cache_1.AsyncWorkCache(f.analyzedDocumentPromises);
        this.dependenciesScannedPromises =
            new async_work_cache_1.AsyncWorkCache(f.dependenciesScannedPromises);
        this.failedDocuments = new Map(f.failedDocuments);
        this.scannedDocuments = new Map(f.scannedDocuments);
        this.analyzedDocuments = new Map(f.analyzedDocuments);
        this.dependencyGraph = newDependencyGraph || new dependency_graph_1.DependencyGraph();
    }
    /**
     * Returns a copy of this cache, with the given document and all of its
     * transitive dependants invalidated.
     *
     * Must be called whenever a document changes.
     */
    invalidate(documentPaths) {
        // TODO(rictic): how much of this work can we short circuit in the case
        //     none of these paths are in any of the caches? e.g. when someone calls
        //     filesChanged() for the same files twice without ever calling analyze?
        //     Could end up saving some work in the editor case.
        //     On the other hand, copying a half dozen maps with maybe 200 entries
        //     each should be pretty cheap, maybe not worth the effort.
        const newCache = new AnalysisCache(this, this.dependencyGraph.invalidatePaths(documentPaths));
        for (const path of documentPaths) {
            // Note that we must calculate the dependency graph based on the parent,
            // not the forked newCache.
            const dependants = this.dependencyGraph.getAllDependantsOf(path);
            newCache.parsedDocumentPromises.delete(path);
            newCache.scannedDocumentPromises.delete(path);
            newCache.dependenciesScannedPromises.delete(path);
            newCache.scannedDocuments.delete(path);
            newCache.analyzedDocuments.delete(path);
            newCache.failedDocuments.delete(path);
            // Analyzed documents need to be treated more carefully, because they have
            // relationships with other documents. So first we remove all documents
            // which transitively import the changed document. We also need to mark
            // all of those docs as needing to rescan their dependencies.
            for (const partiallyInvalidatedPath of dependants) {
                newCache.dependenciesScannedPromises.delete(partiallyInvalidatedPath);
                newCache.analyzedDocuments.delete(partiallyInvalidatedPath);
            }
            // Then we clear out the analyzed document promises, which could have
            // in-progress results that don't cohere with the state of the new cache.
            // Only populate the new analyzed promise cache with results that are
            // definite, and not invalidated.
            newCache.analyzedDocumentPromises.clear();
            for (const keyValue of newCache.analyzedDocuments) {
                newCache.analyzedDocumentPromises.set(keyValue[0], keyValue[1]);
            }
        }
        return newCache;
    }
    toString() {
        return `<AnalysisCache
        scannedDocuments:
            ${Array.from(this.scannedDocuments.keys())
            .join('\n            ')}
        analyzedDocuments:
            ${Array.from(this.analyzedDocuments.keys())
            .join('\n            ')}
      >`;
    }
}
exports.AnalysisCache = AnalysisCache;

//# sourceMappingURL=analysis-cache.js.map
