94 lines
3.3 KiB
Python
94 lines
3.3 KiB
Python
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
import re
|
|
|
|
from .base import CAN_COPY, Entry, OffsetComment, Junk, Whitespace, Parser
|
|
|
|
|
|
class DefinesInstruction(Entry):
|
|
"""Entity-like object representing processing instructions in inc files"""
|
|
|
|
def __init__(self, ctx, span, val_span):
|
|
self.ctx = ctx
|
|
self.span = span
|
|
self.key_span = self.val_span = val_span
|
|
|
|
def __repr__(self):
|
|
return self.raw_val
|
|
|
|
|
|
class DefinesParser(Parser):
|
|
# can't merge, #unfilter needs to be the last item, which we don't support
|
|
capabilities = CAN_COPY
|
|
reWhitespace = re.compile("\n+", re.M)
|
|
|
|
EMPTY_LINES = 1 << 0
|
|
|
|
class Comment(OffsetComment):
|
|
comment_offset = 2
|
|
|
|
class Context(Parser.Context):
|
|
def __init__(self, contents):
|
|
super().__init__(contents)
|
|
self.filter_empty_lines = False
|
|
|
|
def __init__(self):
|
|
self.reComment = re.compile("(?:^# .*?\n)*(?:^# [^\n]*)", re.M)
|
|
# corresponds to
|
|
# https://hg.mozilla.org/mozilla-central/file/72ee4800d4156931c89b58bd807af4a3083702bb/python/mozbuild/mozbuild/preprocessor.py#l561 # noqa
|
|
self.reKey = re.compile(
|
|
r"#define[ \t]+(?P<key>\w+)(?:[ \t](?P<val>[^\n]*))?", re.M
|
|
)
|
|
self.rePI = re.compile(r"#(?P<val>\w+[ \t]+[^\n]+)", re.M)
|
|
Parser.__init__(self)
|
|
|
|
def getNext(self, ctx, offset):
|
|
junk_offset = offset
|
|
contents = ctx.contents
|
|
|
|
m = self.reComment.match(ctx.contents, offset)
|
|
if m:
|
|
current_comment = self.Comment(ctx, m.span())
|
|
offset = m.end()
|
|
else:
|
|
current_comment = None
|
|
|
|
m = self.reWhitespace.match(contents, offset)
|
|
if m:
|
|
# blank lines outside of filter_empty_lines or
|
|
# leading whitespace are bad
|
|
if offset == 0 or not (len(m.group()) == 1 or ctx.filter_empty_lines):
|
|
if current_comment:
|
|
return current_comment
|
|
return Junk(ctx, m.span())
|
|
white_space = Whitespace(ctx, m.span())
|
|
offset = m.end()
|
|
if current_comment is not None and white_space.raw_val.count("\n") > 1:
|
|
# standalone comment
|
|
# return the comment, and reparse the whitespace next time
|
|
return current_comment
|
|
if current_comment is None:
|
|
return white_space
|
|
else:
|
|
white_space = None
|
|
|
|
m = self.reKey.match(contents, offset)
|
|
if m:
|
|
return self.createEntity(ctx, m, current_comment, white_space)
|
|
# defines instructions don't have comments
|
|
# Any pending commment is standalone
|
|
if current_comment:
|
|
return current_comment
|
|
if white_space:
|
|
return white_space
|
|
m = self.rePI.match(contents, offset)
|
|
if m:
|
|
instr = DefinesInstruction(ctx, m.span(), m.span("val"))
|
|
if instr.val == "filter emptyLines":
|
|
ctx.filter_empty_lines = True
|
|
if instr.val == "unfilter emptyLines":
|
|
ctx.filter_empty_lines = False
|
|
return instr
|
|
return self.getJunk(ctx, junk_offset, self.reComment, self.reKey, self.rePI)
|