Merge pull request #269985 from microsoft/tyriar/more_terminal_any

Remove more as any from terminal
This commit is contained in:
Daniel Imms
2025-10-08 13:18:01 +09:00
committed by GitHub
7 changed files with 138 additions and 77 deletions

View File

@@ -66,33 +66,38 @@ async function getAliases(options: ExecOptionsWithStringEncoding, existingComman
console.error('Error parsing output:', e);
return [];
}
return (json as any[]).map(e => {
// Aliases sometimes use the same Name and DisplayName, show them as methods in this case.
const isAlias = e.Name !== e.DisplayName;
const detailParts: string[] = [];
if (e.Definition) {
detailParts.push(e.Definition);
}
if (e.ModuleName && e.Version) {
detailParts.push(`${e.ModuleName} v${e.Version}`);
}
let definitionCommand = undefined;
if (e.Definition) {
let definitionIndex = e.Definition.indexOf(' ');
if (definitionIndex === -1) {
definitionIndex = e.Definition.length;
definitionCommand = e.Definition.substring(0, definitionIndex);
if (!Array.isArray(json)) {
return [];
}
return (json as unknown[])
.filter(isPwshGetCommandEntry)
.map(e => {
// Aliases sometimes use the same Name and DisplayName, show them as methods in this case.
const isAlias = e.Name !== e.DisplayName;
const detailParts: string[] = [];
if (e.Definition) {
detailParts.push(e.Definition);
}
}
return {
label: e.Name,
detail: detailParts.join('\n\n'),
kind: (isAlias
? vscode.TerminalCompletionItemKind.Alias
: vscode.TerminalCompletionItemKind.Method),
definitionCommand,
};
});
if (e.ModuleName && e.Version) {
detailParts.push(`${e.ModuleName} v${e.Version}`);
}
let definitionCommand = undefined;
if (e.Definition) {
let definitionIndex = e.Definition.indexOf(' ');
if (definitionIndex === -1) {
definitionIndex = e.Definition.length;
definitionCommand = e.Definition.substring(0, definitionIndex);
}
}
return {
label: e.Name,
detail: detailParts.join('\n\n'),
kind: (isAlias
? vscode.TerminalCompletionItemKind.Alias
: vscode.TerminalCompletionItemKind.Method),
definitionCommand,
};
});
}
async function getCommands(options: ExecOptionsWithStringEncoding, existingCommands?: Set<string>): Promise<ICompletionResource[]> {
@@ -100,15 +105,19 @@ async function getCommands(options: ExecOptionsWithStringEncoding, existingComma
...options,
maxBuffer: 1024 * 1024 * 100 // This is a lot of content, increase buffer size
});
let json: any;
let json: unknown;
try {
json = JSON.parse(output);
} catch (e) {
console.error('Error parsing pwsh output:', e);
return [];
}
if (!Array.isArray(json)) {
return [];
}
return (
(json as any[])
(json as unknown[])
.filter(isPwshGetCommandEntry)
.filter(e => e.CommandType !== PwshCommandType.Alias)
.map(e => {
const detailParts: string[] = [];
@@ -126,3 +135,39 @@ async function getCommands(options: ExecOptionsWithStringEncoding, existingComma
})
);
}
interface IPwshGetCommandEntry {
Name: string;
CommandType: PwshCommandType;
DisplayName?: string | null;
Definition?: string | null;
ModuleName?: string | null;
Version?: string | null;
}
function isPwshGetCommandEntry(entry: unknown): entry is IPwshGetCommandEntry {
return (
isObject(entry) &&
'Name' in entry && typeof entry.Name === 'string' &&
'CommandType' in entry && typeof entry.CommandType === 'number' &&
(!('DisplayName' in entry) || typeof entry.DisplayName === 'string' || entry.DisplayName === null) &&
(!('Definition' in entry) || typeof entry.Definition === 'string' || entry.Definition === null) &&
(!('ModuleName' in entry) || typeof entry.ModuleName === 'string' || entry.ModuleName === null) &&
(!('Version' in entry) || typeof entry.Version === 'string' || entry.Version === null)
);
}
/**
* @returns whether the provided parameter is of type `object` but **not**
* `null`, an `array`, a `regexp`, nor a `date`.
*/
export function isObject(obj: unknown): obj is Object {
// The method can't do a type cast since there are type (like strings) which
// are subclasses of any put not positvely matched by the function. Hence type
// narrowing results in wrong results.
return typeof obj === 'object'
&& obj !== null
&& !Array.isArray(obj)
&& !(obj instanceof RegExp)
&& !(obj instanceof Date);
}

