summaryrefslogtreecommitdiffstats
path: root/remoting/tools
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-12 19:28:18 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-11-12 19:28:18 +0000
commitdc91bc562d3b4c59f061e3fb884207ebae8c523f (patch)
tree9181553d646c77653450e06c8534754cfce98b40 /remoting/tools
parent3ed6125cee1aa92163c1ab8c036f4e99067d2271 (diff)
downloadchromium_src-dc91bc562d3b4c59f061e3fb884207ebae8c523f.zip
chromium_src-dc91bc562d3b4c59f061e3fb884207ebae8c523f.tar.gz
chromium_src-dc91bc562d3b4c59f061e3fb884207ebae8c523f.tar.bz2
replace verify-webapp.py script with verify_resources.py
verify-webapp.py was lookin only in webapp sources. The new verify_resources.py verifies all source files and not only webapp. Review URL: https://codereview.chromium.org/11362072 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@167224 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/tools')
-rwxr-xr-xremoting/tools/verify_resources.py155
1 files changed, 155 insertions, 0 deletions
diff --git a/remoting/tools/verify_resources.py b/remoting/tools/verify_resources.py
new file mode 100755
index 0000000..045f95d
--- /dev/null
+++ b/remoting/tools/verify_resources.py
@@ -0,0 +1,155 @@
+#!/usr/bin/env 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.
+
+"""Verifies that GRD resource files define all the strings used by a given
+set of source files. For file formats where it is not possible to infer which
+strings represent message identifiers, localized strings should be explicitly
+annotated with the string "i18n-content", for example:
+
+ LocalizeString(/*i18n-content*/"PRODUCT_NAME");
+
+This script also recognises localized strings in HTML and manifest.json files:
+
+ HTML: <span i18n-content="PRODUCT_NAME"></span>
+ or ...i18n-value-name-1="BUTTON_NAME"...
+ manifest.json: __MSG_PRODUCT_NAME__
+
+Note that these forms must be exact; extra spaces are not permitted, though
+either single or double quotes are recognized.
+
+In addition, the script checks that all the messages are still in use; if
+this is not the case then a warning is issued, but the script still succeeds.
+"""
+
+import json
+import os
+import optparse
+import re
+import sys
+import xml.dom.minidom as minidom
+
+WARNING_MESSAGE = """
+To remove this warning, either remove the unused tags from
+resource files, add the files that use the tags listed above to
+remoting.gyp, or annotate existing uses of those tags with the
+prefix /*i18n-content*/
+"""
+
+def LoadTagsFromGrd(filename):
+ xml = minidom.parse(filename)
+ tags = []
+ msgs_and_structs = xml.getElementsByTagName("message")
+ msgs_and_structs.extend(xml.getElementsByTagName("structure"))
+ for res in msgs_and_structs:
+ name = res.getAttribute("name")
+ if not name or not name.startswith("IDR_"):
+ raise Exception("Tag name doesn't start with IDR_: %s" % name)
+ tags.append(name[4:])
+ return tags
+
+def ExtractTagFromLine(file_type, line):
+ """Extract a tag from a line of HTML, C++, JS or JSON."""
+ if file_type == "html":
+ # HTML-style (tags)
+ m = re.search('i18n-content=[\'"]([^\'"]*)[\'"]', line)
+ if m: return m.group(1)
+ # HTML-style (substitutions)
+ m = re.search('i18n-value-name-[1-9]=[\'"]([^\'"]*)[\'"]', line)
+ if m: return m.group(1)
+ elif file_type == 'js':
+ # Javascript style
+ m = re.search('/\*i18n-content\*/[\'"]([^\`"]*)[\'"]', line)
+ if m: return m.group(1)
+ elif file_type == 'cc':
+ # C++ style
+ m = re.search('IDR_([A-Z0-9_]*)', line)
+ if m: return m.group(1)
+ m = re.search('/\*i18n-content\*/["]([^\`"]*)["]', line)
+ if m: return m.group(1)
+ elif file_type == 'json':
+ # Manifest style
+ m = re.search('__MSG_(.*)__', line)
+ if m: return m.group(1)
+ return None
+
+
+def VerifyFile(filename, messages, used_tags):
+ """
+ Parse |filename|, looking for tags and report any that are not included in
+ |messages|. Return True if all tags are present and correct, or False if
+ any are missing. If no tags are found, print a warning message and return
+ True.
+ """
+
+ base_name, extension = os.path.splitext(filename)
+ extension = extension[1:]
+ if extension not in ['js', 'cc', 'html', 'json']:
+ raise Exception("Unknown file type: %s" % extension)
+
+ result = True
+ matches = False
+ f = open(filename, 'r')
+ lines = f.readlines()
+ for i in xrange(0, len(lines)):
+ tag = ExtractTagFromLine(extension, lines[i])
+ if tag:
+ tag = tag.upper()
+ used_tags.add(tag)
+ matches = True
+ if not tag in messages:
+ result = False
+ print '%s/%s:%d: error: Undefined tag: %s' % \
+ (os.getcwd(), filename, i + 1, tag)
+ if not matches:
+ print '%s/%s:0: warning: No tags found' % (os.getcwd(), filename)
+ f.close()
+ return result
+
+
+def main():
+ parser = optparse.OptionParser(
+ usage='Usage: %prog [options...] [source_file...]')
+ parser.add_option('-t', '--touch', dest='touch',
+ help='File to touch when finished.')
+ parser.add_option('-r', '--grd', dest='grd', action='append',
+ help='grd file')
+
+ options, args = parser.parse_args()
+ if not options.touch:
+ print '-t is not specified.'
+ return 1
+ if len(options.grd) == 0 or len(args) == 0:
+ print 'At least one GRD file needs to be specified.'
+ return 1
+
+ resources = []
+ for f in options.grd:
+ resources.extend(LoadTagsFromGrd(f))
+
+ used_tags = set([])
+ exit_code = 0
+ for f in args:
+ if not VerifyFile(f, resources, used_tags):
+ exit_code = 1
+
+ warnings = False
+ for tag in resources:
+ if tag not in used_tags:
+ print ('%s/%s:0: warning: %s is defined but not used') % \
+ (os.getcwd(), sys.argv[2], tag)
+ warnings = True
+ if warnings:
+ print WARNING_MESSAGE
+
+ if exit_code == 0:
+ f = open(options.touch, 'a')
+ f.close()
+ os.utime(options.touch, None)
+
+ return exit_code
+
+
+if __name__ == '__main__':
+ sys.exit(main())