forked from mirrors/gecko-dev
122 lines
4 KiB
Python
122 lines
4 KiB
Python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
""" Lint for IDL """
|
|
|
|
import os
|
|
import sys
|
|
|
|
from idl_log import ErrOut, InfoOut, WarnOut
|
|
from idl_node import IDLAttribute, IDLNode
|
|
from idl_ast import IDLAst
|
|
from idl_option import GetOption, Option, ParseOptions
|
|
from idl_outfile import IDLOutFile
|
|
from idl_visitor import IDLVisitor
|
|
|
|
|
|
Option('wcomment', 'Disable warning for missing comment.')
|
|
Option('wenum', 'Disable warning for missing enum value.')
|
|
Option('winline', 'Disable warning for inline blocks.')
|
|
Option('wname', 'Disable warning for inconsistent interface name.')
|
|
Option('wnone', 'Disable all warnings.')
|
|
Option('wparam', 'Disable warning for missing [in|out|inout] on param.')
|
|
Option('wpass', 'Disable warning for mixed passByValue and returnByValue.')
|
|
|
|
#
|
|
# IDLLinter
|
|
#
|
|
# Once the AST is build, we need to resolve the namespace and version
|
|
# information.
|
|
#
|
|
class IDLLinter(IDLVisitor):
|
|
def VisitFilter(self, node, data):
|
|
__pychecker__ = 'unusednames=node,data'
|
|
return not node.IsA('Comment', 'Copyright')
|
|
|
|
def Arrive(self, node, errors):
|
|
__pychecker__ = 'unusednames=node,errors'
|
|
warnings = 0
|
|
if node.IsA('Interface', 'Member', 'Struct', 'Enum', 'EnumItem', 'Typedef'):
|
|
comments = node.GetListOf('Comment')
|
|
if not comments and not node.GetProperty('wcomment'):
|
|
node.Warning('Expecting a comment.')
|
|
warnings += 1
|
|
|
|
if node.IsA('File'):
|
|
labels = node.GetListOf('Label')
|
|
interfaces = node.GetListOf('Interface')
|
|
if interfaces and not labels:
|
|
node.Warning('Expecting a label in a file containing interfaces.')
|
|
|
|
if node.IsA('Struct', 'Typedef') and not node.GetProperty('wpass'):
|
|
if node.GetProperty('passByValue'):
|
|
pbv = 'is'
|
|
else:
|
|
pbv = 'is not'
|
|
if node.GetProperty('returnByValue'):
|
|
ret = 'is'
|
|
else:
|
|
ret = 'is not'
|
|
if pbv != ret:
|
|
node.Warning('%s passByValue but %s returnByValue.' % (pbv, ret))
|
|
warnings += 1
|
|
|
|
if node.IsA('EnumItem'):
|
|
if not node.GetProperty('VALUE') and not node.GetProperty('wenum'):
|
|
node.Warning('Expecting value for enumeration.')
|
|
warnings += 1
|
|
|
|
if node.IsA('Interface'):
|
|
macro = node.GetProperty('macro')
|
|
if macro and not node.GetProperty('wname'):
|
|
node.Warning('Interface name inconsistent: %s' % macro)
|
|
warnings += 1
|
|
|
|
if node.IsA('Inline') and not node.GetProperty('winline'):
|
|
inline_type = node.GetProperty('NAME')
|
|
node.parent.Warning('Requires an inline %s block.' % inline_type)
|
|
warnings += 1
|
|
|
|
if node.IsA('Callspec') and not node.GetProperty('wparam'):
|
|
out = False
|
|
for arg in node.GetListOf('Param'):
|
|
if arg.GetProperty('out'):
|
|
out = True
|
|
if arg.GetProperty('in') and out:
|
|
arg.Warning('[in] parameter after [out] parameter')
|
|
warnings += 1
|
|
|
|
if node.IsA('Param') and not node.GetProperty('wparam'):
|
|
found = False;
|
|
for form in ['in', 'inout', 'out']:
|
|
if node.GetProperty(form): found = True
|
|
if not found:
|
|
node.Warning('Missing argument type: [in|out|inout]')
|
|
warnings += 1
|
|
|
|
return warnings
|
|
|
|
def Depart(self, node, warnings, childdata):
|
|
__pychecker__ = 'unusednames=node'
|
|
for child in childdata:
|
|
warnings += child
|
|
return warnings
|
|
|
|
def Lint(ast):
|
|
options = ['wcomment', 'wenum', 'winline', 'wparam', 'wpass', 'wname']
|
|
wnone = GetOption('wnone')
|
|
for opt in options:
|
|
if wnone or GetOption(opt): ast.SetProperty(opt, True)
|
|
|
|
skipList = []
|
|
for filenode in ast.GetListOf('File'):
|
|
name = filenode.GetProperty('NAME')
|
|
if filenode.GetProperty('ERRORS') > 0:
|
|
ErrOut.Log('%s : Skipped due to errors.' % name)
|
|
skipList.append(filenode)
|
|
continue
|
|
warnings = IDLLinter().Visit(filenode, 0)
|
|
if warnings:
|
|
WarnOut.Log('%s warning(s) for %s\n' % (warnings, name))
|
|
return skipList
|