UNPKG

atom-nuclide

Version:

A unified developer experience for web and mobile development, built as a suite of features on top of Atom to provide hackability and the support of an active community.

188 lines (155 loc) 6.38 kB
Object.defineProperty(exports, '__esModule', { value: true }); /* * Copyright (c) 2015-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the license found in the LICENSE file in * the root directory of this source tree. */ var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } var _atom2; function _atom() { return _atom2 = require('atom'); } var _assert2; function _assert() { return _assert2 = _interopRequireDefault(require('assert')); } var _commonsNodeCollection2; function _commonsNodeCollection() { return _commonsNodeCollection2 = require('../../commons-node/collection'); } var MarkerTracker = (function () { function MarkerTracker() { var _this = this; _classCallCheck(this, MarkerTracker); this._messageToMarker = new Map(); this._fileToMessages = new (_commonsNodeCollection2 || _commonsNodeCollection()).MultiMap(); this._subscriptions = new (_atom2 || _atom()).CompositeDisposable(); this._disposed = false; this._subscriptions.add(atom.workspace.observeTextEditors(function (editor) { var path = editor.getPath(); if (path == null) { return; } var messagesForPath = _this._fileToMessages.get(path); for (var message of messagesForPath) { // There might already be a marker because there can be multiple TextEditors open for a // given file. if (!_this._messageToMarker.has(message)) { _this._addMarker(editor, message); } } })); } _createClass(MarkerTracker, [{ key: 'dispose', value: function dispose() { if (!this._disposed) { this._subscriptions.dispose(); for (var marker of this._messageToMarker.values()) { marker.destroy(); } this._fileToMessages.clear(); this._messageToMarker.clear(); this._disposed = true; } } /** Return a Range if the marker is still valid, otherwise return null */ }, { key: 'getCurrentRange', value: function getCurrentRange(message) { this._assertNotDisposed(); var marker = this._messageToMarker.get(message); if (marker != null && marker.isValid()) { return marker.getBufferRange(); } else { return null; } } }, { key: 'addFileMessages', value: function addFileMessages(messages) { var _this2 = this; this._assertNotDisposed(); // Right now we only care about messages with fixes. var messagesWithFix = messages.filter(function (m) { return m.fix != null; }); var _loop = function (message) { _this2._fileToMessages.add(message.filePath, message); // If the file is currently open, create a marker. // TODO If there is a long delay between when the file is saved and results appear, the file // may have changed in the mean time. Meaning that the markers we place here may be in the // wrong place already. Consider detecting such cases (perhaps with a checksum included in the // fix) and rejecting the fixes, since we can't accurately track their locations. var editorForFile = atom.workspace.getTextEditors().filter(function (editor) { return editor.getPath() === message.filePath; })[0]; if (editorForFile != null) { _this2._addMarker(editorForFile, message); } }; for (var message of messagesWithFix) { _loop(message); } } /** Remove the given messages, if they are currently present */ }, { key: 'removeFileMessages', value: function removeFileMessages(messages) { this._assertNotDisposed(); for (var message of messages) { this._fileToMessages.delete(message.filePath, message); var marker = this._messageToMarker.get(message); if (marker != null) { // No need to remove from the set explicitly since we do that on the marker's onDidDestroy // handler. marker.destroy(); } } } }, { key: '_addMarker', value: function _addMarker(editor, message) { var _this3 = this; var fix = message.fix; (0, (_assert2 || _assert()).default)(fix != null); var marker = editor.markBufferRange(fix.oldRange, { // 'touch' is the least permissive invalidation strategy: It will invalidate for // changes that touch the marked region in any way. We want to invalidate // aggressively because an incorrect fix application is far worse than a failed // application. invalidate: 'touch' }); this._messageToMarker.set(message, marker); // The marker will be destroyed automatically when its associated TextBuffer is destroyed. Clean // up when that happens. var markerSubscription = marker.onDidDestroy(function () { _this3._messageToMarker.delete(message); markerSubscription.dispose(); _this3._subscriptions.remove(markerSubscription); }); this._subscriptions.add(markerSubscription); } }, { key: '_assertNotDisposed', value: function _assertNotDisposed() { (0, (_assert2 || _assert()).default)(!this._disposed, 'MarkerTracker has been disposed'); } }]); return MarkerTracker; })(); exports.MarkerTracker = MarkerTracker; /** * Stores all current FileDiagnosticMessages, indexed by file. Includes those for files that are * not open. */ /** * Stores all current markers, indexed by FileDiagnosticMessage. * invariant: No messages for closed files, no destroyed markers. */