Home | History | Annotate | Download | only in generators
      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
    123