blob: 286b5a94059d09b0cc484a226a43720c38dbd3f0 [file] [log] [blame]
Patrick Williamsc0f7c042017-02-23 20:41:17 -06001#!/usr/bin/env python3
Patrick Williamsc124f4f2015-09-15 14:41:29 -05002
3# This program is free software; you can redistribute it and/or modify
4# it under the terms of the GNU General Public License as published by
5# the Free Software Foundation; either version 2 of the License, or
6# (at your option) any later version.
7#
8# This program is distributed in the hope that it will be useful,
9# but WITHOUT ANY WARRANTY; without even the implied warranty of
10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11# GNU General Public License for more details.
12#
13# You should have received a copy of the GNU General Public License
14# along with this program; if not, write to the Free Software
15# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16#
17# Copyright (C) Darren Hart <dvhart@linux.intel.com>, 2010
18
19
20import sys
21import getopt
22import os
23import os.path
24import re
25
Brad Bishop316dfdd2018-06-25 12:45:53 -040026# Set up sys.path to let us import tinfoil
27scripts_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
28lib_path = scripts_path + '/lib'
29sys.path.insert(0, lib_path)
30import scriptpath
31scriptpath.add_bitbake_lib_path()
32import bb.tinfoil
33
Patrick Williamsc124f4f2015-09-15 14:41:29 -050034def usage():
Brad Bishop316dfdd2018-06-25 12:45:53 -040035 print('Usage: %s -d FILENAME [-d FILENAME]*' % os.path.basename(sys.argv[0]))
Patrick Williamsc0f7c042017-02-23 20:41:17 -060036 print(' -d FILENAME documentation file to search')
37 print(' -h, --help display this help and exit')
Patrick Williamsc0f7c042017-02-23 20:41:17 -060038 print(' -t FILENAME documentation config file (for doc tags)')
39 print(' -T Only display variables with doc tags (requires -t)')
Patrick Williamsc124f4f2015-09-15 14:41:29 -050040
Brad Bishop316dfdd2018-06-25 12:45:53 -040041def bbvar_is_documented(var, documented_vars):
42 ''' Check if variable (var) is in the list of documented variables(documented_vars) '''
43 if var in documented_vars:
44 return True
45 else:
46 return False
Patrick Williamsc124f4f2015-09-15 14:41:29 -050047
Brad Bishop316dfdd2018-06-25 12:45:53 -040048def collect_documented_vars(docfiles):
49 ''' Walk the docfiles and collect the documented variables '''
50 documented_vars = []
51 prog = re.compile(".*($|[^A-Z_])<glossentry id=\'var-")
52 var_prog = re.compile('<glossentry id=\'var-(.*)\'>')
53 for d in docfiles:
54 with open(d) as f:
55 documented_vars += var_prog.findall(f.read())
Patrick Williamsc124f4f2015-09-15 14:41:29 -050056
Brad Bishop316dfdd2018-06-25 12:45:53 -040057 return documented_vars
Patrick Williamsc124f4f2015-09-15 14:41:29 -050058
59def bbvar_doctag(var, docconf):
60 prog = re.compile('^%s\[doc\] *= *"(.*)"' % (var))
61 if docconf == "":
62 return "?"
63
64 try:
65 f = open(docconf)
Patrick Williamsc0f7c042017-02-23 20:41:17 -060066 except IOError as err:
67 return err.args[1]
Patrick Williamsc124f4f2015-09-15 14:41:29 -050068
69 for line in f:
70 m = prog.search(line)
71 if m:
72 return m.group(1)
73
74 f.close()
75 return ""
76
77def main():
78 docfiles = []
Brad Bishop316dfdd2018-06-25 12:45:53 -040079 bbvars = set()
Patrick Williamsc124f4f2015-09-15 14:41:29 -050080 undocumented = []
81 docconf = ""
82 onlydoctags = False
83
84 # Collect and validate input
85 try:
86 opts, args = getopt.getopt(sys.argv[1:], "d:hm:t:T", ["help"])
Patrick Williamsc0f7c042017-02-23 20:41:17 -060087 except getopt.GetoptError as err:
88 print('%s' % str(err))
Patrick Williamsc124f4f2015-09-15 14:41:29 -050089 usage()
90 sys.exit(2)
91
92 for o, a in opts:
93 if o in ('-h', '--help'):
94 usage()
95 sys.exit(0)
96 elif o == '-d':
97 if os.path.isfile(a):
98 docfiles.append(a)
99 else:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600100 print('ERROR: documentation file %s is not a regular file' % a)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500101 sys.exit(3)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500102 elif o == "-t":
103 if os.path.isfile(a):
104 docconf = a
105 elif o == "-T":
106 onlydoctags = True
107 else:
108 assert False, "unhandled option"
109
110 if len(docfiles) == 0:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600111 print('ERROR: no docfile specified')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500112 usage()
113 sys.exit(5)
114
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500115 if onlydoctags and docconf == "":
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600116 print('ERROR: no docconf specified')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500117 usage()
118 sys.exit(7)
119
Brad Bishop316dfdd2018-06-25 12:45:53 -0400120 prog = re.compile("^[^a-z]*$")
121 with bb.tinfoil.Tinfoil() as tinfoil:
122 tinfoil.prepare(config_only=False)
123 parser = bb.codeparser.PythonParser('parser', None)
124 datastore = tinfoil.config_data
125
126 def bbvars_update(data):
127 if prog.match(data):
128 bbvars.add(data)
129 if tinfoil.config_data.getVarFlag(data, 'python'):
130 try:
131 parser.parse_python(tinfoil.config_data.getVar(data))
132 except bb.data_smart.ExpansionError:
133 pass
134 for var in parser.references:
135 if prog.match(var):
136 bbvars.add(var)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500137 else:
Brad Bishop316dfdd2018-06-25 12:45:53 -0400138 try:
139 expandedVar = datastore.expandWithRefs(datastore.getVar(data, False), data)
140 for var in expandedVar.references:
141 if prog.match(var):
142 bbvars.add(var)
143 except bb.data_smart.ExpansionError:
144 pass
145
146 # Use tinfoil to collect all the variable names globally
147 for data in datastore:
148 bbvars_update(data)
149
150 # Collect variables from all recipes
151 for recipe in tinfoil.all_recipe_files(variants=False):
152 print("Checking %s" % recipe)
153 for data in tinfoil.parse_recipe_file(recipe):
154 bbvars_update(data)
155
156 documented_vars = collect_documented_vars(docfiles)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500157
158 # Check each var for documentation
159 varlen = 0
Brad Bishop316dfdd2018-06-25 12:45:53 -0400160 for v in bbvars:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500161 if len(v) > varlen:
162 varlen = len(v)
Brad Bishop316dfdd2018-06-25 12:45:53 -0400163 if not bbvar_is_documented(v, documented_vars):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500164 undocumented.append(v)
165 undocumented.sort()
166 varlen = varlen + 1
167
168 # Report all undocumented variables
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600169 print('Found %d undocumented bb variables (out of %d):' % (len(undocumented), len(bbvars)))
Brad Bishop316dfdd2018-06-25 12:45:53 -0400170 header = '%s%s' % (str("VARIABLE").ljust(varlen), str("DOCTAG").ljust(7))
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600171 print(header)
172 print(str("").ljust(len(header), '='))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500173 for v in undocumented:
174 doctag = bbvar_doctag(v, docconf)
175 if not onlydoctags or not doctag == "":
Brad Bishop316dfdd2018-06-25 12:45:53 -0400176 print('%s%s' % (v.ljust(varlen), doctag))
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500177
178
179if __name__ == "__main__":
180 main()