summaryrefslogtreecommitdiffstats
path: root/ppapi/generators/idl_lint.py
diff options
context:
space:
mode:
Diffstat (limited to 'ppapi/generators/idl_lint.py')
-rw-r--r--ppapi/generators/idl_lint.py120
1 files changed, 120 insertions, 0 deletions
diff --git a/ppapi/generators/idl_lint.py b/ppapi/generators/idl_lint.py
new file mode 100644
index 0000000..c6ef89e
--- /dev/null
+++ b/ppapi/generators/idl_lint.py
@@ -0,0 +1,120 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2011 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('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('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'):
+ if not node.GetLabel():
+ node.Warning('Expecting label.')
+ warnings += 1
+ macro = node.GetProperty('macro')
+ if macro:
+ 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'):
+ 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):
+ if GetOption('wcomment'): ast.SetProperty('wcomment', True)
+ if GetOption('wenum'): ast.SetProperty('wenum', True)
+ if GetOption('winline'): ast.SetProperty('winilne', True)
+ if GetOption('wparam'): ast.SetProperty('wparam', True)
+ if GetOption('wpass'): ast.SetProperty('wpass', 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