Vulkan-Docs/scripts/spec_tools/base_printer.py
Jon Leech 5abf83f95d Change log for April 16, 2019 Vulkan 1.1.107 spec update:
* Update release number to 107.

Public Issues:

  * Fix revision date for the `<<VK_AMD_gpu_shader_half_float>>` appendix
    (public issue 617).
  * Make <<synchronization-pipeline-barriers-subpass-self-dependencies,
    subpass self-dependencies>> less restrictive (public issue 777).
  * Fix the `<<VK_EXT_full_screen_exclusive>>` dependency on
    `<<VK_KHR_win32_surface>>` in `vk.xml` (public pull request 849).
  * Remove single-page (`apispec.html`) refpage sub-targets from the
    Makefile `allman` target and the build instructions. The target is still
    present in the Makefile, but we have not been actively maintaining the
    single-page document and do not promise it will work. The full
    Specification and the individual API reference pages are what we support
    and publish at present (public issue 949).

Internal Issues:

  * De-duplicate common valid usage statements shared by multiple commands
    or structures by using asciidoctor includes and dynamically assigning
    part of the valid usage ID based on which command or structure they're
    being applied to (internal issue 779).
  * Add reference pages for constructs not part of the formal API, such as
    platform calling convention macros, and script changes supporting them
    This required suppressing some check_spec_links warning classes in order
    to pass CI, until a more sophisticated fix can be done (internal issue
    888).
  * Change math notation for the elink:VkPrimitiveTopology descriptions to
    use short forms `v` and `p` instead of `vertex` and `primitive`,
    increasing legibility (internal issue 1611).
  * Rewrite generated file includes relative to a globally specified path,
    fixing some issues with refpage generation (internal issue 1630).
  * Update contributor list for `<<VK_EXT_calibrated_timestamps>>`.
  * Fix use of pathlin in `scripts/generator.py` so the script will work on
    Windows under Python 3.5 (internal merge request 3107).
  * Add missing conditionals around the
    <<descriptorsets-accelerationstructure, Acceleration Structure>>
    section (internal merge request 3108).
  * More script synchronization with OpenXR spec repository (internal merge
    request 3109).
  * Mark the `<<VK_AMD_gpu_shader_half_float>>` and
    `<<VK_AMD_gpu_shader_int16>>` extensions as deprecated in `vk.xml` and
    the corresponding extension appendices (internal merge request 3112).

New Extensions:

  * `<<VK_EXT_headless_surface>>`
2019-04-16 05:19:43 -07:00

224 lines
7.0 KiB
Python

