DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Line Code
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 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
import WebIDL

def WebIDLTest(parser, harness):
    parser.parse("""
        interface TestNullableEquivalency1 {
          attribute long  a;
          attribute long? b;
        };

        interface TestNullableEquivalency2 {
          attribute ArrayBuffer  a;
          attribute ArrayBuffer? b;
        };

        /* Not implemented */
        /*dictionary TestNullableEquivalency3Dict {
          long foo = 42;
        };

        interface TestNullableEquivalency3 {
          attribute Test3Dict  a;
          attribute Test3Dict? b;
        };*/

        enum TestNullableEquivalency4Enum {
          "Foo",
          "Bar"
        };

        interface TestNullableEquivalency4 {
          attribute TestNullableEquivalency4Enum  a;
          attribute TestNullableEquivalency4Enum? b;
        };

        interface TestNullableEquivalency5 {
          attribute TestNullableEquivalency4  a;
          attribute TestNullableEquivalency4? b;
        };

        interface TestNullableEquivalency6 {
          attribute boolean  a;
          attribute boolean? b;
        };

        interface TestNullableEquivalency7 {
          attribute DOMString  a;
          attribute DOMString? b;
        };

        /* Not implemented. */
        /*interface TestNullableEquivalency8 {
          attribute float  a;
          attribute float? b;
        };*/

        interface TestNullableEquivalency8 {
          attribute double  a;
          attribute double? b;
        };

        interface TestNullableEquivalency9 {
          attribute object  a;
          attribute object? b;
        };

        interface TestNullableEquivalency10 {
          attribute double[]  a;
          attribute double[]? b;
        };

        interface TestNullableEquivalency11 {
          attribute TestNullableEquivalency9[]  a;
          attribute TestNullableEquivalency9[]? b;
        };
    """)

    for decl in parser.finish():
        if decl.isInterface():
            checkEquivalent(decl, harness)

def checkEquivalent(iface, harness):
    type1 = iface.members[0].type
    type2 = iface.members[1].type

    harness.check(type1.nullable(), False, 'attr1 should not be nullable')
    harness.check(type2.nullable(), True, 'attr2 should be nullable')

    # We don't know about type1, but type2, the nullable type, definitely
    # shouldn't be builtin.
    harness.check(type2.builtin, False, 'attr2 should not be builtin')

    # Ensure that all attributes of type2 match those in type1, except for:
    #  - names on an ignore list,
    #  - names beginning with '_',
    #  - functions which throw when called with no args, and
    #  - class-level non-callables ("static variables").
    #
    # Yes, this is an ugly, fragile hack.  But it finds bugs...
    for attr in dir(type1):
        if attr.startswith('_') or \
           attr in ['nullable', 'builtin', 'filename', 'location',
                    'inner', 'QName'] or \
           (hasattr(type(type1), attr) and not callable(getattr(type1, attr))):
            continue

        a1 = getattr(type1, attr)

        if callable(a1):
            try:
                v1 = a1()
            except:
                # Can't call a1 with no args, so skip this attriute.
                continue

            try:
                a2 = getattr(type2, attr)
            except:
                harness.ok(False, 'Missing %s attribute on type %s in %s' % (attr, type2, iface))
                continue

            if not callable(a2):
                harness.ok(False, "%s attribute on type %s in %s wasn't callable" % (attr, type2, iface))
                continue

            v2 = a2()
            harness.check(v2, v1, '%s method return value' % attr)
        else:
            try:
                a2 = getattr(type2, attr)
            except:
                harness.ok(False, 'Missing %s attribute on type %s in %s' % (attr, type2, iface))
                continue

            harness.check(a2, a1, '%s attribute should match' % attr)