Repository: rollup/rollup
File: src/ast/nodes/CallExpression.ts (TypeScript)

Code before:
		if (
			this.annotations &&
			(this.scope.context.options.treeshake as NormalizedTreeshakingOptions).annotations
		) {
			this.annotationPure = this.annotations.some(comment => comment.type === 'pure');
		}
	}

	render(
		code: MagicString,
		options: RenderOptions,
		{ renderedSurroundingElement }: NodeRenderOptions = BLANK
	): void {
		if (this.callee instanceof Identifier) {
			const variable = this.scope.findVariable(this.callee.name);

			if (!this._namespaceWarned && variable.isNamespace) {
				this._namespaceWarned = true;
				this.scope.context.log(LOGLEVEL_WARN, logCannotCallNamespace(this.callee.name), this.start);
			}

			if (!this._evalWarned && this.callee.name === 'eval') {
				this._evalWarned = true;
				this.scope.context.log(LOGLEVEL_WARN, logEval(this.scope.context.module.id), this.start);
			}
		}
		this.callee.render(code, options, {
			isCalleeOfRenderedParent: true,
			renderedSurroundingElement
		});
		renderCallArguments(code, options, this);
	}

	applyDeoptimizations() {
		this.deoptimized = true;
		this.callee.deoptimizeArgumentsOnInteractionAtPath(
			this.interaction,
			EMPTY_PATH,
			SHARED_RECURSION_TRACKER
		);
		this.scope.context.requestTreeshakingPass();
	}

	protected getReturnExpression(
		recursionTracker: EntityPathTracker = SHARED_RECURSION_TRACKER
	): [expression: ExpressionEntity, isPure: boolean] {
		if (this.returnExpression === null) {
			this.returnExpression = UNKNOWN_RETURN_EXPRESSION;
			return (this.returnExpression = this.callee.getReturnExpressionWhenCalledAtPath(
				EMPTY_PATH,
				this.interaction,

Review comment (suggestion):
Maybe instead, use a single flag at the top?

```suggestion
		if (this.callee instanceof Identifier && !this.hasCheckedForWarnings) {
		  this.hasCheckedForWarnings = true;
			const variable = this.scope.findVariable(this.callee.name);

			if (variable.isNamespace) {
				this.scope.context.log(LOGLEVEL_WARN, logCannotCallNamespace(this.callee.name), this.start);
			}

			if (this.callee.name === 'eval') {
				this.scope.context.log(LOGLEVEL_WARN, logEval(this.scope.context.module.id), this.start);
			}
		}
```

Code after:
	}

	initialise() {
		super.initialise();
		if (
			this.annotations &&
			(this.scope.context.options.treeshake as NormalizedTreeshakingOptions).annotations
		) {
			this.annotationPure = this.annotations.some(comment => comment.type === 'pure');
		}
	}

	render(
		code: MagicString,
		options: RenderOptions,
		{ renderedSurroundingElement }: NodeRenderOptions = BLANK
	): void {
		this.callee.render(code, options, {
			isCalleeOfRenderedParent: true,
			renderedSurroundingElement
		});
		renderCallArguments(code, options, this);

		if (this.callee instanceof Identifier && !this.hasCheckedForWarnings) {
			this.hasCheckedForWarnings = true;
			const variable = this.scope.findVariable(this.callee.name);
			if (variable.isNamespace) {
				this.scope.context.log(LOGLEVEL_WARN, logCannotCallNamespace(this.callee.name), this.start);
			}
			if (this.callee.name === 'eval') {
				this.scope.context.log(LOGLEVEL_WARN, logEval(this.scope.context.module.id), this.start);
			}
		}
	}

	applyDeoptimizations() {
		this.deoptimized = true;
		this.callee.deoptimizeArgumentsOnInteractionAtPath(
			this.interaction,
			EMPTY_PATH,
			SHARED_RECURSION_TRACKER
		);
		this.scope.context.requestTreeshakingPass();
	}

	protected getReturnExpression(
		recursionTracker: EntityPathTracker = SHARED_RECURSION_TRACKER
	): [expression: ExpressionEntity, isPure: boolean] {
		if (this.returnExpression === null) {
			this.returnExpression = UNKNOWN_RETURN_EXPRESSION;
			return (this.returnExpression = this.callee.getReturnExpressionWhenCalledAtPath(