Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests shouldn't make code to be considered as used #23284

Open
t3chguy opened this issue Sep 15, 2022 · 5 comments
Open

Tests shouldn't make code to be considered as used #23284

t3chguy opened this issue Sep 15, 2022 · 5 comments
Labels
A-Developer-Experience A-Testing Testing, code coverage, etc. Hacktoberfest Issues which are suitable for Hacktoberfest PRs: https://hacktoberfest.digitalocean.com/ Help Wanted Extra attention is needed O-Frequent Affects or can be seen by most users regularly or impacts most users' first experience S-Minor Impairs non-critical functionality or suitable workarounds exist T-Task Tasks for the team like planning

Comments

@t3chguy
Copy link
Member

t3chguy commented Sep 15, 2022

No description provided.

@SimonBrandner
Copy link
Contributor

It would be nice to have further context here

@SimonBrandner SimonBrandner added the X-Needs-Info This issue is blocked awaiting information from the reporter label Sep 15, 2022
@t3chguy
Copy link
Member Author

t3chguy commented Sep 15, 2022

A component was added with a test, it was not used anywhere, it was not identified as dead code because it was imported by a test. If we stop using a bit of code and it happens to have a unit test then it will never get identified as dead code

@SimonBrandner SimonBrandner changed the title Dead code checker should ignore tests Tests shouldn't make code to be considered as used Sep 15, 2022
@SimonBrandner SimonBrandner added S-Minor Impairs non-critical functionality or suitable workarounds exist A-Developer-Experience O-Frequent Affects or can be seen by most users regularly or impacts most users' first experience T-Task Tasks for the team like planning and removed X-Needs-Info This issue is blocked awaiting information from the reporter labels Sep 15, 2022
@clarkf
Copy link

clarkf commented Jan 16, 2023

I played around with this a bit today, and there's definitely some stuff that can be safely removed (e.g. useAccountData, <TooltipButton />. I found about 600 unused lines).

From what I can gather, ts-prune isn't quite flexible enough to deal with the mutli-project structure. I had to drop down and use ts-morph directly:

import { Project, Node, ReferenceFindableNode, SourceFile } from "ts-morph";
import * as path from "node:path";

const root = path.resolve(path.join(__dirname, ".."));

const project = new Project({
    tsConfigFilePath: path.join(root, "tsconfig.json"),
});

const SAFE: Record<string, string[]> = {
    // list symbols that are externally depended upon, e.g.
    "src/rageshake/rageshake": ["init", "flush", "cleanup", "tryInitStorage"],
};

for (const file of project.getSourceFiles()) {
    file.forEachChild((child) => {
        if (Node.isVariableStatement(child)) {
            if (isExported(child)) child.getDeclarations().forEach(checkNode);
        } else if (isExported(child)) checkNode(child);
    });
}

function isExported(node: Node) {
    return Node.isExportable(node) && node.isExported();
}

function checkNode(node: Node) {
    if (Node.isInterfaceDeclaration(node) || Node.isTypeAliasDeclaration(node)) return;
    if (!Node.isReferenceFindable(node)) return;

    const file = node.getSourceFile();
    const filePath = path.relative(root, file.getFilePath());
    const symbName = Node.hasName(node) ? node.getName() : node.getText();

    if (isSafe(node)) {
        return;
    }

    if (isDeadCode(node, file))
        console.log(`[${filePath}:${node.getStartLineNumber()}]: ${symbName} - ${node.getKindName()}`);
}

function isDeadCode(node: ReferenceFindableNode, _file: SourceFile): boolean {
    return node.findReferencesAsNodes().length === 0;
}

function isSafe(node: Node): boolean {
    const file = node.getSourceFile();
    const filePath = path.relative(root, file.getFilePath());
    const symbName = Node.hasName(node) ? node.getName() : node.getText();

    // ts-morph likes to omit extensions, so check against both
    return [filePath, filePath.replace(/\.tsx?$/, "")].some((p) => !!SAFE[p]?.includes(symbName));
}

(Based on the same gist that ts-prune came from).

I've skipped type-level information altogether, since it's elided from the final build, but there's fiddling to be done there too. I could try to add a feature to ts-prune, but it almost seems unnecessary, since element-web is dropping into JS to do this already.

In order for something like this to be realistic, noImplcitAny would need to be true (ref #21968 - ambiguous data in, ambiguous data out ;-)). tsconfig.json would also need to be sorted out. I can't remember off the top of my head what best practices are, but I think it involves having separate tsconfigs for src and test/spec.

@t3chguy
Copy link
Member Author

t3chguy commented Jan 18, 2023

@clarkf thanks for digging into that, I'm working on noImplicitAny right now!

@Johennes Johennes added the A-Testing Testing, code coverage, etc. label Oct 16, 2023
@Johennes Johennes added the Help Wanted Extra attention is needed label Oct 24, 2023
@Johennes
Copy link
Contributor

The work on enabling noImplicitAny has concluded by now.

@Johennes Johennes added the Hacktoberfest Issues which are suitable for Hacktoberfest PRs: https://hacktoberfest.digitalocean.com/ label Oct 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Developer-Experience A-Testing Testing, code coverage, etc. Hacktoberfest Issues which are suitable for Hacktoberfest PRs: https://hacktoberfest.digitalocean.com/ Help Wanted Extra attention is needed O-Frequent Affects or can be seen by most users regularly or impacts most users' first experience S-Minor Impairs non-critical functionality or suitable workarounds exist T-Task Tasks for the team like planning
Projects
None yet
Development

No branches or pull requests

4 participants