Refactor the Scanner class(es) into a Prototype pattern.
authorstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Mon, 3 Dec 2001 02:53:01 +0000 (02:53 +0000)
committerstevenknight <stevenknight@fdb21ef1-2011-0410-befe-b5e4ea1792b1>
Mon, 3 Dec 2001 02:53:01 +0000 (02:53 +0000)
git-svn-id: http://scons.tigris.org/svn/scons/trunk@129 fdb21ef1-2011-0410-befe-b5e4ea1792b1

src/engine/SCons/Builder.py
src/engine/SCons/BuilderTests.py
src/engine/SCons/Scanner/C.py
src/engine/SCons/Scanner/Prog.py
src/engine/SCons/Scanner/ScannerTests.py
src/engine/SCons/Scanner/__init__.py

index e36f332d6c7e578fac96b19c52d9a92f9db1a200..2d2d6234387bbeb7f58bc9c47d601ebe536c0e6b 100644 (file)
@@ -184,7 +184,7 @@ class BuilderBase:
            t.env_set(env)
            t.add_source(slist)
             if self.scanner:
-                t.scanner_set(self.scanner)
+                t.scanner_set(self.scanner.instance(env))
 
        for s in slist:
            s.env_set(env, 1)
index cc5b314b7b80c42d34ecb79228b304a96d5b3778..54776ffdbe0653938bec95a76039113a74fca481 100644 (file)
@@ -61,6 +61,7 @@ act_py = test.workpath('act.py')
 outfile = test.workpath('outfile')
 
 show_string = None
+instanced = None
 
 class Environment:
             def subst(self, s):
@@ -349,13 +350,19 @@ class BuilderTestCase(unittest.TestCase):
 
     def test_build_scanner(self):
         """Testing ability to set a target scanner through a builder."""
+        global instanced
         class TestScanner:
-            pass
+            def instance(self, env):
+                global instanced
+                instanced = 1
+                return self
         scn = TestScanner()
         builder=SCons.Builder.Builder(scanner=scn)
         tgt = builder(env, target='foo', source='bar')
         assert tgt.scanner == scn, tgt.scanner
+        assert instanced
 
+        instanced = None
         builder1 = SCons.Builder.Builder(action='foo',
                                          src_suffix='.bar',
                                          suffix='.foo')
@@ -364,6 +371,7 @@ class BuilderTestCase(unittest.TestCase):
                                          scanner = scn)
         tgt = builder2(env, target='baz', source='test.bar test2.foo test3.txt')
         assert tgt.scanner == scn, tgt.scanner
+        assert instanced
 
 if __name__ == "__main__":
     suite = unittest.makeSuite(BuilderTestCase, 'test_')
index 90cb141f98d35fa37665875fe71f0f79a703a8f1..739612523f01796ffbf90bdee340447ee8a0dd6f 100644 (file)
@@ -39,12 +39,11 @@ angle_re = re.compile('^[ \t]*#[ \t]*include[ \t]+<([\\w./\\\\]+)>', re.M)
 quote_re = re.compile('^[ \t]*#[ \t]*include[ \t]+"([\\w./\\\\]+)"', re.M)
 
 def CScan():
-    "Return a Scanner instance for scanning C/C++ source files"
-    s = SCons.Scanner.Recursive(scan, SCons.Node.FS.default_fs.File,
-                                [".c", ".C", ".cxx", ".cpp", ".c++",
-                                 ".h", ".H", ".hxx", ".hpp"])
-    s.name = "CScan"
-    return s
+    "Return a prototype Scanner instance for scanning C/C++ source files"
+    return SCons.Scanner.Recursive(scan, "CScan",
+                                   SCons.Node.FS.default_fs.File,
+                                   [".c", ".C", ".cxx", ".cpp", ".c++",
+                                    ".h", ".H", ".hxx", ".hpp"])
 
 def scan(filename, env, node_factory):
     """
index 62dee973a7c1a7dbc214ca2e0f2589e94ba3bbe8..0f8acff302d5554b208f565540d2ef60bc770d69 100644 (file)
@@ -28,11 +28,9 @@ import SCons.Node.FS
 import SCons.Util
 
 def ProgScan():
-    """Return a Scanner instance for scanning executable files
-    for static-lib dependencies"""
-    s = SCons.Scanner.Base(scan, SCons.Node.FS.default_fs.File)
-    s.name = "ProgScan"
-    return s
+    """Return a prototype Scanner instance for scanning executable
+    files for static-lib dependencies"""
+    return SCons.Scanner.Base(scan, "ProgScan", SCons.Node.FS.default_fs.File)
 
 def scan(filename, env, node_factory):
     """
index 5d434a631b21f12d01844fdf7e7562a3f322854e..f1a92cdecad7a57648d276b9f3acfaa0502bc36a 100644 (file)
@@ -57,39 +57,60 @@ class DummyEnvironment:
 
 
 class ScannerPositionalTestCase(ScannerTestBase, unittest.TestCase):
