alm
Version:
The best IDE for TypeScript
255 lines (254 loc) • 12.6 kB
JavaScript
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
var React = require("react");
var ReactDOM = require("react-dom");
var csx = require("../../base/csx");
var ui_1 = require("../../ui");
var ui = require("../../ui");
var utils = require("../../../common/utils");
var styles = require("../../styles/styles");
var state = require("../../state/state");
var uix = require("../../uix");
var commands = require("../../commands/commands");
var Modal = require("react-modal");
var socketClient_1 = require("../../../socket/socketClient");
var styles_1 = require("../../styles/styles");
var codeEditor_1 = require("../editor/codeEditor");
var typestyle = require("typestyle");
var inputClassName = typestyle.style(styles.modal.inputStyleBase);
var validationErrorStyle = {
color: 'red',
fontFamily: 'monospace',
fontSize: '1.2rem',
padding: '5px',
};
var summaryStyle = {
padding: '5px',
backgroundColor: '#222',
color: '#CCC',
fontSize: '.8rem',
};
var RenameVariable = /** @class */ (function (_super) {
__extends(RenameVariable, _super);
function RenameVariable(props) {
var _this = _super.call(this, props) || this;
_this.onChangeFilter = function (e) {
var newText = ReactDOM.findDOMNode(_this.refs.mainInput).value;
if (newText.replace(/\s/g, '') !== newText.trim()) {
_this.setState({ invalidMessage: 'The new variable must not contain a space' });
}
else if (!newText.trim()) {
_this.setState({ invalidMessage: 'Please provide a new name or press esc to abort rename' });
}
else {
_this.setState({ invalidMessage: '' });
}
};
_this.onChangeSelected = function (event) {
var keyStates = ui.getKeyStates(event);
if (keyStates.up || keyStates.tabPrevious) {
event.preventDefault();
var selectedIndex = utils.rangeLimited({ num: _this.state.selectedIndex - 1, min: 0, max: _this.state.flattened.length - 1, loopAround: true });
_this.setState({ selectedIndex: selectedIndex });
}
if (keyStates.down || keyStates.tabNext) {
event.preventDefault();
var selectedIndex = utils.rangeLimited({ num: _this.state.selectedIndex + 1, min: 0, max: _this.state.flattened.length - 1, loopAround: true });
_this.setState({ selectedIndex: selectedIndex });
}
if (keyStates.enter) {
event.preventDefault();
var newText_1 = ReactDOM.findDOMNode(_this.refs.mainInput).value.trim();
var refactorings_1 = {};
Object.keys(_this.props.info.locations).map(function (filePath) {
refactorings_1[filePath] = [];
var forPath = refactorings_1[filePath];
_this.props.info.locations[filePath].forEach(function (loc) {
var refactoring = {
filePath: filePath,
span: loc,
newText: newText_1
};
forPath.push(refactoring);
});
});
uix.API.applyRefactorings(refactorings_1);
setTimeout(function () { _this.props.unmount(); });
}
};
_this.selectAndRefocus = function (index) {
_this.setState({ selectedIndex: index });
_this.focus();
};
_this.focus = function () {
var input = ReactDOM.findDOMNode(_this.refs.mainInput);
input.focus();
};
var flattended = utils.selectMany(Object.keys(props.info.locations).map(function (filePath) {
var refs = props.info.locations[filePath].slice().reverse();
return refs.map(function (preview, i) {
return {
filePath: filePath,
preview: preview,
indexForFilePath: i + 1,
totalForFilePath: refs.length,
};
});
}));
_this.state = {
selectedIndex: 0,
flattened: flattended
};
return _this;
}
RenameVariable.prototype.componentDidMount = function () {
var _this = this;
this.disposible.add(commands.esc.on(function () {
_this.props.unmount();
}));
setTimeout(function () {
_this.focus();
var input = ReactDOM.findDOMNode(_this.refs.mainInput);
var len = input.value.length;
input.setSelectionRange(0, len);
});
};
RenameVariable.prototype.componentDidUpdate = function () {
var _this = this;
setTimeout(function () {
var selected = ReactDOM.findDOMNode(_this.refs.selectedTabTitle);
if (selected) {
selected.scrollIntoViewIfNeeded(false);
}
});
};
RenameVariable.prototype.render = function () {
var _this = this;
var selectedPreview = this.state.flattened[this.state.selectedIndex];
var filePathsRendered = this.state.flattened.map(function (item, i) {
var selected = i == _this.state.selectedIndex;
var active = selected ? styles.tabHeaderActive : {};
var ref = selected && "selectedTabTitle";
return (React.createElement("div", { ref: ref, key: item.filePath + i, style: csx.extend(styles.tabHeader, active, { overflow: 'hidden' }), onClick: function () { return _this.selectAndRefocus(i); } },
React.createElement("div", { title: item.filePath, style: { overflow: 'hidden', textOverflow: 'ellipsis' } },
utils.getFileName(item.filePath),
" (",
item.indexForFilePath,
" of ",
item.totalForFilePath,
")")));
});
var previewRendered = React.createElement(codeEditor_1.CodeEditor, { key: selectedPreview.filePath, filePath: selectedPreview.filePath, readOnly: true, preview: selectedPreview.preview });
return (React.createElement(Modal, { isOpen: true, onRequestClose: this.props.unmount },
React.createElement("div", { style: csx.extend(csx.vertical, csx.flex) },
React.createElement("div", { style: csx.extend(csx.horizontal, csx.content) },
React.createElement("h4", null, "Rename"),
React.createElement("div", { style: csx.flex }),
React.createElement("div", { style: { fontSize: '0.9rem', color: 'grey' } },
React.createElement("code", { style: styles_1.modal.keyStrokeStyle }, "Esc"),
" to exit ",
React.createElement("code", { style: styles_1.modal.keyStrokeStyle }, "Enter"),
" to select",
' ',
React.createElement("code", { style: styles_1.modal.keyStrokeStyle }, "Up / Down"),
" to see usages")),
React.createElement("div", { style: csx.extend(styles.padded1TopBottom, csx.vertical, csx.content) },
React.createElement("input", { defaultValue: this.props.info.displayName, className: inputClassName, type: "text", ref: "mainInput", placeholder: "Filter", onChange: this.onChangeFilter, onKeyDown: this.onChangeSelected })),
this.state.invalidMessage &&
React.createElement("div", { style: csx.extend(csx.content, validationErrorStyle) }, this.state.invalidMessage),
React.createElement("div", { style: csx.extend(csx.content, summaryStyle) },
this.state.flattened.length,
" usages, ",
this.props.alreadyOpenFilePaths.length,
" files open, ",
this.props.currentlyClosedFilePaths.length,
" files closed"),
React.createElement("div", { style: csx.extend(csx.horizontal, csx.flex, { overflow: 'hidden' }) },
React.createElement("div", { style: { width: '200px', overflow: 'auto' } }, filePathsRendered),
React.createElement("div", { style: csx.extend(csx.flex, csx.flexRoot, styles.modal.previewContainerStyle) }, previewRendered)))));
};
return RenameVariable;
}(ui_1.BaseComponent));
exports.RenameVariable = RenameVariable;
var monacoUtils = require("../monacoUtils");
var CommonEditorRegistry = monaco.CommonEditorRegistry;
var EditorAction = monaco.EditorAction;
var KeyCode = monaco.KeyCode;
var EditorContextKeys = monaco.EditorContextKeys;
var RenameVariableAction = /** @class */ (function (_super) {
__extends(RenameVariableAction, _super);
function RenameVariableAction() {
return _super.call(this, {
id: 'editor.action.renameVariable',
label: 'TypeScript: Rename Variable',
alias: 'TypeScript: Rename Variable',
precondition: EditorContextKeys.Writable,
kbOpts: {
kbExpr: EditorContextKeys.TextFocus,
primary: KeyCode.F2
}
}) || this;
}
RenameVariableAction.prototype.run = function (accessor, editor) {
var filePath = editor.filePath;
if (!state.inActiveProjectFilePath(filePath)) {
ui.notifyInfoNormalDisappear('The current file is no in the active project');
return;
}
var position = monacoUtils.getCurrentPosition(editor);
socketClient_1.server.getRenameInfo({ filePath: filePath, position: position }).then(function (res) {
if (!res.canRename) {
ui.notifyInfoNormalDisappear("Rename not available at cursor location");
}
else {
var filePaths = Object.keys(res.locations);
// if there is only a single file path and that is the current and there aren't that many usages
// we do the rename inline
if (filePaths.length == 1
&& filePaths[0] == filePath
&& res.locations[filePath].length < 5) {
selectName(editor, res.locations[filePath]);
}
else {
var _a = uix.API.getClosedVsOpenFilePaths(filePaths), alreadyOpenFilePaths = _a.alreadyOpenFilePaths, currentlyClosedFilePaths = _a.currentlyClosedFilePaths;
var _b = ui.getUnmountableNode(), node = _b.node, unmount = _b.unmount;
ReactDOM.render(React.createElement(RenameVariable, { info: res, alreadyOpenFilePaths: alreadyOpenFilePaths, currentlyClosedFilePaths: currentlyClosedFilePaths, unmount: unmount }), node);
}
}
});
};
return RenameVariableAction;
}(EditorAction));
CommonEditorRegistry.registerEditorAction(new RenameVariableAction());
/** Selects the locations keeping the current one as the first (to allow easy escape back to current cursor) */
function selectName(editor, locations) {
var ranges = [];
var curPos = editor.getSelection();
for (var i = 0; i < locations.length; i++) {
var ref = locations[i];
var from = editor.getModel().getPositionAt(ref.start);
var to = editor.getModel().getPositionAt(ref.start + ref.length);
var range = new monaco.Range(from.lineNumber, from.column, to.lineNumber, to.column);
var selection = {
selectionStartLineNumber: from.lineNumber,
selectionStartColumn: from.column,
positionLineNumber: to.lineNumber,
positionColumn: to.column
};
if (!monaco.Range.containsRange(range, curPos))
ranges.push(selection);
else
ranges.unshift(selection);
}
editor.setSelections(ranges);
}