"""Provides the BasePrinter base class for MacroChecker/Message output techniques."""
# Copyright (c) 2018-2019 Collabora, Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Author(s): Ryan Pavlik <ryan.pavlik@collabora.com>
from abc import ABC, abstractmethod
from pathlib import Path
from .macro_checker import MacroChecker
from .macro_checker_file import MacroCheckerFile
from .shared import EntityData, Message, MessageContext, MessageType
def getColumn(message_context):
"""Return the (zero-based) column number of the message context.
If a group is specified: returns the column of the start of the group.
If no group, but a match is specified: returns the column of the start of
the match.
If no match: returns column 0 (whole line).
"""
if not message_context.match:
# whole line
return 0
if message_context.group is not None:
return message_context.match.start(message_context.group)
return message_context.match.start()
class BasePrinter(ABC):
"""Base class for a way of outputting results of a checker execution."""
def __init__(self):
"""Constructor."""
self._cwd = None
def close(self):
"""Write the tail end of the output and close it, if applicable.
Override if you want to print a summary or are writing to a file.
"""
pass
###
# Output methods: these should all print/output directly.
def output(self, obj):
"""Output any object.
Delegates to other output* methods, if type known,
otherwise uses self.outputFallback().
"""
if isinstance(obj, Message):
self.outputMessage(obj)
elif isinstance(obj, MacroCheckerFile):
self.outputCheckerFile(obj)
elif isinstance(obj, MacroChecker):
self.outputChecker(obj)
else:
self.outputFallback(self.formatBrief(obj))
@abstractmethod
def outputResults(self, checker, broken_links=True,
missing_includes=False):
"""Output the full results of a checker run.
Must be implemented.
Typically will call self.output() on the MacroChecker,
as well as calling self.outputBrokenAndMissing()
"""
raise NotImplementedError
@abstractmethod
def outputBrokenLinks(self, checker, broken):
"""Output the collection of broken links.
`broken` is a dictionary of entity names: usage contexts.
Must be implemented.
Called by self.outputBrokenAndMissing() if requested.
"""
raise NotImplementedError
@abstractmethod
def outputMissingIncludes(self, checker, missing):
"""Output a table of missing includes.
`missing` is a iterable entity names.
Must be implemented.
Called by self.outputBrokenAndMissing() if requested.
"""
raise NotImplementedError
def outputChecker(self, checker):
"""Output the contents of a MacroChecker object.
Default implementation calls self.output() on every MacroCheckerFile.
"""
for f in checker.files:
self.output(f)
def outputCheckerFile(self, fileChecker):
"""Output the contents of a MacroCheckerFile object.
Default implementation calls self.output() on every Message.
"""
for m in fileChecker.messages:
self.output(m)
def outputBrokenAndMissing(self, checker, broken_links=True,
missing_includes=False):
"""Outputs broken links and missing includes, if desired.
Delegates to self.outputBrokenLinks() (if broken_links==True)
and self.outputMissingIncludes() (if missing_includes==True).
"""
if broken_links:
broken = checker.getBrokenLinks()
if broken:
self.outputBrokenLinks(checker, broken)
if missing_includes:
missing = checker.getMissingUnreferencedApiIncludes()
if missing:
self.outputMissingIncludes(checker, missing)
@abstractmethod
def outputMessage(self, msg):
"""Output a Message.
Must be implemented.
"""
raise NotImplementedError
@abstractmethod
def outputFallback(self, msg):
"""Output some text in a general way.
Must be implemented.
"""
raise NotImplementedError
###
# Format methods: these should all return a string.
def formatContext(self, context, _message_type=None):
"""Format a message context in a verbose way, if applicable.
May override, default implementation delegates to
self.formatContextBrief().
"""
return self.formatContextBrief(context)
def formatContextBrief(self, context, _with_color=True):
"""Format a message context in a brief way.
May override, default is relativeFilename:line:column
"""
return '{}:{}:{}'.format(self.getRelativeFilename(context.filename),
context.lineNum, getColumn(context))
def formatMessageTypeBrief(self, message_type, _with_color=True):
"""Format a message type in a brief way.
May override, default is message_type:
"""
return '{}:'.format(message_type)
def formatEntityBrief(self, entity_data, _with_color=True):
"""Format an entity in a brief way.
May override, default is macro:entity.
"""
return '{}:{}'.format(entity_data.macro, entity_data.entity)
def formatBrief(self, obj, with_color=True):
"""Format any object in a brief way.
Delegates to other format*Brief methods, if known,
otherwise uses str().
"""
if isinstance(obj, MessageContext):
return self.formatContextBrief(obj, with_color)
if isinstance(obj, MessageType):
return self.formatMessageTypeBrief(obj, with_color)
if isinstance(obj, EntityData):
return self.formatEntityBrief(obj, with_color)
return str(obj)
@property
def cwd(self):
"""Get the current working directory, fully resolved.
Lazy initialized.
"""
if not self._cwd:
self._cwd = Path('.').resolve()
return self._cwd
###
# Helper function
def getRelativeFilename(self, fn):
"""Return the given filename relative to the current directory,
if possible.
"""
try:
return str(Path(fn).relative_to(self.cwd))
except ValueError:
return str(Path(fn))