Bug 770182 Warn when preprocessing unnecessarily r=bsmedberg
authorNeil Rashbrook <neil@parkwaycc.co.uk>
Tue, 10 Jul 2012 22:01:08 +0100
changeset 101575 13ea641e1b5a608aa64a583ade753b24d048c22f
parent 101574 3980bc27a10e0ef2b8974f989a18c388b1aba346
child 101576 25ffee656138a6c80172c57101523cfe9d5e4f79
push idunknown
push userunknown
push dateunknown
reviewersbsmedberg
bugs770182
milestone16.0a1
Bug 770182 Warn when preprocessing unnecessarily r=bsmedberg
config/JarMaker.py
config/Preprocessor.py
js/src/config/Preprocessor.py
--- a/config/JarMaker.py
+++ b/config/JarMaker.py
@@ -365,16 +365,17 @@ class JarMaker(object):
       if m.group('optPreprocess'):
         outf = outHelper.getOutput(out)
         inf = open(realsrc)
         pp = self.pp.clone()
         if src[-4:] == '.css':
           pp.setMarker('%')
         pp.out = outf
         pp.do_include(inf)
+        pp.warnUnused(realsrc)
         outf.close()
         inf.close()
         return
       # copy or symlink if newer or overwrite
       if (m.group('optOverwrite')
           or (getModTime(realsrc) >
               outHelper.getDestModTime(m.group('output')))):
         if self.outputFormat == 'symlink':
--- a/config/Preprocessor.py
+++ b/config/Preprocessor.py
@@ -36,16 +36,17 @@ class Preprocessor:
       self.key = MSG
       RuntimeError.__init__(self, (self.file, self.line, self.key, context))
   def __init__(self):
     self.context = Expression.Context()
     for k,v in {'FILE': '',
                 'LINE': 0,
                 'DIRECTORY': os.path.abspath('.')}.iteritems():
       self.context[k] = v
+    self.actionLevel = 0
     self.disableLevel = 0
     # ifStates can be
     #  0: hadTrue
     #  1: wantsTrue
     #  2: #else found
     self.ifStates = []
     self.checkLineNumbers = False
     self.writtenLines = 0
@@ -69,16 +70,23 @@ class Preprocessor:
                        'includesubst': 0,
                        'error': 0}.iteritems():
       self.cmds[cmd] = (level, getattr(self, 'do_' + cmd))
     self.out = sys.stdout
     self.setMarker('#')
     self.LE = '\n'
     self.varsubst = re.compile('@(?P<VAR>\w+)@', re.U)
   
+  def warnUnused(self, file):
+    if self.actionLevel == 0:
+      sys.stderr.write('%s: WARNING: no preprocessor directives found\n' % file)
+    elif self.actionLevel == 1:
+      sys.stderr.write('%s: WARNING: no useful preprocessor directives found\n' % file)
+    pass
+
   def setLineEndings(self, aLE):
     """
     Set the line endings to be used for output.
     """
     self.LE = {'cr': '\x0D', 'lf': '\x0A', 'crlf': '\x0D\x0A'}[aLE]
   
   def setMarker(self, aMarker):
     """
@@ -130,18 +138,20 @@ class Preprocessor:
     Uses OptionParser internally, no args mean sys.argv[1:].
     """
     p = self.getCommandLineParser()
     (options, args) = p.parse_args(args=args)
     includes = options.I
     if defaultToStdin and len(args) == 0:
       args = [sys.stdin]
     includes.extend(args)
-    for f in includes:
-      self.do_include(f, False)
+    if includes:
+      for f in includes:
+        self.do_include(f, False)
+      self.warnUnused(f)
     pass
 
   def getCommandLineParser(self, unescapeDefines = False):
     escapedValue = re.compile('".*"$')
     numberValue = re.compile('\d+$')
     def handleE(option, opt, value, parser):
       for k,v in os.environ.iteritems():
         self.context[k] = v
@@ -181,29 +191,33 @@ class Preprocessor:
                  type="string",
                  help='Use the specified marker instead of #')
     return p
 
   def handleLine(self, aLine):
     """
     Handle a single line of input (internal).
     """
