Skip to content

Commit 7bca541

Browse files
robintowntoger5
andauthored
Perform dead code analysis with Knip (#2575)
* Install Knip * Clarify an import that was confusing Knip * Fix issues detected by Knip Including cleaning up some unused code and dependencies, using a React hook that we unintentionally stopped using, and also adding some previously undeclared dependencies. * Run dead code analysis in lint script and CI --------- Co-authored-by: Timo <[email protected]>
1 parent 51ae4c0 commit 7bca541

20 files changed

+271
-774
lines changed

.github/workflows/lint.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,5 @@ jobs:
2323
run: "yarn run lint:eslint"
2424
- name: Type check
2525
run: "yarn run lint:types"
26+
- name: Dead code analysis
27+
run: "yarn run lint:knip"

.github/workflows/test.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ jobs:
2121
run: "yarn run test:coverage"
2222
- name: Upload to codecov
2323
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4
24+
env:
25+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
2426
with:
2527
flags: unittests
26-
token: ${{ secrets.CODECOV_TOKEN }}
2728
fail_ci_if_error: true

knip.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { KnipConfig } from "knip";
2+
3+
export default {
4+
entry: ["src/main.tsx", "i18next-parser.config.ts"],
5+
ignoreBinaries: [
6+
// This is deprecated, so Knip doesn't actually recognize it as a globally
7+
// installed binary. TODO We should switch to Compose v2:
8+
// https://docs.docker.com/compose/migrate/
9+
"docker-compose",
10+
],
11+
ignoreDependencies: [
12+
// Used in CSS
13+
"normalize.css",
14+
// Used for its global type declarations
15+
"@types/grecaptcha",
16+
// Because we use matrix-js-sdk as a Git dependency rather than consuming
17+
// the proper release artifacts, and also import directly from src/, we're
18+
// forced to re-install some of the types that it depends on even though
19+
// these look unused to Knip
20+
"@types/content-type",
21+
"@types/sdp-transform",
22+
"@types/uuid",
23+
// We obviously use this, but if the package has been linked with yarn link,
24+
// then Knip will flag it as a false positive
25+
// https://github.com/webpro-nl/knip/issues/766
26+
"@vector-im/compound-web",
27+
"matrix-widget-api",
28+
],
29+
ignoreExportsUsedInFile: true,
30+
} satisfies KnipConfig;

package.json

Lines changed: 55 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,39 @@
88
"serve": "vite preview",
99
"prettier:check": "prettier -c .",
1010
"prettier:format": "prettier -w .",
11-
"lint": "yarn lint:types && yarn lint:eslint",
11+
"lint": "yarn lint:types && yarn lint:eslint && yarn lint:knip",
1212
"lint:eslint": "eslint --max-warnings 0 src",
1313
"lint:eslint-fix": "eslint --max-warnings 0 src --fix",
14+
"lint:knip": "knip",
1415
"lint:types": "tsc",
15-
"i18n": "node_modules/i18next-parser/bin/cli.js",
16-
"i18n:check": "node_modules/i18next-parser/bin/cli.js --fail-on-warnings --fail-on-update",
16+
"i18n": "i18next",
17+
"i18n:check": "i18next --fail-on-warnings --fail-on-update",
1718
"test": "vitest",
1819
"test:coverage": "vitest --coverage",
1920
"backend": "docker-compose -f backend-docker-compose.yml up"
2021
},
21-
"dependencies": {
22+
"devDependencies": {
23+
"@babel/core": "^7.16.5",
24+
"@babel/preset-env": "^7.22.20",
25+
"@babel/preset-react": "^7.22.15",
26+
"@babel/preset-typescript": "^7.23.0",
2227
"@juggle/resize-observer": "^3.3.1",
2328
"@livekit/components-core": "^0.11.0",
2429
"@livekit/components-react": "^2.0.0",
2530
"@opentelemetry/api": "^1.4.0",
26-
"@opentelemetry/context-zone": "^1.9.1",
27-
"@opentelemetry/exporter-jaeger": "^1.9.1",
31+
"@opentelemetry/core": "^1.25.1",
2832
"@opentelemetry/exporter-trace-otlp-http": "^0.52.0",
29-
"@opentelemetry/instrumentation-document-load": "^0.39.0",
30-
"@opentelemetry/instrumentation-user-interaction": "^0.39.0",
33+
"@opentelemetry/resources": "^1.25.1",
34+
"@opentelemetry/sdk-trace-base": "^1.25.1",
3135
"@opentelemetry/sdk-trace-web": "^1.9.1",
36+
"@opentelemetry/semantic-conventions": "^1.25.1",
3237
"@radix-ui/react-dialog": "^1.0.4",
3338
"@radix-ui/react-slider": "^1.1.2",
3439
"@radix-ui/react-visually-hidden": "^1.0.3",
3540
"@react-aria/button": "^3.3.4",
3641
"@react-aria/focus": "^3.5.0",
42+
"@react-aria/interactions": "^3.9.1",
43+
"@react-aria/listbox": "^3.5.1",
3744
"@react-aria/menu": "^3.3.0",
3845
"@react-aria/overlays": "^3.7.3",
3946
"@react-aria/select": "^3.6.0",
@@ -42,71 +49,40 @@
4249
"@react-aria/utils": "^3.10.0",
4350
"@react-spring/web": "^9.4.4",
4451
"@react-stately/collections": "^3.3.4",
52+
"@react-stately/list": "^3.5.1",
53+
"@react-stately/menu": "^3.3.1",
4554
"@react-stately/select": "^3.1.3",
55+
"@react-stately/tabs": "^3.1.1",
4656
"@react-stately/tooltip": "^3.0.5",
4757
"@react-stately/tree": "^3.2.0",
48-
"@sentry/react": "^8.0.0",
49-
"@sentry/tracing": "^7.0.0",
50-
"@types/lodash": "^4.14.199",
51-
"@use-gesture/react": "^10.2.11",
52-
"@vector-im/compound-design-tokens": "^1.0.0",
53-
"@vector-im/compound-web": "^6.0.0",
54-
"@vitejs/plugin-basic-ssl": "^1.0.1",
55-
"@vitejs/plugin-react": "^4.0.1",
56-
"buffer": "^6.0.3",
57-
"classnames": "^2.3.1",
58-
"events": "^3.3.0",
59-
"i18next": "^23.0.0",
60-
"i18next-browser-languagedetector": "^8.0.0",
61-
"i18next-http-backend": "^2.0.0",
62-
"livekit-client": "^2.0.2",
63-
"lodash": "^4.17.21",
64-
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#467908703bc67fa3e23d978f5549e2709d4acf74",
65-
"matrix-widget-api": "^1.8.2",
66-
"normalize.css": "^8.0.1",
67-
"observable-hooks": "^4.2.3",
68-
"pako": "^2.0.4",
69-
"postcss-preset-env": "^10.0.0",
70-
"posthog-js": "^1.29.0",
71-
"react": "18",
72-
"react-dom": "18",
73-
"react-i18next": "^15.0.0",
74-
"react-router-dom": "^5.2.0",
75-
"react-use-clipboard": "^1.0.7",
76-
"react-use-measure": "^2.1.1",
77-
"rxjs": "^7.8.1",
78-
"sdp-transform": "^2.14.1",
79-
"tinyqueue": "^3.0.0",
80-
"unique-names-generator": "^4.6.0",
81-
"uuid": "10",
82-
"vaul": "^0.9.0"
83-
},
84-
"devDependencies": {
85-
"@babel/core": "^7.16.5",
86-
"@babel/preset-env": "^7.22.20",
87-
"@babel/preset-react": "^7.22.15",
88-
"@babel/preset-typescript": "^7.23.0",
89-
"@react-spring/rafz": "^9.7.3",
9058
"@react-types/dialog": "^3.5.5",
59+
"@react-types/menu": "^3.6.1",
60+
"@react-types/overlays": "^3.6.1",
61+
"@react-types/shared": "^3.13.1",
62+
"@react-types/tabs": "^3.1.1",
63+
"@sentry/react": "^8.0.0",
9164
"@sentry/vite-plugin": "^2.0.0",
9265
"@testing-library/dom": "^10.1.0",
9366
"@testing-library/react": "^16.0.0",
9467
"@testing-library/user-event": "^14.5.1",
9568
"@types/content-type": "^1.1.5",
96-
"@types/dom-screen-wake-lock": "^1.0.1",
97-
"@types/dompurify": "^3.0.2",
9869
"@types/grecaptcha": "^3.0.9",
70+
"@types/lodash": "^4.14.199",
9971
"@types/node": "^20.0.0",
10072
"@types/react-dom": "^18.3.0",
10173
"@types/react-router-dom": "^5.3.3",
102-
"@types/request": "^2.48.8",
10374
"@types/sdp-transform": "^2.4.5",
10475
"@types/uuid": "10",
10576
"@typescript-eslint/eslint-plugin": "^7.0.0",
10677
"@typescript-eslint/parser": "^7.0.0",
78+
"@use-gesture/react": "^10.2.11",
79+
"@vector-im/compound-design-tokens": "^1.0.0",
80+
"@vector-im/compound-web": "^6.0.0",
81+
"@vitejs/plugin-basic-ssl": "^1.0.1",
82+
"@vitejs/plugin-react": "^4.0.1",
10783
"@vitest/coverage-v8": "^2.0.5",
108-
"babel-loader": "^9.0.0",
10984
"babel-plugin-transform-vite-meta-env": "^1.0.3",
85+
"classnames": "^2.3.1",
11086
"eslint": "^8.14.0",
11187
"eslint-config-google": "^0.14.0",
11288
"eslint-config-prettier": "^9.0.0",
@@ -118,12 +94,37 @@
11894
"eslint-plugin-react-hooks": "^4.5.0",
11995
"eslint-plugin-unicorn": "^55.0.0",
12096
"global-jsdom": "^24.0.0",
97+
"history": "^4.0.0",
98+
"i18next": "^23.0.0",
99+
"i18next-browser-languagedetector": "^8.0.0",
100+
"i18next-http-backend": "^2.0.0",
121101
"i18next-parser": "^9.0.0",
122102
"jsdom": "^25.0.0",
103+
"knip": "^5.27.2",
104+
"livekit-client": "^2.0.2",
105+
"lodash": "^4.17.21",
106+
"loglevel": "^1.9.1",
107+
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#467908703bc67fa3e23d978f5549e2709d4acf74",
108+
"matrix-widget-api": "^1.8.2",
109+
"normalize.css": "^8.0.1",
110+
"observable-hooks": "^4.2.3",
111+
"pako": "^2.0.4",
112+
"postcss": "^8.4.41",
113+
"postcss-preset-env": "^10.0.0",
114+
"posthog-js": "^1.29.0",
123115
"prettier": "^3.0.0",
116+
"react": "18",
117+
"react-dom": "18",
118+
"react-i18next": "^15.0.0",
119+
"react-router-dom": "^5.2.0",
120+
"react-use-clipboard": "^1.0.7",
121+
"react-use-measure": "^2.1.1",
122+
"rxjs": "^7.8.1",
124123
"sass": "^1.42.1",
125124
"typescript": "^5.1.6",
126125
"typescript-eslint-language-service": "^5.0.5",
126+
"unique-names-generator": "^4.6.0",
127+
"vaul": "^0.9.0",
127128
"vite": "^5.0.0",
128129
"vite-plugin-html-template": "^1.1.0",
129130
"vite-plugin-svgr": "^4.0.0",

renovate.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,25 @@
4848
"ignoreDeps": [
4949
"@react-aria/button",
5050
"@react-aria/focus",
51+
"@react-aria/interactions",
52+
"@react-aria/listbox",
5153
"@react-aria/menu",
5254
"@react-aria/overlays",
5355
"@react-aria/select",
5456
"@react-aria/tabs",
5557
"@react-aria/tooltip",
5658
"@react-aria/utils",
5759
"@react-stately/collections",
60+
"@react-stately/list",
61+
"@react-stately/menu",
5862
"@react-stately/select",
63+
"@react-stately/tabs",
5964
"@react-stately/tooltip",
6065
"@react-stately/tree",
61-
"@react-types/dialog"
66+
"@react-types/dialog",
67+
"@react-types/menu",
68+
"@react-types/overlays",
69+
"@react-types/shared",
70+
"@react-types/tabs"
6271
]
6372
}

src/Banner.tsx

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/home/RegisteredView.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,7 @@ import { Caption } from "../typography/Typography";
4040
import { Form } from "../form/Form";
4141
import { AnalyticsNotice } from "../analytics/AnalyticsNotice";
4242
import { E2eeType } from "../e2ee/e2eeType";
43-
import {
44-
useSetting,
45-
optInAnalytics as optInAnalyticsSetting,
46-
} from "../settings/settings";
43+
import { useOptInAnalytics } from "../settings/settings";
4744

4845
interface Props {
4946
client: MatrixClient;
@@ -52,7 +49,7 @@ interface Props {
5249
export const RegisteredView: FC<Props> = ({ client }) => {
5350
const [loading, setLoading] = useState(false);
5451
const [error, setError] = useState<Error>();
55-
const [optInAnalytics] = useSetting(optInAnalyticsSetting);
52+
const [optInAnalytics] = useOptInAnalytics();
5653
const history = useHistory();
5754
const { t } = useTranslation();
5855
const [joinExistingCallModalOpen, setJoinExistingCallModalOpen] =

src/home/UnauthenticatedView.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,13 @@ import { generateRandomName } from "../auth/generateRandomName";
4343
import { AnalyticsNotice } from "../analytics/AnalyticsNotice";
4444
import { Config } from "../config/Config";
4545
import { E2eeType } from "../e2ee/e2eeType";
46-
import {
47-
useSetting,
48-
optInAnalytics as optInAnalyticsSetting,
49-
} from "../settings/settings";
46+
import { useOptInAnalytics } from "../settings/settings";
5047

5148
export const UnauthenticatedView: FC = () => {
5249
const { setClient } = useClient();
5350
const [loading, setLoading] = useState(false);
5451
const [error, setError] = useState<Error>();
55-
const [optInAnalytics] = useSetting(optInAnalyticsSetting);
52+
const [optInAnalytics] = useOptInAnalytics();
5653
const { recaptchaKey, register } = useInteractiveRegistration();
5754
const { execute, reset, recaptchaId } = useRecaptcha(recaptchaKey);
5855

src/livekit/LivekitFocus.ts

Whitespace-only changes.

src/room/RoomPage.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,7 @@ import { LobbyView } from "./LobbyView";
3535
import { E2eeType } from "../e2ee/e2eeType";
3636
import { useProfile } from "../profile/useProfile";
3737
import { useMuteStates } from "./MuteStates";
38-
import {
39-
useSetting,
40-
optInAnalytics as optInAnalyticsSetting,
41-
} from "../settings/settings";
38+
import { useOptInAnalytics } from "../settings/settings";
4239

4340
export const RoomPage: FC = () => {
4441
const {
@@ -83,7 +80,7 @@ export const RoomPage: FC = () => {
8380
registerPasswordlessUser,
8481
]);
8582

86-
const [optInAnalytics, setOptInAnalytics] = useSetting(optInAnalyticsSetting);
83+
const [optInAnalytics, setOptInAnalytics] = useOptInAnalytics();
8784
useEffect(() => {
8885
// During the beta, opt into analytics by default
8986
if (optInAnalytics === null && setOptInAnalytics) setOptInAnalytics(true);

0 commit comments

Comments
 (0)