<commit_before>#!/usr/bin/python

# 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/.

# The idea of this script is to find interfaces that are not
# implemented in JS, but not marked builtinclass.

import re
import os
import argparse


okayInterfacePatt = re.compile("^nsI|xpcI|mozI|nsPI|imgI|rrI|amI|txI|IPeer")

weirdInterfacesToIgnore = [
    "IJSDebugger",
    "inIDeepTreeWalker",
    "IUrlClassifierUITelemetry",
]
weirdInterfacesToIgnorePatt = re.compile("^" + "|".join(weirdInterfacesToIgnore) + "$")

def assertInterfaceOkay(fname, interface):
    if okayInterfacePatt.match(interface):
        return
    if weirdInterfacesToIgnorePatt.match(interface):
        return
    raise Exception("Bad interface " + interface + " in file " + fname)


# Look for calls to ChromeUtils.generateQI and add any interfaces found to the
# set |jsImplementedInterfaces|.
def generateQIFinder(args, fname, jsImplementedInterfaces):
    f = open(fname, "r")
    qiArgString = None

    for l in f:
        l = l.strip()

        # Skip lines that are comments or are probably part of comments.
        if l.startswith("//") or l.startswith("*"):
            continue

        if not qiArgString:
            if not "ChromeUtils.generateQI" in l:
                continue
            qiArgString = ""
            l = l.split("ChromeUtils.generateQI")[1]

        l = l.split(")")
        qiArgString += l[0].strip()
        if len(l) == 1:
            continue

        rawInterfaces = qiArgString.strip("([],").split(",")
        for r in rawInterfaces:
            interface = r.strip('" ')
            if interface == "":
                continue

            # Ignore some weird cases in test files.
            if interface.endswith("interfaces"):
                if (fname.endswith("js/xpconnect/tests/unit/test_generateQI.js") or
                    fname.endswith("netwerk/test/browser/browser_nsIFormPOSTActionChannel.js") or
                    fname.endswith("testing/modules/AppInfo.jsm") or
                    fname.endswith("browser/components/places/content/browserPlacesViews.js")):
                    continue
            if interface == "observerInterface":
                if fname.endswith("browser/components/newtab/lib/PlacesFeed.jsm"):
                    continue
            if interface == "ifaces":
                if (fname.endswith("toolkit/content/customElements.js") or
                    fname.endswith("toolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js")):
                    continue
            if interface == "iface":
                if fname.endswith("toolkit/components/places/tests/PlacesTestUtils.jsm"):
                    continue

            if interface.startswith("Ci."):
                interface = interface[3:]
            elif interface.startswith('Ci["'):
                interface = interface[4:]
            elif interface.startswith("parentCi."):
                interface = interface[9:]
            assertInterfaceOkay(fname, interface)
            jsImplementedInterfaces.add(interface)

        qiArgString = None

    f.close()


# Look at XPIDL files for interfaces that are not marked builtinclass.
def idlFileAnalyzer(args, fname, jsImplementedInterfaces, nonBuiltinInterfaces):
    f = open(fname, "r")
    prevLine = None

    for l in f:
        l = l.strip()
        if l.startswith("//"):
            continue
        if not l.startswith("interface "):
            prevLine = l
            continue
        if l.endswith(";"):
            # Just a forward declaration. Ignore it.
            prevLine = None
            continue
        interface = l.split()[1].strip(":")
        assertInterfaceOkay(fname, interface)

        attributes = prevLine.strip().strip("[]").split(", ")
        builtinClass = False
        anyUUID = False
        for a in attributes:
            if a == 'builtinclass':
                builtinClass = True
                continue
            if a.startswith('uuid'):<commit_msg>make the forward declaration matching better<commit_after>#!/usr/bin/python

# 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/.

# The idea of this script is to find interfaces that are not
# implemented in JS, but not marked builtinclass.

import re
import os
import argparse


