[feaLib] show all missing glyphs at once (#2665)

This commit is contained in:
Simon Cozens 2022-06-23 15:04:59 +01:00 committed by GitHub
parent b4d85f23cf
commit d224e1f73d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 20 additions and 10 deletions

View File

@ -73,6 +73,7 @@ class Parser(object):
self.next_token_location_ = None self.next_token_location_ = None
lexerClass = IncludingLexer if followIncludes else NonIncludingLexer lexerClass = IncludingLexer if followIncludes else NonIncludingLexer
self.lexer_ = lexerClass(featurefile, includeDir=includeDir) self.lexer_ = lexerClass(featurefile, includeDir=includeDir)
self.missing = {}
self.advance_lexer_(comments=True) self.advance_lexer_(comments=True)
def parse(self): def parse(self):
@ -125,6 +126,16 @@ class Parser(object):
), ),
self.cur_token_location_, self.cur_token_location_,
) )
# Report any missing glyphs at the end of parsing
if self.missing:
error = [
" %s (first found at %s)" % (name, loc)
for name, loc in self.missing.items()
]
raise FeatureLibError(
"The following glyph names are referenced but are missing from the "
"glyph set:\n" + ("\n".join(error)), None
)
return self.doc_ return self.doc_
def parse_anchor_(self): def parse_anchor_(self):
@ -2073,19 +2084,18 @@ class Parser(object):
raise FeatureLibError("Expected a glyph name or CID", self.cur_token_location_) raise FeatureLibError("Expected a glyph name or CID", self.cur_token_location_)
def check_glyph_name_in_glyph_set(self, *names): def check_glyph_name_in_glyph_set(self, *names):
"""Raises if glyph name (just `start`) or glyph names of a """Adds a glyph name (just `start`) or glyph names of a
range (`start` and `end`) are not in the glyph set. range (`start` and `end`) which are not in the glyph set
to the "missing list" for future error reporting.
If no glyph set is present, does nothing. If no glyph set is present, does nothing.
""" """
if self.glyphNames_: if self.glyphNames_:
missing = [name for name in names if name not in self.glyphNames_] for name in names:
if missing: if name in self.glyphNames_:
raise FeatureLibError( continue
"The following glyph names are referenced but are missing from the " if name not in self.missing:
f"glyph set: {', '.join(missing)}", self.missing[name] = self.cur_token_location_
self.cur_token_location_,
)
def expect_markClass_reference_(self): def expect_markClass_reference_(self):
name = self.expect_class_name_() name = self.expect_class_name_()

View File

@ -316,7 +316,7 @@ class ParserTest(unittest.TestCase):
def test_strict_glyph_name_check(self): def test_strict_glyph_name_check(self):
self.parse("@bad = [a b ccc];", glyphNames=("a", "b", "ccc")) self.parse("@bad = [a b ccc];", glyphNames=("a", "b", "ccc"))
with self.assertRaisesRegex(FeatureLibError, "missing from the glyph set: ccc"): with self.assertRaisesRegex(FeatureLibError, "(?s)missing from the glyph set:.*ccc"):
self.parse("@bad = [a b ccc];", glyphNames=("a", "b")) self.parse("@bad = [a b ccc];", glyphNames=("a", "b"))
def test_glyphclass(self): def test_glyphclass(self):