check macro calls for mismatches in argument number. Fix a few glitches found in mainline using this test.
This commit is contained in:
parent
779ea775e5
commit
2f30f121cc
6 changed files with 69 additions and 19 deletions
|
@ -146,7 +146,7 @@
|
|||
y=9
|
||||
[/recall]
|
||||
|
||||
{PLACE_IMAGE units/transport/galleon.png) 10 9}
|
||||
{PLACE_IMAGE units/transport/galleon.png 10 9}
|
||||
|
||||
[objectives]
|
||||
side=1
|
||||
|
|
|
@ -139,7 +139,7 @@
|
|||
y=24
|
||||
[/recall]
|
||||
|
||||
{PLACE_IMAGE units/transport/galleon.png) 10 27}
|
||||
{PLACE_IMAGE units/transport/galleon.png 10 27}
|
||||
|
||||
[objectives]
|
||||
side=1
|
||||
|
|
|
@ -150,7 +150,7 @@
|
|||
y=31,31,32,32,33,34,35,36,36,37,38,38
|
||||
[/move_unit_fake]
|
||||
|
||||
{PLACE_IMAGE units/transport/galleon.png) 2 38}
|
||||
{PLACE_IMAGE units/transport/galleon.png 2 38}
|
||||
{PLACE_IMAGE (units/transport/pirate-galleon.png) 3 26}
|
||||
{PLACE_IMAGE (units/transport/pirate-galleon.png) 4 24}
|
||||
{PLACE_IMAGE (units/transport/pirate-galleon.png) 2 23}
|
||||
|
|
|
@ -629,11 +629,6 @@
|
|||
{TERRAIN_ADJACENT_CORNER {OUTER} {INNER} {INNER} 56,68 {IMAGE}-concave}
|
||||
#enddef
|
||||
|
||||
#define TERRAIN_ADJACENT_CORNER_BOTH_PROB INNER OUTER IMAGE PROB
|
||||
{TERRAIN_ADJACENT_CORNER {INNER} {OUTER} {OUTER} 52,76 {IMAGE}-convex {PROB}}
|
||||
{TERRAIN_ADJACENT_CORNER {OUTER} {INNER} {INNER} 56,68 {IMAGE}-concave {PROB}}
|
||||
#enddef
|
||||
|
||||
# Loyalist castle
|
||||
{TERRAIN_ADJACENT_CORNER Ch (!,Ch*,Kh*) (!,Ch*,Kh*) 52,76 castle/castle-convex}
|
||||
{TERRAIN_ADJACENT_CORNER (!,Ch*,Kh*) Ch Ch* 56,68 castle/castle-concave}
|
||||
|
|
|
@ -62,19 +62,20 @@ def isresource(filename):
|
|||
|
||||
class Reference:
|
||||
"Describes a location by file and line."
|
||||
def __init__(self, filename, lineno=None, docstring=None):
|
||||
def __init__(self, filename, lineno=None, docstring=None, arity=None):
|
||||
self.filename = filename
|
||||
self.lineno = lineno
|
||||
self.references = {}
|
||||
self.docstring = docstring
|
||||
self.arity = arity
|
||||
self.references = {}
|
||||
self.undef = None
|
||||
def append(self, fn, n):
|
||||
def append(self, fn, n, a=None):
|
||||
if fn not in self.references:
|
||||
self.references[fn] = []
|
||||
self.references[fn].append(n)
|
||||
self.references[fn].append((n, a))
|
||||
def dump_references(self):
|
||||
for (file, linenumbers) in self.references.items():
|
||||
print " %s: %s" % (file, `linenumbers`[1:-1])
|
||||
for (file, refs) in self.references.items():
|
||||
print " %s: %s" % (file, `map(lambda x: x[0], refs)`[1:-1])
|
||||
def __cmp__(self, other):
|
||||
"Compare two documentation objects for place in the sort order."
|
||||
# Major sort by file, minor by line number. This presumes that the
|
||||
|
@ -85,6 +86,14 @@ class Reference:
|
|||
return byfile
|
||||
else:
|
||||
return cmp(self.lineno, other.lineno)
|
||||
def mismatches(self):
|
||||
copy = Reference(self.filename, self.lineno, self.docstring, self.arity)
|
||||
copy.undef = self.undef
|
||||
for filename in self.references:
|
||||
mis = filter(lambda (ln, a): a != -1 and a != self.arity, self.references[filename])
|
||||
if mis:
|
||||
copy.references[filename] = mis
|
||||
return copy
|
||||
def __str__(self):
|
||||
if self.lineno:
|
||||
return '"%s", line %d' % (self.filename, self.lineno)
|
||||
|
@ -156,7 +165,7 @@ class CrossRef:
|
|||
elif line.strip().startswith("#define"):
|
||||
tokens = line.split()
|
||||
name = tokens[1]
|
||||
here = Reference(filename, n+1, line)
|
||||
here = Reference(filename, n+1, line, arity=len(tokens)-2)
|
||||
here.hash = md5.new()
|
||||
here.docstring = line.lstrip()[8:] # Strip off #define_
|
||||
state = "macro_header"
|
||||
|
@ -231,14 +240,45 @@ class CrossRef:
|
|||
if name in formals:
|
||||
continue
|
||||
elif name in self.xref:
|
||||
# Count the number of actual arguments.
|
||||
# Set arity to -n if the call doesn't
|
||||
# close on this line
|
||||
brackdepth = parendepth = arity = 0
|
||||
instring = False
|
||||
for i in range(match.start(0), len(line)):
|
||||
if line[i] == "{":
|
||||
brackdepth += 1
|
||||
elif line[i] == "}":
|
||||
brackdepth -= 1
|
||||
if brackdepth == 0:
|
||||
if line[i-1].isspace():
|
||||
arity -= 1
|
||||
break
|
||||
elif line[i] == "(":
|
||||
parendepth += 1
|
||||
elif line[i] == ")":
|
||||
parendepth -= 1
|
||||
elif line[i] == '"':
|
||||
instring = not instring
|
||||
elif line[i].isspace() and \
|
||||
not line[i-1].isspace() and \
|
||||
brackdepth == 1 and \
|
||||
parendepth == 0 and \
|
||||
not instring:
|
||||
arity += 1
|
||||
if brackdepth > 0 or parendepth > 0:
|
||||
arity = -1
|
||||
#print '"%s", line %d: arity of %s is %d' \
|
||||
# % (fn, n+1, name, arity)
|
||||
# Figure out which macros might resolve this
|
||||
for defn in self.xref[name]:
|
||||
if self.visible_from(defn, fn, n+1):
|
||||
candidates += 1
|
||||
defn.append(fn, n+1)
|
||||
defn.append(fn, n+1, arity)
|
||||
if candidates > 1:
|
||||
print "%s: more than one definition of %s is visible here." % (Reference(fn, n), name)
|
||||
if candidates == 0:
|
||||
self.unresolved.append((name, Reference(fn,n+1)))
|
||||
self.unresolved.append((name,Reference(fn,n+1,arity=arity)))
|
||||
# Find references to resource files
|
||||
for match in re.finditer(CrossRef.file_reference, line):
|
||||
name = match.group(0)
|
||||
|
|
|
@ -103,7 +103,7 @@ class CrossRefLister(CrossRef):
|
|||
if nrefs == 0:
|
||||
print "%s: %s macro %s is unused" % (defn, type, name)
|
||||
else:
|
||||
print "%s: %s macro %s is used in %d files:" % (defn, type, name, nrefs)
|
||||
print "%s: %s macro %s (%d args) is used in %d files:" % (defn, type, name, defn.arity, nrefs)
|
||||
defn.dump_references()
|
||||
sorted = self.fileref.keys()
|
||||
sorted.sort()
|
||||
|
@ -118,7 +118,8 @@ class CrossRefLister(CrossRef):
|
|||
print "Resource %s is used in %d files:" % (defloc, nrefs)
|
||||
defloc.dump_references()
|
||||
def unresdump(self):
|
||||
"Report unresolved references."
|
||||
"Report unresolved references and arity mismatches."
|
||||
# First the unresolved references
|
||||
if len(self.unresolved) == 0 and len(self.missing) == 0:
|
||||
print "# No unresolved references"
|
||||
else:
|
||||
|
@ -126,6 +127,20 @@ class CrossRefLister(CrossRef):
|
|||
print "# Unresolved references:"
|
||||
for (name, reference) in self.unresolved + self.missing:
|
||||
print "%s -> %s" % (reference, name)
|
||||
mismatched = []
|
||||
sorted = self.xref.keys()
|
||||
sorted.sort()
|
||||
for name in sorted:
|
||||
for defn in self.xref[name]:
|
||||
m = defn.mismatches()
|
||||
if m.references:
|
||||
mismatched.append((name, m))
|
||||
# Then the arity mismatches
|
||||
if mismatched:
|
||||
print "# Mismatched references:"
|
||||
for (n, m) in mismatched:
|
||||
print "%s: macro %s (%d args) has arity mismatches:" % (m, n, m.arity)
|
||||
m.dump_references()
|
||||
def deflist(self, pred=None):
|
||||
"List all resource definitions."
|
||||
sorted = self.xref.keys()
|
||||
|
|
Loading…
Add table
Reference in a new issue