okayInterfacePatt = re.compile("^nsI|xpcI|mozI|nsPI|imgI|rrI|amI|txI|IPeer")

weirdInterfacesToIgnore = [
    "IJSDebugger",
    "inIDeepTreeWalker",
    "IUrlClassifierUITelemetry",
]
weirdInterfacesToIgnorePatt = re.compile("^" + "|".join(weirdInterfacesToIgnore) + "$")

def assertInterfaceOkay(fname, interface):
    if okayInterfacePatt.match(interface):
        return
    if weirdInterfacesToIgnorePatt.match(interface):
        return
    raise Exception("Bad interface " + interface + " in file " + fname)


# Look for calls to ChromeUtils.generateQI and add any interfaces found to the
# set |jsImplementedInterfaces|.
def generateQIFinder(args, fname, jsImplementedInterfaces):
    f = open(fname, "r")
    qiArgString = None

    for l in f:
        l = l.strip()

        # Skip lines that are comments or are probably part of comments.
        if l.startswith("//") or l.startswith("*"):
            continue

        if not qiArgString:
            if not "ChromeUtils.generateQI" in l:
                continue
            qiArgString = ""
            l = l.split("ChromeUtils.generateQI")[1]

        l = l.split(")")
        qiArgString += l[0].strip()
        if len(l) == 1:
            continue

        rawInterfaces = qiArgString.strip("([],").split(",")
        for r in rawInterfaces:
            interface = r.strip('" ')
            if interface == "":
                continue

            # Ignore some weird cases in test files.
            if interface.endswith("interfaces"):
                if (fname.endswith("js/xpconnect/tests/unit/test_generateQI.js") or
                    fname.endswith("netwerk/test/browser/browser_nsIFormPOSTActionChannel.js") or
                    fname.endswith("testing/modules/AppInfo.jsm") or
                    fname.endswith("browser/components/places/content/browserPlacesViews.js")):
                    continue
            if interface == "observerInterface":
                if fname.endswith("browser/components/newtab/lib/PlacesFeed.jsm"):
                    continue
            if interface == "ifaces":
                if (fname.endswith("toolkit/content/customElements.js") or
                    fname.endswith("toolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js")):
                    continue
            if interface == "iface":
                if fname.endswith("toolkit/components/places/tests/PlacesTestUtils.jsm"):
                    continue

            if interface.startswith("Ci."):
                interface = interface[3:]
            elif interface.startswith('Ci["'):
                interface = interface[4:]
            elif interface.startswith("parentCi."):
                interface = interface[9:]
            assertInterfaceOkay(fname, interface)
            jsImplementedInterfaces.add(interface)

        qiArgString = None

    f.close()


forwardDeclPatt = re.compile("^interface [A-Za-z0-9_-]+;$")

# Look at XPIDL files for interfaces that are not marked builtinclass.
def idlFileAnalyzer(args, fname, jsImplementedInterfaces, nonBuiltinInterfaces):
    f = open(fname, "r")
    prevLine = None

    for l in f:
        l = l.strip()
        if l.startswith("//"):
            continue
        if not l.startswith("interface "):
            prevLine = l
            continue
        # Just a forward declaration. Ignore it.
        if forwardDeclPatt.match(l):
            prevLine = None
            continue
        interface = l.split()[1].strip(":")
        assertInterfaceOkay(fname, interface)

        attributes = prevLine.strip().strip("[]").split(", ")
        builtinClass = False
        anyUUID = False
        for a in attributes:
            if a == 'builtinclass':
                builtinClass = True
                continue
            if a.startswith('uuid'):
{'fraction_non_alphanumeric': 0.10772917914919113, 'fraction_numerical': 0.002875973636908328, 'mean_word_length': 2.114179104477612, 'pattern_counts': {'":': 10, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '699718', 'n_tokens_mistral': 2461, 'n_tokens_neox': 2332, 'n_words': 579}