Repository: rollup/rollup
File: src/utils/renderHelpers.ts (TypeScript)

Code before:
import type MagicString from 'magic-string';
import type { Node, StatementNode } from '../ast/nodes/shared/Node';
import type Variable from '../ast/variables/Variable';
import type { InternalModuleFormat } from '../rollup/types';
import type { PluginDriver } from './PluginDriver';
import type { GenerateCodeSnippets } from './generateCodeSnippets';
import { treeshakeNode } from './treeshakeNode';

export interface RenderOptions {
	dynamicImportFunction: string | undefined;
	exportNamesByVariable: Map<Variable, string[]>;
	format: InternalModuleFormat;
	freeze: boolean;
	indent: string;
	namespaceToStringTag: boolean;
	pluginDriver: PluginDriver;
	snippets: GenerateCodeSnippets;
	useOriginalName?: (variable: Variable) => boolean;
}

export interface NodeRenderOptions {
	end?: number;
	isCalleeOfRenderedParent?: boolean;
	isNoStatement?: boolean;
	isShorthandProperty?: boolean;
	preventASI?: boolean;
	/* Indicates if the direct parent of an element changed.
	Necessary for determining the "this" context of callees. */
	renderedParentType?: string;
	/* Indicates if the parent or ancestor surrounding an element has changed and what it changed to.
	Necessary for adding parentheses. */
	renderedSurroundingElement?: string;
	start?: number;
}

export const NO_SEMICOLON: NodeRenderOptions = { isNoStatement: true };

// This assumes there are only white-space and comments between start and the string we are looking for
export function findFirstOccurrenceOutsideComment(
	code: string,
	searchString: string,
	start = 0
): number {

Review comment (performance):
That is a really minimal solution, I like that. Very minor point: For performance reasons, it is better if objects passed to functions always have the same properties. Then the compiler can produce more optimized code. Thus, a better type would be

```js
useOriginalName: ((variable: Variable) => boolean) | null
```

and you add an explicit `null` where the RenderOptions are created.

Code after:
import type MagicString from 'magic-string';
import type { Node, StatementNode } from '../ast/nodes/shared/Node';
import type Variable from '../ast/variables/Variable';
import type { InternalModuleFormat } from '../rollup/types';
import type { PluginDriver } from './PluginDriver';
import type { GenerateCodeSnippets } from './generateCodeSnippets';
import { treeshakeNode } from './treeshakeNode';

export interface RenderOptions {
	dynamicImportFunction: string | undefined;
	exportNamesByVariable: Map<Variable, string[]>;
	format: InternalModuleFormat;
	freeze: boolean;
	indent: string;
	namespaceToStringTag: boolean;
	pluginDriver: PluginDriver;
	snippets: GenerateCodeSnippets;
	useOriginalName: ((variable: Variable) => boolean) | null;
}

export interface NodeRenderOptions {
	end?: number;
	isCalleeOfRenderedParent?: boolean;
	isNoStatement?: boolean;
	isShorthandProperty?: boolean;
	preventASI?: boolean;
	/* Indicates if the direct parent of an element changed.
	Necessary for determining the "this" context of callees. */
	renderedParentType?: string;
	/* Indicates if the parent or ancestor surrounding an element has changed and what it changed to.
	Necessary for adding parentheses. */
	renderedSurroundingElement?: string;
	start?: number;
}

export const NO_SEMICOLON: NodeRenderOptions = { isNoStatement: true };

// This assumes there are only white-space and comments between start and the string we are looking for
export function findFirstOccurrenceOutsideComment(
	code: string,
	searchString: string,
	start = 0
): number {