| OLD | NEW |
| (Empty) | |
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 """ Lint for IDL """ |
| 6 |
| 7 import os |
| 8 import sys |
| 9 |
| 10 from idl_log import ErrOut, InfoOut, WarnOut |
| 11 from idl_node import IDLAttribute, IDLNode |
| 12 from idl_ast import IDLAst |
| 13 from idl_option import GetOption, Option, ParseOptions |
| 14 from idl_outfile import IDLOutFile |
| 15 from idl_visitor import IDLVisitor |
| 16 |
| 17 |
| 18 Option('wcomment', 'Disable warning for missing comment.') |
| 19 Option('wenum', 'Disable warning for missing enum value.') |
| 20 Option('winline', 'Disable warning for inline blocks.') |
| 21 Option('wname', 'Disable warning for inconsistent interface name.') |
| 22 Option('wnone', 'Disable all warnings.') |
| 23 Option('wparam', 'Disable warning for missing [in|out|inout] on param.') |
| 24 Option('wpass', 'Disable warning for mixed passByValue and returnByValue.') |
| 25 |
| 26 # |
| 27 # IDLLinter |
| 28 # |
| 29 # Once the AST is build, we need to resolve the namespace and version |
| 30 # information. |
| 31 # |
| 32 class IDLLinter(IDLVisitor): |
| 33 def VisitFilter(self, node, data): |
| 34 __pychecker__ = 'unusednames=node,data' |
| 35 return not node.IsA('Comment', 'Copyright') |
| 36 |
| 37 def Arrive(self, node, errors): |
| 38 __pychecker__ = 'unusednames=node,errors' |
| 39 warnings = 0 |
| 40 if node.IsA('Interface', 'Member', 'Struct', 'Enum', 'EnumItem', 'Typedef'): |
| 41 comments = node.GetListOf('Comment') |
| 42 if not comments and not node.GetProperty('wcomment'): |
| 43 node.Warning('Expecting a comment.') |
| 44 warnings += 1 |
| 45 |
| 46 if node.IsA('File'): |
| 47 labels = node.GetListOf('Label') |
| 48 interfaces = node.GetListOf('Interface') |
| 49 if interfaces and not labels: |
| 50 node.Warning('Expecting a label in a file containing interfaces.') |
| 51 |
| 52 if node.IsA('Struct', 'Typedef') and not node.GetProperty('wpass'): |
| 53 if node.GetProperty('passByValue'): |
| 54 pbv = 'is' |
| 55 else: |
| 56 pbv = 'is not' |
| 57 if node.GetProperty('returnByValue'): |
| 58 ret = 'is' |
| 59 else: |
| 60 ret = 'is not' |
| 61 if pbv != ret: |
| 62 node.Warning('%s passByValue but %s returnByValue.' % (pbv, ret)) |
| 63 warnings += 1 |
| 64 |
| 65 if node.IsA('EnumItem'): |
| 66 if not node.GetProperty('VALUE') and not node.GetProperty('wenum'): |
| 67 node.Warning('Expecting value for enumeration.') |
| 68 warnings += 1 |
| 69 |
| 70 if node.IsA('Interface'): |
| 71 macro = node.GetProperty('macro') |
| 72 if macro and not node.GetProperty('wname'): |
| 73 node.Warning('Interface name inconsistent: %s' % macro) |
| 74 warnings += 1 |
| 75 |
| 76 if node.IsA('Inline') and not node.GetProperty('winline'): |
| 77 inline_type = node.GetProperty('NAME') |
| 78 node.parent.Warning('Requires an inline %s block.' % inline_type) |
| 79 warnings += 1 |
| 80 |
| 81 if node.IsA('Callspec') and not node.GetProperty('wparam'): |
| 82 out = False |
| 83 for arg in node.GetListOf('Param'): |
| 84 if arg.GetProperty('out'): |
| 85 out = True |
| 86 if arg.GetProperty('in') and out: |
| 87 arg.Warning('[in] parameter after [out] parameter') |
| 88 warnings += 1 |
| 89 |
| 90 if node.IsA('Param') and not node.GetProperty('wparam'): |
| 91 found = False; |
| 92 for form in ['in', 'inout', 'out']: |
| 93 if node.GetProperty(form): found = True |
| 94 if not found: |
| 95 node.Warning('Missing argument type: [in|out|inout]') |
| 96 warnings += 1 |
| 97 |
| 98 return warnings |
| 99 |
| 100 def Depart(self, node, warnings, childdata): |
| 101 __pychecker__ = 'unusednames=node' |
| 102 for child in childdata: |
| 103 warnings += child |
| 104 return warnings |
| 105 |
| 106 def Lint(ast): |
| 107 options = ['wcomment', 'wenum', 'winline', 'wparam', 'wpass', 'wname'] |
| 108 wnone = GetOption('wnone') |
| 109 for opt in options: |
| 110 if wnone or GetOption(opt): ast.SetProperty(opt, True) |
| 111 |
| 112 skipList = [] |
| 113 for filenode in ast.GetListOf('File'): |
| 114 name = filenode.GetProperty('NAME') |
| 115 if filenode.GetProperty('ERRORS') > 0: |
| 116 ErrOut.Log('%s : Skipped due to errors.' % name) |
| 117 skipList.append(filenode) |
| 118 continue |
| 119 warnings = IDLLinter().Visit(filenode, 0) |
| 120 if warnings: |
| 121 WarnOut.Log('%s warning(s) for %s\n' % (warnings, name)) |
| 122 return skipList |
| OLD | NEW |