Changeset - r27004:19d7e1215f65
[Not reviewed]
master
0 1 2
Rubidium - 21 months ago 2023-03-02 21:02:37
rubidium@openttd.org
Add: workflow and script for checking missing mode enforcements
3 files changed with 96 insertions and 4 deletions:
0 comments (0 inline, 0 general)
.github/script-missing-mode-enforcement.py
Show inline comments
 
new file 100644
 
"""
 
Script to scan the OpenTTD's script API for functions that miss checks for the
 
function being called from the right mode (deity or company mode).
 

	
 
When a function calls either ScriptObject::Command or ScriptObject::GetCompany
 
then the function is considered dangerous. When one of the mode enforcement
 
macros from script_error.hpp, i.e. EnforceDeityMode, EnforceCompanyModeValid or
 
EnforceDeityOrCompanyModeValid, are called in the function, then we consider
 
that the function has mode enforcement.
 

	
 
Any dangerous function for which no enforcement is found are emitted as errors.
 
"""
 

	
 
import glob
 
import re
 
import sys
 

	
 

	
 
def check_mode_enforcement(path):
 
    errors = []
 
    with open(path, "r") as reader:
 
        mode_enforcement_found = False
 
        dangerous_function = False
 
        for line in reader:
 
            # Line does not start with a tab and have <word>::<word>. That looks like the begin of a function, so reset the state.
 
            if re.match(r"^[^\t].*\w::\w", line):
 
                mode_enforcement_found = False
 
                dangerous_function = False
 
                currentFunction = line
 
                continue
 

	
 
            if re.match(
 
                r"\t(EnforceDeityMode|EnforceCompanyModeValid|EnforceDeityOrCompanyModeValid|EnforceDeityOrCompanyModeValid_Void)\(",
 
                line,
 
            ):
 
                # Mode enforcement macro found
 
                mode_enforcement_found = True
 
                continue
 

	
 
            if re.match(r".*(ScriptObject::Command|ScriptObject::GetCompany).*", line):
 
                # Dangerous function found
 
                dangerous_function = True
 
                continue
 

	
 
            # Line with only a closing bracket. That looks like the end of a function, so check for the dangerous function without mode enforcement
 
            if re.match(r"^}$", line) and dangerous_function and not mode_enforcement_found:
 
                function_name = currentFunction.rstrip("\n").replace("/* static */ ", "")
 
                errors.append(f"{path}: {function_name}")
 

	
 
    return errors
 

	
 

	
 
def main():
 
    errors = []
 
    for path in sorted(glob.glob("src/script/api/*.cpp")):
 
        # Skip a number of files that yield only false positives
 
        if path.endswith(("script_object.cpp", "script_companymode.cpp", "script_controller.cpp", "script_game.cpp")):
 
            continue
 

	
 
        errors.extend(check_mode_enforcement(path))
 

	
 
    if errors:
 
        print("Mode enforcement was expected in the following files/functions:")
 
        print("\n".join(errors))
 
        sys.exit(1)
 

	
 
    print("OK")
 

	
 

	
 
if __name__ == "__main__":
 
    main()
.github/unused-strings.py
Show inline comments
 
@@ -210,11 +210,10 @@ def main():
 
            errors.append(f"ERROR: {string} is (possibly) no longer needed.")
 

	
 
    if errors:
 
        for error in errors:
 
            print(error)
 
        print("\n".join(errors))
 
        sys.exit(1)
 
    else:
 
        print("OK")
 

	
 
    print("OK")
 

	
 

	
 
if __name__ == "__main__":
.github/workflows/script-missing-mode-enforcement.yml
Show inline comments
 
new file 100644
 
name: Script missing mode enforcement
 

	
 
on:
 
  pull_request:
 

	
 
concurrency:
 
  group: ${{ github.workflow }}-${{ github.ref }}
 
  cancel-in-progress: ${{ github.ref != 'refs/heads/master' }}
 

	
 
jobs:
 
  script-missing-mode-enforcement:
 
    name: Script missing mode enforcement
 
    runs-on: ubuntu-latest
 

	
 
    steps:
 
    - name: Checkout
 
      uses: actions/checkout@v3
 

	
 
    - name: Check for finding script functions that require company/deity mode enforcement/checks
 
      run: |
 
        set -ex
 
        python3 .github/script-missing-mode-enforcement.py
0 comments (0 inline, 0 general)