From b8d3efdb311110e133ea3094e111975d3d20373d Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 29 Mar 2017 16:33:01 +0100 Subject: [PATCH] Move document checking to a C++ header file * It's better to edit C++ source natively not in the SWIG file, and also clang-format can format it. --- qrenderdoc/Code/pyrenderdoc/document_check.h | 86 ++++++++++++++++++++ qrenderdoc/Code/pyrenderdoc/document_check.i | 70 ---------------- qrenderdoc/Code/pyrenderdoc/renderdoc.i | 21 ++++- qrenderdoc/qrenderdoc.pro | 2 + qrenderdoc/qrenderdoc_local.vcxproj | 4 +- qrenderdoc/qrenderdoc_local.vcxproj.filters | 6 +- 6 files changed, 113 insertions(+), 76 deletions(-) create mode 100644 qrenderdoc/Code/pyrenderdoc/document_check.h delete mode 100644 qrenderdoc/Code/pyrenderdoc/document_check.i diff --git a/qrenderdoc/Code/pyrenderdoc/document_check.h b/qrenderdoc/Code/pyrenderdoc/document_check.h new file mode 100644 index 000000000..f0dbf5e72 --- /dev/null +++ b/qrenderdoc/Code/pyrenderdoc/document_check.h @@ -0,0 +1,86 @@ +/****************************************************************************** + * The MIT License (MIT) + * + * Copyright (c) 2017 Baldur Karlsson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + ******************************************************************************/ + +#pragma once + +inline void check_docstrings(swig_type_info **swig_types, size_t numTypes) +{ + std::set docstrings; + for(size_t i = 0; i < numTypes; i++) + { + SwigPyClientData *typeinfo = (SwigPyClientData *)swig_types[i]->clientdata; + + // opaque types have no typeinfo, skip these + if(!typeinfo) + continue; + + PyTypeObject *typeobj = typeinfo->pytype; + + std::string typedoc = typeobj->tp_doc; + + auto result = docstrings.insert(typedoc); + + if(!result.second) + { + snprintf(convert_error, sizeof(convert_error) - 1, + "Duplicate docstring '%s' found on struct '%s' - are you missing a DOCUMENT()?", + typedoc.c_str(), typeobj->tp_name); + RENDERDOC_LogMessage(LogType::Fatal, "QTRD", __FILE__, __LINE__, convert_error); + } + + PyMethodDef *method = typeobj->tp_methods; + + while(method->ml_doc) + { + std::string typedoc = method->ml_doc; + + size_t i = 0; + while(typedoc[i] == '\n') + i++; + + // skip the first line as it's autodoc generated + i = typedoc.find('\n', i); + if(i != std::string::npos) + { + while(typedoc[i] == '\n') + i++; + + typedoc.erase(0, i); + + result = docstrings.insert(typedoc); + + if(!result.second) + { + snprintf( + convert_error, sizeof(convert_error) - 1, + "Duplicate docstring '%s' found on method '%s.%s' - are you missing a DOCUMENT()?", + method_doc.c_str(), typeobj->tp_name, method->ml_name); + RENDERDOC_LogMessage(LogType::Fatal, "QTRD", __FILE__, __LINE__, convert_error); + } + } + + method++; + } + } +} diff --git a/qrenderdoc/Code/pyrenderdoc/document_check.i b/qrenderdoc/Code/pyrenderdoc/document_check.i deleted file mode 100644 index 541837639..000000000 --- a/qrenderdoc/Code/pyrenderdoc/document_check.i +++ /dev/null @@ -1,70 +0,0 @@ -// this file is included from renderdoc.i, it's not a module in itself - -%header %{ - #include -%} - -%init %{ - // verify that docstrings aren't duplicated, which is a symptom of missing DOCUMENT() - // macros around newly added classes/members. - #if !defined(RELEASE) - static bool doc_checked = false; - - if(!doc_checked) - { - doc_checked = true; - - std::set docstrings; - for(size_t i=0; i < sizeof(swig_type_initial)/sizeof(swig_type_initial[0]); i++) - { - SwigPyClientData *typeinfo = (SwigPyClientData *)swig_type_initial[i]->clientdata; - - // opaque types have no typeinfo, skip these - if(!typeinfo) continue; - - PyTypeObject *typeobj = typeinfo->pytype; - - std::string typedoc = typeobj->tp_doc; - - auto result = docstrings.insert(typedoc); - - if(!result.second) - { - snprintf(convert_error, sizeof(convert_error)-1, "Duplicate docstring '%s' found on struct '%s' - are you missing a DOCUMENT()?", typedoc.c_str(), typeobj->tp_name); - RENDERDOC_LogMessage(LogType::Fatal, "QTRD", __FILE__, __LINE__, convert_error); - } - - PyMethodDef *method = typeobj->tp_methods; - - while(method->ml_doc) - { - std::string typedoc = method->ml_doc; - - size_t i = 0; - while(typedoc[i] == '\n') - i++; - - // skip the first line as it's autodoc generated - i = typedoc.find('\n', i); - if(i != std::string::npos) - { - while(typedoc[i] == '\n') - i++; - - typedoc.erase(0, i); - - result = docstrings.insert(typedoc); - - if(!result.second) - { - snprintf(convert_error, sizeof(convert_error)-1, "Duplicate docstring '%s' found on method '%s' - are you missing a DOCUMENT()?", typedoc.c_str(), method->ml_name); - RENDERDOC_LogMessage(LogType::Fatal, "QTRD", __FILE__, __LINE__, convert_error); - } - } - - method++; - } - } - } - #endif -%} diff --git a/qrenderdoc/Code/pyrenderdoc/renderdoc.i b/qrenderdoc/Code/pyrenderdoc/renderdoc.i index c2d37aec8..16ade6b82 100644 --- a/qrenderdoc/Code/pyrenderdoc/renderdoc.i +++ b/qrenderdoc/Code/pyrenderdoc/renderdoc.i @@ -102,4 +102,23 @@ PyObject *PassObjectToPython(const char *type, void *obj) %} -%include "document_check.i" +%header %{ + #include + #include "Code/pyrenderdoc/document_check.h" +%} + +%init %{ + // verify that docstrings aren't duplicated, which is a symptom of missing DOCUMENT() + // macros around newly added classes/members. + // For enums, verify that all constants are documented in the parent docstring + #if !defined(RELEASE) + static bool doc_checked = false; + + if(!doc_checked) + { + doc_checked = true; + + check_docstrings(swig_type_initial, sizeof(swig_type_initial)/sizeof(swig_type_initial[0])); + } + #endif +%} diff --git a/qrenderdoc/qrenderdoc.pro b/qrenderdoc/qrenderdoc.pro index 3e7ccada0..15bc6f926 100644 --- a/qrenderdoc/qrenderdoc.pro +++ b/qrenderdoc/qrenderdoc.pro @@ -210,6 +210,8 @@ HEADERS += Code/CaptureContext.h \ Code/QRDUtils.h \ Code/Resources.h \ Code/pyrenderdoc/PythonContext.h \ + Code/pyrenderdoc/pyconversion.h \ + Code/pyrenderdoc/document_check.h \ Code/Interface/QRDInterface.h \ Code/Interface/CommonPipelineState.h \ Code/Interface/PersistantConfig.h \ diff --git a/qrenderdoc/qrenderdoc_local.vcxproj b/qrenderdoc/qrenderdoc_local.vcxproj index 081ede8f7..b67c19edb 100644 --- a/qrenderdoc/qrenderdoc_local.vcxproj +++ b/qrenderdoc/qrenderdoc_local.vcxproj @@ -859,6 +859,7 @@ + @@ -1175,7 +1176,7 @@ Document - %(Fullpath);pyconversion.i;document_check.i;$(SolutionDir)renderdoc\api\replay\basic_types.h;$(SolutionDir)renderdoc\api\replay\capture_options.h;$(SolutionDir)renderdoc\api\replay\control_types.h;$(SolutionDir)renderdoc\api\replay\d3d11_pipestate.h;$(SolutionDir)renderdoc\api\replay\d3d12_pipestate.h;$(SolutionDir)renderdoc\api\replay\data_types.h;$(SolutionDir)renderdoc\api\replay\gl_pipestate.h;$(SolutionDir)renderdoc\api\replay\renderdoc_replay.h;$(SolutionDir)renderdoc\api\replay\replay_enums.h;$(SolutionDir)renderdoc\api\replay\shader_types.h;$(SolutionDir)renderdoc\api\replay\vk_pipestate.h;%(AdditionalInputs) + %(Fullpath);pyconversion.i;document_check.h;$(SolutionDir)renderdoc\api\replay\basic_types.h;$(SolutionDir)renderdoc\api\replay\capture_options.h;$(SolutionDir)renderdoc\api\replay\control_types.h;$(SolutionDir)renderdoc\api\replay\d3d11_pipestate.h;$(SolutionDir)renderdoc\api\replay\d3d12_pipestate.h;$(SolutionDir)renderdoc\api\replay\data_types.h;$(SolutionDir)renderdoc\api\replay\gl_pipestate.h;$(SolutionDir)renderdoc\api\replay\renderdoc_replay.h;$(SolutionDir)renderdoc\api\replay\replay_enums.h;$(SolutionDir)renderdoc\api\replay\shader_types.h;$(SolutionDir)renderdoc\api\replay\vk_pipestate.h;%(AdditionalInputs) $(ProjectDir)3rdparty\swig\swig.exe -v -Wextra -Werror -O -c++ -python -modern -modernargs -enumclass -fastunpack -py3 -builtin -I$(SolutionDir)renderdoc\api\replay -outdir $(IntDir)generated -o $(IntDir)generated\%(Filename)_python.cxx %(FullPath) Compiling SWIG interface $(IntDir)generated\%(Filename).py;$(IntDir)generated\%(Filename)_python.cxx;%(Outputs) @@ -1374,7 +1375,6 @@ - diff --git a/qrenderdoc/qrenderdoc_local.vcxproj.filters b/qrenderdoc/qrenderdoc_local.vcxproj.filters index 3f319adf6..22762f82a 100644 --- a/qrenderdoc/qrenderdoc_local.vcxproj.filters +++ b/qrenderdoc/qrenderdoc_local.vcxproj.filters @@ -878,6 +878,9 @@ Code\Interface + + Code\pyrenderdoc + @@ -1060,9 +1063,6 @@ Code\pyrenderdoc - - Code\pyrenderdoc -