File: __init__.py

package info (click to toggle)
firefox 149.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,767,760 kB
  • sloc: cpp: 7,416,064; javascript: 6,752,859; ansic: 3,774,850; python: 1,250,473; xml: 641,578; asm: 439,191; java: 186,617; sh: 56,634; makefile: 18,856; objc: 13,092; perl: 12,763; pascal: 5,960; yacc: 4,583; cs: 3,846; lex: 1,720; ruby: 1,002; php: 436; lisp: 258; awk: 105; sql: 66; sed: 53; csh: 10; exp: 6
file content (116 lines) | stat: -rw-r--r-- 3,927 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import difflib
import os
import re

from mozlint import result
from mozlint.pathutils import expand_exclusions

comment_remover = re.compile(r"((?://[^\r\n]*)|(?:/\*.*?\*/)|\s)", re.DOTALL)
header_guard = re.compile(
    r"^\s*#\s*(?:(?:ifndef\s(\w+))|(?:if\s+\!\s*defined\(\s*(\w+)\s*\))|(?:pragma\s+once)).*"
)


def check_missing_header_guards(results, topsrcdir, path, raw_content, config, fix):
    offset = 0
    comment_prelude = re.match(comment_remover, raw_content)
    while comment_prelude:
        offset += len(comment_prelude.group(1))
        comment_prelude = re.match(comment_remover, raw_content[offset:])
    stripped_content = raw_content[offset:]
    lineno = raw_content.count("\n", 0, offset)
    if m := re.match(header_guard, stripped_content):
        groups = m.groups()
        if any(groups):
            existing_guard = groups[0] or groups[1]
            if "__" in existing_guard:
                results["results"].append(
                    result.from_config(
                        config,
                        path=path,
                        message=f"invalid header guard {existing_guard}, using '__' in a macro name is reserved",
                        level="error",
                        line=lineno,
                    )
                )
            if re.match("^_[A-Z]", existing_guard):
                results["results"].append(
                    result.from_config(
                        config,
                        path=path,
                        message=f"invalid header guard {existing_guard}, leading underscore followed by a capital letter in a macro name is reserved",
                        level="error",
                        line=lineno,
                    )
                )
        return
    guard = make_guard(topsrcdir, path)
    if fix:
        fix_guard(guard, path, raw_content, lineno)
        results["fixed"] += 1
    else:
        diff = generate_diff(guard, path, raw_content, lineno)
        results["results"].append(
            result.from_config(
                config,
                path=path,
                message="missing header guard",
                level="error",
                diff=diff,
            )
        )


def make_guard(topsrcdir, path):
    guard = f"{os.path.splitext(path[1 + len(topsrcdir) :])[0]}_H_"
    guard = re.sub(r"[/.-]", "_", guard)
    guard = re.sub("_+", "_", guard)
    guard = guard.upper()
    return guard


def insert_guard(guard, sequence, lineno):
    new_sequence = sequence + [f"#endif  // {guard}"]
    new_sequence.insert(lineno, f"#ifndef {guard}")
    new_sequence.insert(lineno + 1, f"#define {guard}")
    new_sequence.insert(lineno + 2, "")
    return new_sequence


def fix_guard(guard, path, raw_content, lineno):
    prev_content = raw_content.split("\n")
    new_content = insert_guard(guard, prev_content, lineno)
    with open(path, "w") as fd:
        fd.write("\n".join(new_content))


def generate_diff(guard, path, raw_content, lineno):
    prev_content = raw_content.split("\n")
    new_content = insert_guard(guard, prev_content, lineno)
    diff = "\n".join(
        difflib.unified_diff(prev_content, new_content, fromfile=path, tofile=path)
    )
    return diff


def lint(paths, config, **lintargs):
    results = {"results": [], "fixed": 0}
    paths = list(expand_exclusions(paths, config, lintargs["root"]))
    fix = lintargs.get("fix")

    for path in paths:
        try:
            with open(path) as fd:
                raw_content = fd.read()
        except UnicodeDecodeError:
            continue

        check_missing_header_guards(
            results, lintargs["root"], path, raw_content, config, fix
        )

    return results