diff options
Diffstat (limited to 'codegen/vulkan/scripts/check_spec_links.py')
-rwxr-xr-x | codegen/vulkan/scripts/check_spec_links.py | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/codegen/vulkan/scripts/check_spec_links.py b/codegen/vulkan/scripts/check_spec_links.py new file mode 100755 index 00000000..16cfe438 --- /dev/null +++ b/codegen/vulkan/scripts/check_spec_links.py @@ -0,0 +1,164 @@ +#!/usr/bin/python3 +# +# Copyright (c) 2018-2019 Collabora, Ltd. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Author(s): Ryan Pavlik <ryan.pavlik@collabora.com> +# +# Purpose: This file performs some basic checks of the custom macros +# used in the AsciiDoctor source for the spec, especially +# related to the validity of the entities linked-to. + +from pathlib import Path + +from reg import Registry +from spec_tools.entity_db import EntityDatabase +from spec_tools.macro_checker import MacroChecker +from spec_tools.macro_checker_file import MacroCheckerFile +from spec_tools.main import checkerMain +from spec_tools.shared import (AUTO_FIX_STRING, EXTENSION_CATEGORY, MessageId, + MessageType) + +### +# "Configuration" constants + +FREEFORM_CATEGORY = 'freeform' + +# defines mentioned in spec but not needed in registry +EXTRA_DEFINES = ( + 'VKAPI_ATTR', + 'VKAPI_CALL', + 'VKAPI_PTR', + 'VK_NO_STDDEF_H', + 'VK_NO_STDINT_H', + ) + +# Extra freeform refpages in addition to EXTRA_DEFINES +EXTRA_REFPAGES = ( + 'VK_VERSION_1_0', + 'VK_VERSION_1_1', + 'VK_VERSION_1_2', + 'WSIheaders', + 'provisional-headers', + ) + +# These are marked with the code: macro +SYSTEM_TYPES = set(('void', 'char', 'float', 'size_t', 'uintptr_t', + 'int8_t', 'uint8_t', + 'int32_t', 'uint32_t', + 'int64_t', 'uint64_t')) + +ROOT = Path(__file__).resolve().parent.parent +DEFAULT_DISABLED_MESSAGES = set(( + MessageId.LEGACY, + MessageId.REFPAGE_MISSING, + MessageId.MISSING_MACRO, + MessageId.EXTENSION, + # TODO *text macro checking actually needs fixing for Vulkan + MessageId.MISUSED_TEXT, + MessageId.MISSING_TEXT +)) + +CWD = Path('.').resolve() + + +class VulkanEntityDatabase(EntityDatabase): + """Vulkan-specific subclass of EntityDatabase.""" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._conditionally_recognized = set(('fname', 'sname')) + + def makeRegistry(self): + registryFile = str(ROOT / 'xml/vk.xml') + registry = Registry() + registry.loadFile(registryFile) + return registry + + def getNamePrefix(self): + return "vk" + + def getPlatformRequires(self): + return 'vk_platform' + + def getSystemTypes(self): + return SYSTEM_TYPES + + def populateMacros(self): + self.addMacros('t', ['link', 'name'], ['funcpointers', 'flags']) + + def populateEntities(self): + # These are not mentioned in the XML + for name in EXTRA_DEFINES: + self.addEntity(name, 'dlink', + category=FREEFORM_CATEGORY, generates=False) + for name in EXTRA_REFPAGES: + self.addEntity(name, 'code', + category=FREEFORM_CATEGORY, generates=False) + + def shouldBeRecognized(self, macro, entity_name): + """Determine, based on the macro and the name provided, if we should expect to recognize the entity.""" + if super().shouldBeRecognized(macro, entity_name): + return True + + # The *name: macros in Vulkan should also be recognized if the entity name matches the pattern. + if macro in self._conditionally_recognized and self.likelyRecognizedEntity(entity_name): + return True + return False + + +class VulkanMacroCheckerFile(MacroCheckerFile): + """Vulkan-specific subclass of MacroCheckerFile.""" + + def handleWrongMacro(self, msg, data): + """Report an appropriate message when we found that the macro used is incorrect. + + May be overridden depending on each API's behavior regarding macro misuse: + e.g. in some cases, it may be considered a MessageId.LEGACY warning rather than + a MessageId.WRONG_MACRO or MessageId.EXTENSION. + """ + message_type = MessageType.WARNING + message_id = MessageId.WRONG_MACRO + group = 'macro' + + if data.category == EXTENSION_CATEGORY: + # Ah, this is an extension + msg.append( + 'This is apparently an extension name, which should be marked up as a link.') + message_id = MessageId.EXTENSION + group = None # replace the whole thing + else: + # Non-extension, we found the macro though. + if data.macro[0] == self.macro[0] and data.macro[1:] == 'link' and self.macro[1:] == 'name': + # First letter matches, old is 'name', new is 'link': + # This is legacy markup + msg.append( + 'This is legacy markup that has not been updated yet.') + message_id = MessageId.LEGACY + else: + # Not legacy, just wrong. + message_type = MessageType.ERROR + + msg.append(AUTO_FIX_STRING) + self.diag(message_type, message_id, msg, + group=group, replacement=self.makeMacroMarkup(data=data), fix=self.makeFix(data=data)) + + +def makeMacroChecker(enabled_messages): + """Create a correctly-configured MacroChecker instance.""" + entity_db = VulkanEntityDatabase() + return MacroChecker(enabled_messages, entity_db, VulkanMacroCheckerFile, ROOT) + + +if __name__ == '__main__': + default_enabled_messages = set(MessageId).difference( + DEFAULT_DISABLED_MESSAGES) + + all_docs = [str(fn) + for fn in sorted((ROOT / 'chapters/').glob('**/*.txt'))] + all_docs.extend([str(fn) + for fn in sorted((ROOT / 'appendices/').glob('**/*.txt'))]) + + checkerMain(default_enabled_messages, makeMacroChecker, + all_docs) |