View File

@@ -91,8 +91,7 @@ registerTerminalAction({
}
escapedData = escapedData.slice(0, match.index) + String.fromCharCode(parseInt(match[1], 16)) + escapedData.slice(match.index + 4);
}
// eslint-disable-next-line local/code-no-any-casts
const xterm = instance.xterm as any as IInternalXtermTerminal;
const xterm = instance.xterm as IInternalXtermTerminal;
xterm._writeText(escapedData);
}
});

View File

@@ -149,8 +149,10 @@ export class TerminalLinkManager extends DisposableStore {
activeHoverDisposable = undefined;
activeTooltipScheduler?.dispose();
activeTooltipScheduler = new RunOnceScheduler(() => {
// eslint-disable-next-line local/code-no-any-casts
const core = (this._xterm as any)._core as IXtermCore;
interface XtermWithCore extends Terminal {
_core: IXtermCore;
}
const core = (this._xterm as XtermWithCore)._core;
const cellDimensions = {
width: core._renderService.dimensions.css.cell.width,
height: core._renderService.dimensions.css.cell.height
@@ -348,8 +350,10 @@ export class TerminalLinkManager extends DisposableStore {
return;
}
// eslint-disable-next-line local/code-no-any-casts
const core = (this._xterm as any)._core as IXtermCore;
interface XtermWithCore extends Terminal {
_core: IXtermCore;
}
const core = (this._xterm as XtermWithCore)._core;
const cellDimensions = {
width: core._renderService.dimensions.css.cell.width,
height: core._renderService.dimensions.css.cell.height

View File

@@ -406,8 +406,10 @@ export class TerminalStickyScrollOverlay extends Disposable {
}
hoverOverlay.title = hoverTitle;
// eslint-disable-next-line local/code-no-any-casts
const scrollBarWidth = (this._xterm.raw as any as { _core: IXtermCore })._core.viewport?.scrollBarWidth;
interface XtermWithCore extends XTermTerminal {
_core: IXtermCore;
}
const scrollBarWidth = (this._xterm.raw as XtermWithCore)._core.viewport?.scrollBarWidth;
if (scrollBarWidth !== undefined) {
this._element.style.right = `${scrollBarWidth}px`;
}

View File

@@ -682,8 +682,10 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest
}
private _getTerminalDimensions(): { width: number; height: number } {
// eslint-disable-next-line local/code-no-any-casts
const cssCellDims = (this._terminal as any as { _core: IXtermCore })._core._renderService.dimensions.css.cell;
interface XtermWithCore extends Terminal {
_core: IXtermCore;
}
const cssCellDims = (this._terminal as XtermWithCore)._core._renderService.dimensions.css.cell;
return {
width: cssCellDims.width,
height: cssCellDims.height,
@@ -708,8 +710,10 @@ export class SuggestAddon extends Disposable implements ITerminalAddon, ISuggest
return this._cachedFontInfo;
}
// eslint-disable-next-line local/code-no-any-casts
const core = (this._terminal as any)._core as IXtermCore;
interface XtermWithCore extends Terminal {
_core: IXtermCore;
}
const core = (this._terminal as XtermWithCore)._core;
const font = this._terminalConfigurationService.getFont(dom.getActiveWindow(), core);
let lineHeight: number = font.lineHeight;
const fontSize: number = font.fontSize;

View File

@@ -50,8 +50,12 @@ const enum StatsConstants {
*/
const PREDICTION_OMIT_RE = /^(\x1b\[(\??25[hl]|\??[0-9;]+n))+/;
// eslint-disable-next-line local/code-no-any-casts
const core = (terminal: Terminal): IXtermCore => (terminal as any)._core;
const core = (terminal: Terminal): IXtermCore => {
interface XtermWithCore extends Terminal {
_core: IXtermCore;
}
return (terminal as XtermWithCore)._core;
};
const flushOutput = (terminal: Terminal) => {
// TODO: Flushing output is not possible anymore without async
};

View File

@@ -71,43 +71,46 @@ class TerminalMouseWheelZoomContribution extends Disposable implements ITerminal
let gestureHasZoomModifiers = false;
let gestureAccumulatedDelta = 0;
raw.attachCustomWheelEventHandler((e: WheelEvent) => {
// eslint-disable-next-line local/code-no-any-casts
const browserEvent = e as any as IMouseWheelEvent;
if (classifier.isPhysicalMouseWheel()) {
if (this._hasMouseWheelZoomModifiers(browserEvent)) {
const delta = browserEvent.deltaY > 0 ? -1 : 1;
const newFontSize = this._clampFontSize(this._getConfigFontSize() + delta);
this._configurationService.updateValue(TerminalSettingId.FontSize, newFontSize);
// EditorZoom.setZoomLevel(zoomLevel + delta);
browserEvent.preventDefault();
browserEvent.stopPropagation();
return false;
}
} else {
// we consider mousewheel events that occur within 50ms of each other to be part of the same gesture
// we don't want to consider mouse wheel events where ctrl/cmd is pressed during the inertia phase
// we also want to accumulate deltaY values from the same gesture and use that to set the zoom level
if (Date.now() - prevMouseWheelTime > 50) {
// reset if more than 50ms have passed
gestureStartFontSize = this._getConfigFontSize();
gestureHasZoomModifiers = this._hasMouseWheelZoomModifiers(browserEvent);
gestureAccumulatedDelta = 0;
}
raw.attachCustomWheelEventHandler((browserEvent: WheelEvent) => {
function isWheelEvent(e: MouseEvent): e is IMouseWheelEvent {
return 'wheelDelta' in e && 'wheelDeltaX' in e && 'wheelDeltaY' in e;
}
if (isWheelEvent(browserEvent)) {
if (classifier.isPhysicalMouseWheel()) {
if (this._hasMouseWheelZoomModifiers(browserEvent)) {
const delta = browserEvent.deltaY > 0 ? -1 : 1;
const newFontSize = this._clampFontSize(this._getConfigFontSize() + delta);
this._configurationService.updateValue(TerminalSettingId.FontSize, newFontSize);
// EditorZoom.setZoomLevel(zoomLevel + delta);
browserEvent.preventDefault();
browserEvent.stopPropagation();
return false;
}
} else {
// we consider mousewheel events that occur within 50ms of each other to be part of the same gesture
// we don't want to consider mouse wheel events where ctrl/cmd is pressed during the inertia phase
// we also want to accumulate deltaY values from the same gesture and use that to set the zoom level
if (Date.now() - prevMouseWheelTime > 50) {
// reset if more than 50ms have passed
gestureStartFontSize = this._getConfigFontSize();
gestureHasZoomModifiers = this._hasMouseWheelZoomModifiers(browserEvent);
gestureAccumulatedDelta = 0;
}
prevMouseWheelTime = Date.now();
gestureAccumulatedDelta += browserEvent.deltaY;
if (gestureHasZoomModifiers) {
const deltaAbs = Math.ceil(Math.abs(gestureAccumulatedDelta / 5));
const deltaDirection = gestureAccumulatedDelta > 0 ? -1 : 1;
const delta = deltaAbs * deltaDirection;
const newFontSize = this._clampFontSize(gestureStartFontSize + delta);
this._configurationService.updateValue(TerminalSettingId.FontSize, newFontSize);
prevMouseWheelTime = Date.now();
gestureAccumulatedDelta += browserEvent.deltaY;
browserEvent.preventDefault();
browserEvent.stopPropagation();
return false;
if (gestureHasZoomModifiers) {
const deltaAbs = Math.ceil(Math.abs(gestureAccumulatedDelta / 5));
const deltaDirection = gestureAccumulatedDelta > 0 ? -1 : 1;
const delta = deltaAbs * deltaDirection;
const newFontSize = this._clampFontSize(gestureStartFontSize + delta);
this._configurationService.updateValue(TerminalSettingId.FontSize, newFontSize);
gestureAccumulatedDelta += browserEvent.deltaY;
browserEvent.preventDefault();
browserEvent.stopPropagation();
return false;
}
}
}
return true;