mirror of
https://github.com/vector-im/element-call.git
synced 2026-07-09 18:29:21 +00:00
Add lint rule to make sure future child loggers are setup correctly
This commit is contained in:
@@ -34,6 +34,7 @@
|
|||||||
"/*\nCopyright %%CURRENT_YEAR%% Element Creations Ltd.\n\nSPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial\nPlease see LICENSE in the repository root for full details.\n*/\n\n"
|
"/*\nCopyright %%CURRENT_YEAR%% Element Creations Ltd.\n\nSPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial\nPlease see LICENSE in the repository root for full details.\n*/\n\n"
|
||||||
],
|
],
|
||||||
"element-call/no-observablescope-leak": "error",
|
"element-call/no-observablescope-leak": "error",
|
||||||
|
"element-call/no-top-level-logger-get-child": "error",
|
||||||
"jsdoc/empty-tags": "error",
|
"jsdoc/empty-tags": "error",
|
||||||
"jsdoc/check-property-names": "error",
|
"jsdoc/check-property-names": "error",
|
||||||
"jsdoc/require-param-description": "warn",
|
"jsdoc/require-param-description": "warn",
|
||||||
|
|||||||
92
eslint/NoTopLevelLoggerGetChild.js
Normal file
92
eslint/NoTopLevelLoggerGetChild.js
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2026 Element Creations Ltd.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||||
|
Please see LICENSE in the repository root for full details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ESLintUtils } from "@typescript-eslint/utils";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Node types that introduce a new non-module scope. A getChild() call nested
|
||||||
|
* inside any of these is considered "not at the top level".
|
||||||
|
*/
|
||||||
|
const FUNCTION_OR_CLASS_TYPES = new Set([
|
||||||
|
"FunctionDeclaration",
|
||||||
|
"FunctionExpression",
|
||||||
|
"ArrowFunctionExpression",
|
||||||
|
"ClassBody",
|
||||||
|
]);
|
||||||
|
|
||||||
|
const rule = ESLintUtils.RuleCreator(
|
||||||
|
() => "https://github.com/element-hq/element-call",
|
||||||
|
)({
|
||||||
|
name: "no-top-level-logger-get-child",
|
||||||
|
meta: {
|
||||||
|
type: "problem",
|
||||||
|
docs: {
|
||||||
|
description:
|
||||||
|
"Disallow calling logger.getChild() at the top level of a module." +
|
||||||
|
"`getChild` has to be called after the rageshake logger `init()`." +
|
||||||
|
"If it is called at the top level the child logger will never be setup for rageshakes.",
|
||||||
|
},
|
||||||
|
messages: {
|
||||||
|
noTopLevelGetChild:
|
||||||
|
"Do not call logger.getChild() at the top level of a module; move it inside a function or class instead that gets called after rageshake logger `init()` is called.",
|
||||||
|
},
|
||||||
|
schema: [],
|
||||||
|
},
|
||||||
|
create(context) {
|
||||||
|
// Tracks the local binding names that refer to the logger imported from
|
||||||
|
// 'matrix-js-sdk/lib/logger', e.g. both `logger` and `rootLogger` in:
|
||||||
|
// import { logger } from "matrix-js-sdk/lib/logger";
|
||||||
|
// import { logger as rootLogger } from "matrix-js-sdk/lib/logger";
|
||||||
|
const loggerNames = new Set();
|
||||||
|
|
||||||
|
return {
|
||||||
|
ImportDeclaration(node) {
|
||||||
|
if (node.source.value !== "matrix-js-sdk/lib/logger") return;
|
||||||
|
for (const specifier of node.specifiers) {
|
||||||
|
if (
|
||||||
|
specifier.type === "ImportSpecifier" &&
|
||||||
|
specifier.imported.name === "logger"
|
||||||
|
) {
|
||||||
|
loggerNames.add(specifier.local.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
CallExpression(node) {
|
||||||
|
// Must be a non-computed member expression call: something.getChild(...)
|
||||||
|
if (
|
||||||
|
node.callee.type !== "MemberExpression" ||
|
||||||
|
node.callee.computed ||
|
||||||
|
node.callee.property.type !== "Identifier" ||
|
||||||
|
node.callee.property.name !== "getChild"
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// The receiver must be one of the tracked logger names.
|
||||||
|
const object = node.callee.object;
|
||||||
|
if (object.type !== "Identifier" || !loggerNames.has(object.name))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Flag the call only when it is at module top level — i.e. there is no
|
||||||
|
// enclosing function or class body anywhere in the ancestor chain.
|
||||||
|
const ancestors = context.sourceCode.getAncestors(node);
|
||||||
|
const isTopLevel = !ancestors.some((a) =>
|
||||||
|
FUNCTION_OR_CLASS_TYPES.has(a.type),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isTopLevel) {
|
||||||
|
context.report({
|
||||||
|
messageId: "noTopLevelGetChild",
|
||||||
|
node,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default rule;
|
||||||
@@ -2,5 +2,6 @@ module.exports = {
|
|||||||
rules: {
|
rules: {
|
||||||
"copyright-header": require("./CopyrightHeader").default,
|
"copyright-header": require("./CopyrightHeader").default,
|
||||||
"no-observablescope-leak": require("./NoObservableScopeLeak").default,
|
"no-observablescope-leak": require("./NoObservableScopeLeak").default,
|
||||||
|
"no-top-level-logger-get-child": require("./NoTopLevelLoggerGetChild").default,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
AudioTrack,
|
AudioTrack,
|
||||||
type AudioTrackProps,
|
type AudioTrackProps,
|
||||||
} from "@livekit/components-react";
|
} from "@livekit/components-react";
|
||||||
import { logger } from "matrix-js-sdk/lib/logger";
|
import { logger as rootLogger } from "matrix-js-sdk/lib/logger";
|
||||||
|
|
||||||
import { useEarpieceAudioConfig } from "../MediaDevicesContext";
|
import { useEarpieceAudioConfig } from "../MediaDevicesContext";
|
||||||
import { useReactiveState } from "../useReactiveState";
|
import { useReactiveState } from "../useReactiveState";
|
||||||
@@ -59,7 +59,7 @@ export function LivekitRoomAudioRenderer({
|
|||||||
validIdentities,
|
validIdentities,
|
||||||
muted,
|
muted,
|
||||||
}: MatrixAudioRendererProps): ReactNode {
|
}: MatrixAudioRendererProps): ReactNode {
|
||||||
const prefixedLogger = logger.getChild("[MatrixAudioRenderer]");
|
const logger = rootLogger.getChild("[MatrixAudioRenderer]");
|
||||||
const tracks = useTracks(
|
const tracks = useTracks(
|
||||||
[
|
[
|
||||||
Track.Source.Microphone,
|
Track.Source.Microphone,
|
||||||
@@ -80,7 +80,7 @@ export function LivekitRoomAudioRenderer({
|
|||||||
if (!isValid) {
|
if (!isValid) {
|
||||||
// TODO make sure to also skip the warn logging for the local identity
|
// TODO make sure to also skip the warn logging for the local identity
|
||||||
// Log that there is an invalid identity, that means that someone is publishing audio that is not expected to be in the call.
|
// Log that there is an invalid identity, that means that someone is publishing audio that is not expected to be in the call.
|
||||||
prefixedLogger.warn(
|
logger.warn(
|
||||||
`Audio track ${ref.participant.identity} from ${url} has no matching matrix call member`,
|
`Audio track ${ref.participant.identity} from ${url} has no matching matrix call member`,
|
||||||
`current members: ${validIdentities.join()}`,
|
`current members: ${validIdentities.join()}`,
|
||||||
`track will not get rendered`,
|
`track will not get rendered`,
|
||||||
|
|||||||
Reference in New Issue
Block a user