Skip to content

Commit c6b18cd

Browse files
authored
ref: Enable explicit-function-return-type eslint rule (#742)
* ref: Enable `explicit-function-return-type` eslint rule * better solution for rollup-vite type conflicts * cleanup
1 parent ea04da5 commit c6b18cd

File tree

11 files changed

+78
-47
lines changed

11 files changed

+78
-47
lines changed

packages/babel-plugin-component-annotate/src/index.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ function functionBodyPushAttributes(
152152
sourceFileName: string | undefined,
153153
attributeNames: string[],
154154
ignoredComponents: string[]
155-
) {
155+
): void {
156156
let jsxNode: Babel.NodePath;
157157

158158
const functionBody = path.get("body").get("body");
@@ -248,7 +248,7 @@ function processJSX(
248248
sourceFileName: string | undefined,
249249
attributeNames: string[],
250250
ignoredComponents: string[]
251-
) {
251+
): void {
252252
if (!jsxNode) {
253253
return;
254254
}
@@ -323,7 +323,7 @@ function applyAttributes(
323323
sourceFileName: string | undefined,
324324
attributeNames: string[],
325325
ignoredComponents: string[]
326-
) {
326+
): void {
327327
const [componentAttributeName, elementAttributeName, sourceFileAttributeName] = attributeNames;
328328

329329
if (isReactFragment(t, openingElement)) {
@@ -390,7 +390,7 @@ function applyAttributes(
390390
}
391391
}
392392

393-
function sourceFileNameFromState(state: AnnotationPluginPass) {
393+
function sourceFileNameFromState(state: AnnotationPluginPass): string | undefined {
394394
const name = fullSourceFileNameFromState(state);
395395
if (!name) {
396396
return undefined;
@@ -416,7 +416,7 @@ function fullSourceFileNameFromState(state: AnnotationPluginPass): string | null
416416
return null;
417417
}
418418

419-
function isKnownIncompatiblePluginFromState(state: AnnotationPluginPass) {
419+
function isKnownIncompatiblePluginFromState(state: AnnotationPluginPass): boolean {
420420
const fullSourceFileName = fullSourceFileNameFromState(state);
421421

422422
if (!fullSourceFileName) {

packages/bundler-plugin-core/src/build-plugin-manager.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ export function createSentryBuildPluginManager(
172172

173173
let sessionHasEnded = false; // Just to prevent infinite loops with beforeExit, which is called whenever the event loop empties out
174174

175-
function endSession() {
175+
function endSession(): void {
176176
if (sessionHasEnded) {
177177
return;
178178
}
@@ -206,7 +206,7 @@ export function createSentryBuildPluginManager(
206206
* or continue up to them. By default, @param throwByDefault controls if the plugin
207207
* should throw an error (which causes a build fail in most bundlers) or continue.
208208
*/
209-
function handleRecoverableError(unknownError: unknown, throwByDefault: boolean) {
209+
function handleRecoverableError(unknownError: unknown, throwByDefault: boolean): void {
210210
sentrySession.status = "abnormal";
211211
try {
212212
if (options.errorHandler) {
@@ -251,13 +251,13 @@ export function createSentryBuildPluginManager(
251251
const dependenciesOnBuildArtifacts = new Set<symbol>();
252252
const buildArtifactsDependencySubscribers: (() => void)[] = [];
253253

254-
function notifyBuildArtifactDependencySubscribers() {
254+
function notifyBuildArtifactDependencySubscribers(): void {
255255
buildArtifactsDependencySubscribers.forEach((subscriber) => {
256256
subscriber();
257257
});
258258
}
259259

260-
function createDependencyOnBuildArtifacts() {
260+
function createDependencyOnBuildArtifacts(): () => void {
261261
const dependencyIdentifier = Symbol();
262262
dependenciesOnBuildArtifacts.add(dependencyIdentifier);
263263

@@ -273,7 +273,7 @@ export function createSentryBuildPluginManager(
273273
* It is very important that this function is called as late as possible before wanting to await the Promise to give
274274
* the dependency producers as much time as possible to register themselves.
275275
*/
276-
function waitUntilBuildArtifactDependenciesAreFreed() {
276+
function waitUntilBuildArtifactDependenciesAreFreed(): Promise<void> {
277277
return new Promise<void>((resolve) => {
278278
buildArtifactsDependencySubscribers.push(() => {
279279
if (dependenciesOnBuildArtifacts.size === 0) {
@@ -607,7 +607,7 @@ export function createSentryBuildPluginManager(
607607
}
608608
);
609609
const workers: Promise<void>[] = [];
610-
const worker = async () => {
610+
const worker = async (): Promise<void> => {
611611
while (preparationTasks.length > 0) {
612612
const task = preparationTasks.shift();
613613
if (task) {

packages/bundler-plugin-core/src/debug-id-upload.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export async function prepareBundleForDebugIdUpload(
2626
logger: Logger,
2727
rewriteSourcesHook: RewriteSourcesHook,
2828
resolveSourceMapHook: ResolveSourceMapHook | undefined
29-
) {
29+
): Promise<void> {
3030
let bundleContent;
3131
try {
3232
bundleContent = await promisify(fs.readFile)(bundleFilePath, "utf8");

packages/bundler-plugin-core/src/index.ts

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,17 @@ import SentryCli from "@sentry/cli";
44
import { logger } from "@sentry/utils";
55
import * as fs from "fs";
66
import { glob } from "glob";
7-
import MagicString from "magic-string";
7+
import MagicString, { SourceMap } from "magic-string";
88
import * as path from "path";
9-
import { createUnplugin, TransformResult, UnpluginOptions } from "unplugin";
9+
import { createUnplugin, TransformResult, UnpluginInstance, UnpluginOptions } from "unplugin";
1010
import { createSentryBuildPluginManager } from "./build-plugin-manager";
1111
import { createDebugIdUploadFunction } from "./debug-id-upload";
1212
import { Logger } from "./logger";
1313
import { Options, SentrySDKBuildFlags } from "./types";
1414
import {
1515
generateGlobalInjectorCode,
1616
generateModuleMetadataInjectorCode,
17-
getDependencies,
18-
getPackageJson,
19-
parseMajorVersion,
17+
getBuildInformation as actualGetBuildInformation,
2018
replaceBooleanFlagsInCode,
2119
stringToUUID,
2220
stripQueryAndHashFromPath,
@@ -46,7 +44,7 @@ export function sentryUnpluginFactory({
4644
debugIdInjectionPlugin,
4745
debugIdUploadPlugin,
4846
bundleSizeOptimizationsPlugin,
49-
}: SentryUnpluginFactoryOptions) {
47+
}: SentryUnpluginFactoryOptions): UnpluginInstance<Options | undefined, true> {
5048
return createUnplugin<Options | undefined, true>((userOptions = {}, unpluginMetaContext) => {
5149
const sentryBuildPluginManager = createSentryBuildPluginManager(userOptions, {
5250
loggerPrefix:
@@ -177,22 +175,11 @@ export function sentryUnpluginFactory({
177175
}
178176

179177
/**
180-
* @deprecated
178+
* @deprecated This will be removed in v4
181179
*/
182-
// TODO(v4): Don't export this from the package
183-
export function getBuildInformation() {
184-
const packageJson = getPackageJson();
185-
186-
const { deps, depsVersions } = packageJson
187-
? getDependencies(packageJson)
188-
: { deps: [], depsVersions: {} };
189-
190-
return {
191-
deps,
192-
depsVersions,
193-
nodeVersion: parseMajorVersion(process.version),
194-
};
195-
}
180+
// TODO(v4): Don't export this from the package but keep the utils version
181+
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
182+
export const getBuildInformation = actualGetBuildInformation;
196183

197184
/**
198185
* Determines whether the Sentry CLI binary is in its expected location.
@@ -203,7 +190,11 @@ export function sentryCliBinaryExists(): boolean {
203190
return fs.existsSync(SentryCli.getPath());
204191
}
205192

206-
export function createRollupReleaseInjectionHooks(injectionCode: string) {
193+
export function createRollupReleaseInjectionHooks(injectionCode: string): {
194+
resolveId: UnpluginOptions["resolveId"];
195+
load: UnpluginOptions["load"];
196+
transform: UnpluginOptions["transform"];
197+
} {
207198
const virtualReleaseInjectionFileId = "\0sentry-release-injection-file";
208199
return {
209200
resolveId(id: string) {
@@ -260,7 +251,9 @@ export function createRollupReleaseInjectionHooks(injectionCode: string) {
260251
};
261252
}
262253

263-
export function createRollupBundleSizeOptimizationHooks(replacementValues: SentrySDKBuildFlags) {
254+
export function createRollupBundleSizeOptimizationHooks(replacementValues: SentrySDKBuildFlags): {
255+
transform: UnpluginOptions["transform"];
256+
} {
264257
return {
265258
transform(code: string) {
266259
return replaceBooleanFlagsInCode(code, replacementValues);
@@ -274,7 +267,24 @@ const COMMENT_USE_STRICT_REGEX =
274267
// Note: CodeQL complains that this regex potentially has n^2 runtime. This likely won't affect realistic files.
275268
/^(?:\s*|\/\*(?:.|\r|\n)*?\*\/|\/\/.*[\n\r])*(?:"[^"]*";|'[^']*';)?/;
276269

277-
export function createRollupDebugIdInjectionHooks() {
270+
/**
271+
* Simplified `renderChunk` hook type from Rollup.
272+
* We can't reference the type directly because the Vite plugin complains
273+
* about type mismatches
274+
*/
275+
type RenderChunkHook = (
276+
code: string,
277+
chunk: {
278+
fileName: string;
279+
}
280+
) => {
281+
code: string;
282+
map: SourceMap;
283+
} | null;
284+
285+
export function createRollupDebugIdInjectionHooks(): {
286+
renderChunk: RenderChunkHook;
287+
} {
278288
return {
279289
renderChunk(code: string, chunk: { fileName: string }) {
280290
if (
@@ -311,7 +321,9 @@ export function createRollupDebugIdInjectionHooks() {
311321
};
312322
}
313323

314-
export function createRollupModuleMetadataInjectionHooks(injectionCode: string) {
324+
export function createRollupModuleMetadataInjectionHooks(injectionCode: string): {
325+
renderChunk: RenderChunkHook;
326+
} {
315327
return {
316328
renderChunk(code: string, chunk: { fileName: string }) {
317329
if (
@@ -349,7 +361,12 @@ export function createRollupDebugIdUploadHooks(
349361
upload: (buildArtifacts: string[]) => Promise<void>,
350362
_logger: Logger,
351363
createDependencyOnBuildArtifacts: () => () => void
352-
) {
364+
): {
365+
writeBundle: (
366+
outputOptions: { dir?: string; file?: string },
367+
bundle: { [fileName: string]: unknown }
368+
) => Promise<void>;
369+
} {
353370
const freeGlobalDependencyOnDebugIdSourcemapArtifacts = createDependencyOnBuildArtifacts();
354371
return {
355372
async writeBundle(
@@ -390,7 +407,9 @@ export function createRollupDebugIdUploadHooks(
390407
};
391408
}
392409

393-
export function createComponentNameAnnotateHooks(ignoredComponents?: string[]) {
410+
export function createComponentNameAnnotateHooks(ignoredComponents?: string[]): {
411+
transform: UnpluginOptions["transform"];
412+
} {
394413
type ParserPlugins = NonNullable<
395414
NonNullable<Parameters<typeof transformAsync>[1]>["parserOpts"]
396415
>["plugins"];

packages/bundler-plugin-core/src/sentry/telemetry.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export function setTelemetryDataOnScope(
6464
options: NormalizedOptions,
6565
scope: Scope,
6666
buildTool: string
67-
) {
67+
): void {
6868
const { org, project, release, errorHandler, sourcemaps, reactComponentAnnotation } = options;
6969

7070
scope.setTag("upload-legacy-sourcemaps", !!release.uploadLegacySourcemaps);
@@ -161,7 +161,7 @@ export async function allowedToSendTelemetry(options: NormalizedOptions): Promis
161161
/**
162162
* Flushing the SDK client can fail. We never want to crash the plugin because of telemetry.
163163
*/
164-
export async function safeFlushTelemetry(sentryClient: Client) {
164+
export async function safeFlushTelemetry(sentryClient: Client): Promise<void> {
165165
try {
166166
await sentryClient.flush(2000);
167167
} catch {

packages/bundler-plugin-core/src/sentry/transports.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ function createRequestExecutor(options: BaseTransportOptions): TransportRequestE
9393
/**
9494
* Creates a Transport that uses native the native 'http' and 'https' modules to send events to Sentry.
9595
*/
96-
function makeNodeTransport(options: BaseTransportOptions) {
96+
function makeNodeTransport(options: BaseTransportOptions): Transport {
9797
const requestExecutor = createRequestExecutor(options);
9898
return createTransport(options, requestExecutor);
9999
}

packages/bundler-plugin-core/src/utils.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ export function generateGlobalInjectorCode({
311311
}: {
312312
release: string;
313313
injectBuildInformation: boolean;
314-
}) {
314+
}): string {
315315
// The code below is mostly ternary operators because it saves bundle size.
316316
// The checks are to support as many environments as possible. (Node.js, Browser, webworkers, etc.)
317317
let code = `{
@@ -341,7 +341,7 @@ export function generateGlobalInjectorCode({
341341
}
342342

343343
// eslint-disable-next-line @typescript-eslint/no-explicit-any
344-
export function generateModuleMetadataInjectorCode(metadata: any) {
344+
export function generateModuleMetadataInjectorCode(metadata: any): string {
345345
// The code below is mostly ternary operators because it saves bundle size.
346346
// The checks are to support as many environments as possible. (Node.js, Browser, webworkers, etc.)
347347
// We are merging the metadata objects in case modules are bundled twice with the plugin
@@ -369,7 +369,11 @@ export function generateModuleMetadataInjectorCode(metadata: any) {
369369
}`;
370370
}
371371

372-
function getBuildInformation() {
372+
export function getBuildInformation(): {
373+
deps: string[];
374+
depsVersions: Record<string, number>;
375+
nodeVersion: number | undefined;
376+
} {
373377
const packageJson = getPackageJson();
374378

375379
const { deps, depsVersions } = packageJson
@@ -413,7 +417,7 @@ export function replaceBooleanFlagsInCode(
413417
}
414418

415419
// https://turbo.build/repo/docs/reference/system-environment-variables#environment-variables-in-tasks
416-
export function getTurborepoEnvPassthroughWarning(envVarName: string) {
420+
export function getTurborepoEnvPassthroughWarning(envVarName: string): string {
417421
return process.env["TURBO_HASH"]
418422
? `\nYou seem to be using Turborepo, did you forget to put ${envVarName} in \`passThroughEnv\`? https://turbo.build/repo/docs/reference/configuration#passthroughenv`
419423
: "";

packages/bundler-plugin-core/test/utils.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import path from "node:path";
1010

1111
type PackageJson = Record<string, unknown>;
1212

13-
function getCwdFor(dirName: string) {
13+
function getCwdFor(dirName: string): string {
1414
return path.resolve(__dirname + dirName);
1515
}
1616

packages/e2e-tests/.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,6 @@ module.exports = {
2525
},
2626
rules: {
2727
"no-console": "off",
28+
"@typescript-eslint/explicit-function-return-type": "off",
2829
},
2930
};

packages/eslint-configs/base.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,9 @@ module.exports = {
1515
{ argsIgnorePattern: "^_", caughtErrorsIgnorePattern: "^_" },
1616
],
1717
"no-undef": "error", // https://github.com/typescript-eslint/typescript-eslint/issues/4580#issuecomment-1047144015
18+
// Although for most codebases inferencing the return type is fine, we explicitly ask to annotate
19+
// all functions with a return type. This is so that intent is as clear as possible as well as to
20+
// avoid accidental breaking changes.
21+
"@typescript-eslint/explicit-function-return-type": ["error", { allowExpressions: true }],
1822
},
1923
};

0 commit comments

Comments
 (0)