-    "Test the Scanner class using the position argument"
+    "Test the Scanner.Base class using the position argument"
     def runTest(self):
-        s = SCons.Scanner.Base(self.func)
+        s = SCons.Scanner.Base(self.func, "Pos")
         env = DummyEnvironment()
         env.VARIABLE = "var1"
         self.test(s, env, 'f1.cpp', ['f1.h', 'f1.hpp'])
 
+       env = DummyEnvironment()
+       env.VARIABLE = "i1"
+       i = s.instance(env)
+       self.test(i, env, 'i1.cpp', ['i1.h', 'i1.hpp'])
+
 class ScannerKeywordTestCase(ScannerTestBase, unittest.TestCase):
-    "Test the Scanner class using the keyword argument"
+    "Test the Scanner.Base class using the keyword argument"
     def runTest(self):
-        s = SCons.Scanner.Base(function = self.func)
+        s = SCons.Scanner.Base(function = self.func, name = "Key")
         env = DummyEnvironment()
         env.VARIABLE = "var2"
         self.test(s, env, 'f2.cpp', ['f2.h', 'f2.hpp'])
 
+       env = DummyEnvironment()
+       env.VARIABLE = "i2"
+       i = s.instance(env)
+       self.test(i, env, 'i2.cpp', ['i2.h', 'i2.hpp'])
+
 class ScannerPositionalArgumentTestCase(ScannerTestBase, unittest.TestCase):
-    "Test the Scanner class using the position argument and optional argument"
+    "Test the Scanner.Base class using both position and optional arguments"
     def runTest(self):
         arg = "this is the argument"
-        s = SCons.Scanner.Base(self.func, arg)
+        s = SCons.Scanner.Base(self.func, "PosArg", arg)
         env = DummyEnvironment()
         env.VARIABLE = "var3"
         self.test(s, env, 'f3.cpp', ['f3.h', 'f3.hpp'], arg)
 
+       env = DummyEnvironment()
+       env.VARIABLE = "i3"
+       i = s.instance(env)
+       self.test(i, env, 'i3.cpp', ['i3.h', 'i3.hpp'], arg)
+
 class ScannerKeywordArgumentTestCase(ScannerTestBase, unittest.TestCase):
-    "Test the Scanner class using the keyword argument and optional argument"
+    "Test the Scanner.Base class using both keyword and optional arguments"
     def runTest(self):
         arg = "this is another argument"
-        s = SCons.Scanner.Base(function = self.func, argument = arg)
+        s = SCons.Scanner.Base(function = self.func, name = "KeyArg",
+                               argument = arg)
         env = DummyEnvironment()
         env.VARIABLE = "var4"
         self.test(s, env, 'f4.cpp', ['f4.h', 'f4.hpp'], arg)
 
+       env = DummyEnvironment()
+       env.VARIABLE = "i4"
+       i = s.instance(env)
+       self.test(i, env, 'i4.cpp', ['i4.h', 'i4.hpp'], arg)
+
 def suite():
     suite = unittest.TestSuite()
     suite.addTest(ScannerPositionalTestCase())
index 3c53396c576f402bbe5951b7501960fa9584abba..7ecd846f31eec8d939af46ba9bf9471ca43255be 100644 (file)
@@ -48,13 +48,15 @@ class Base:
     straightforward, single-pass scanning of a single file.
     """
 
-    def __init__(self, function, argument=_null, skeys=[]):
+    def __init__(self, function, name = "NONE", argument=_null, skeys=[]):
         """
         Construct a new scanner object given a scanner function.
 
         'function' - a scanner function taking two or three arguments and
         returning a list of strings.
 
+        'name' - a name for identifying this scanner object.
+
         'argument' - an optional argument that will be passed to the
         scanner function if it is given.
 
@@ -84,8 +86,8 @@ class Base:
         # would need to be changed is the documentation.
 
         self.function = function
+        self.name = name
         self.argument = argument
-        self.name = "NONE"
         self.skeys = skeys
 
     def scan(self, filename, env):
@@ -101,17 +103,18 @@ class Base:
         else:
             return self.function(filename, env)
 
-    def __cmp__(self, other):
-        return cmp(self.__dict__, other.__dict__)
+    def instance(self, env):
+        """
+        Return an instance of a Scanner object for use in scanning.
 
-    def __call__(self, sources=None):
-        slist = scons_str2nodes(source, self.node_factory)
-        for s in slist:
-            s.scanner_set(self)
+        In the base class, we just return the scanner itself.
+        Other Scanner classes may use this to clone copies and/or
+        return unique instances as needed.
+        """
+        return self
 
-        if len(slist) == 1:
-            slist = slist[0]
-        return slist
+    def __cmp__(self, other):
+        return cmp(self.__dict__, other.__dict__)
 
 class Recursive(Base):
     """