+    if self.actionLevel == 0 and self.comment.match(aLine):
+      self.actionLevel = 1
     m = self.instruction.match(aLine)
     if m:
       args = None
       cmd = m.group('cmd')
       try:
         args = m.group('args')
       except IndexError:
         pass
       if cmd not in self.cmds:
         raise Preprocessor.Error(self, 'INVALID_CMD', aLine)
       level, cmd = self.cmds[cmd]
       if (level >= self.disableLevel):
         cmd(args)
+      if cmd != 'literal':
+        self.actionLevel = 2
     elif self.disableLevel == 0 and not self.comment.match(aLine):
       self.write(aLine)
     pass
 
   # Instruction handlers
   # These are named do_'instruction name' and take one argument
   
   # Variables
--- a/js/src/config/Preprocessor.py
+++ b/js/src/config/Preprocessor.py
@@ -36,16 +36,17 @@ class Preprocessor:
       self.key = MSG
       RuntimeError.__init__(self, (self.file, self.line, self.key, context))
   def __init__(self):
     self.context = Expression.Context()
     for k,v in {'FILE': '',
                 'LINE': 0,
                 'DIRECTORY': os.path.abspath('.')}.iteritems():
       self.context[k] = v
+    self.actionLevel = 0
     self.disableLevel = 0
     # ifStates can be
     #  0: hadTrue
     #  1: wantsTrue
     #  2: #else found
     self.ifStates = []
     self.checkLineNumbers = False
     self.writtenLines = 0
@@ -69,16 +70,23 @@ class Preprocessor:
                        'includesubst': 0,
                        'error': 0}.iteritems():
       self.cmds[cmd] = (level, getattr(self, 'do_' + cmd))
     self.out = sys.stdout
     self.setMarker('#')
     self.LE = '\n'
     self.varsubst = re.compile('@(?P<VAR>\w+)@', re.U)
   
+  def warnUnused(self, file):
+    if self.actionLevel == 0:
+      sys.stderr.write('%s: WARNING: no preprocessor directives found\n' % file)
+    elif self.actionLevel == 1:
+      sys.stderr.write('%s: WARNING: no useful preprocessor directives found\n' % file)
+    pass
+
   def setLineEndings(self, aLE):
     """
     Set the line endings to be used for output.
     """
     self.LE = {'cr': '\x0D', 'lf': '\x0A', 'crlf': '\x0D\x0A'}[aLE]
   
   def setMarker(self, aMarker):
     """
@@ -130,18 +138,20 @@ class Preprocessor:
     Uses OptionParser internally, no args mean sys.argv[1:].
     """
     p = self.getCommandLineParser()
     (options, args) = p.parse_args(args=args)
     includes = options.I
     if defaultToStdin and len(args) == 0:
       args = [sys.stdin]
     includes.extend(args)
-    for f in includes:
-      self.do_include(f, False)
+    if includes:
+      for f in includes:
+        self.do_include(f, False)
+      self.warnUnused(f)
     pass
 
   def getCommandLineParser(self, unescapeDefines = False):
     escapedValue = re.compile('".*"$')
     numberValue = re.compile('\d+$')
     def handleE(option, opt, value, parser):
       for k,v in os.environ.iteritems():
         self.context[k] = v
@@ -181,29 +191,33 @@ class Preprocessor:
                  type="string",
                  help='Use the specified marker instead of #')
     return p
 
   def handleLine(self, aLine):
     """
     Handle a single line of input (internal).
     """
+    if self.actionLevel == 0 and self.comment.match(aLine):
+      self.actionLevel = 1
     m = self.instruction.match(aLine)
     if m:
       args = None
       cmd = m.group('cmd')
       try:
         args = m.group('args')
       except IndexError:
         pass
       if cmd not in self.cmds:
         raise Preprocessor.Error(self, 'INVALID_CMD', aLine)
       level, cmd = self.cmds[cmd]
       if (level >= self.disableLevel):
         cmd(args)
+      if cmd != 'literal':
+        self.actionLevel = 2
     elif self.disableLevel == 0 and not self.comment.match(aLine):
       self.write(aLine)
     pass
 
   # Instruction handlers
   # These are named do_'instruction name' and take one argument
   
   # Variables