diff options
author | Neil <nyamatongwe@gmail.com> | 2019-06-18 08:25:01 +1000 |
---|---|---|
committer | Neil <nyamatongwe@gmail.com> | 2019-06-18 08:25:01 +1000 |
commit | ba72e38dfd190eba4bc42fa4b3533f96a6735f8c (patch) | |
tree | 21be0671c69517c05f4fec13ddfaac730118acc6 /scripts | |
parent | 1e79a7c53fbfd7481e26f92037de92597dedaf79 (diff) | |
download | scintilla-mirror-ba72e38dfd190eba4bc42fa4b3533f96a6735f8c.tar.gz |
Feature [feature-requests:#1297] 1: Moved CheckMentioned.py script from scite to
scintilla as it does not access SciTE files.
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/CheckMentioned.py | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/scripts/CheckMentioned.py b/scripts/CheckMentioned.py new file mode 100644 index 000000000..5e6d1eefd --- /dev/null +++ b/scripts/CheckMentioned.py @@ -0,0 +1,218 @@ +#!/usr/bin/env python3 +# CheckMentioned.py +# Find all the symbols in scintilla/include/Scintilla.h and check if they +# are mentioned in scintilla/doc/ScintillaDoc.html. +# Requires Python 2.7 or later + +import re, string, sys + +srcRoot = "../.." + +sys.path.append(srcRoot + "/scintilla/scripts") + +import Face +import ScintillaData + +uninteresting = { + "SCINTILLA_H", "SCI_START", "SCI_LEXER_START", "SCI_OPTIONAL_START", + # These archaic names are #defined to the Sci_ prefixed modern equivalents. + # They are not documented so they are not used in new code. + "CharacterRange", "TextRange", "TextToFind", "RangeToFormat", "NotifyHeader", +} + +incFileName = srcRoot + "/scintilla/include/Scintilla.h" +docFileName = srcRoot + "/scintilla/doc/ScintillaDoc.html" +try: # Old Python + identCharacters = "_" + string.letters + string.digits +except AttributeError: # Python 3.x + identCharacters = "_" + string.ascii_letters + string.digits + +# Convert all punctuation characters except '_' into spaces. +def depunctuate(s): + d = "" + for ch in s: + if ch in identCharacters: + d = d + ch + else: + d = d + " " + return d + +symbols = {} +with open(incFileName, "rt") as incFile: + for line in incFile.readlines(): + if line.startswith("#define"): + identifier = line.split()[1] + symbols[identifier] = 0 + +with open(docFileName, "rt") as docFile: + for line in docFile.readlines(): + for word in depunctuate(line).split(): + if word in symbols.keys(): + symbols[word] = 1 + +def convertIFaceTypeToC(t): + if t == "position": + return "int " + elif t == "keymod": + return "int " + elif t == "string": + return "const char *" + elif t == "stringresult": + return "char *" + elif t == "cells": + return "cell *" + elif t == "textrange": + return "Sci_TextRange *" + elif t == "findtext": + return "Sci_TextToFind *" + elif t == "formatrange": + return "Sci_RangeToFormat *" + return t + " " + +def makeParm(t, n, v): + return (convertIFaceTypeToC(t) + n).rstrip() + +def makeRet(params): + retType = params["ReturnType"] + if retType in ["void", "string", "stringresult"]: + retType = "" + if retType: + retType = " → " + retType + + return retType + +def makeSig(params): + p1 = makeParm(params["Param1Type"], params["Param1Name"], params["Param1Value"]) + p2 = makeParm(params["Param2Type"], params["Param2Name"], params["Param2Value"]) + + retType = params["ReturnType"] + if retType in ["void", "string", "stringresult"]: + retType = "" + if retType: + retType = " → " + retType + + if p1 == "" and p2 == "": + return retType + + ret = "" + if p1 == "": + p1 = "<unused>" + joiner = "" + if p2 != "": + joiner = ", " + return "(" + p1 + joiner + p2 + ")" + retType + +pathIface = srcRoot + "/scintilla/include/Scintilla.iface" + +def retrieveFeatures(): + sci = ScintillaData.ScintillaData(srcRoot + "/scintilla/") + face = Face.Face() + face.ReadFromFile(pathIface) + sciToFeature = {} + sccToValue = { "true":"1", "false":"0", "EN_SETFOCUS":"256", "EN_KILLFOCUS":"512"} + for name in face.order: + v = face.features[name] + if v["FeatureType"] in ["fun", "get", "set"]: + featureDefineName = "SCI_" + name.upper() + sciToFeature[featureDefineName] = name + elif v["FeatureType"] in ["val"]: + featureDefineName = name.upper() + sccToValue[featureDefineName] = v["Value"] + elif v["FeatureType"] in ["evt"]: + featureDefineName = "SCN_" + name.upper() + sccToValue[featureDefineName] = v["Value"] + return (face, sciToFeature, sccToValue) + +def flattenSpaces(s): + return s.replace("\n", " ").replace(" ", " ").replace(" ", " ").replace(" ", " ").strip() + +def printCtag(ident, path): + print(ident.strip() + "\t" + path + "\t" + "/^" + ident + "$/") + +def checkDocumentation(): + with open(docFileName, "rt") as docFile: + docs = docFile.read() + + face, sciToFeature, sccToValue = retrieveFeatures() + + headers = {} + definitions = {} + + # Examine header sections which point to definitions + #<a class="message" href="#SCI_SETLAYOUTCACHE">SCI_SETLAYOUTCACHE(int cacheMode)</a><br /> + dirPattern = re.compile(r'<a class="message" href="#([A-Z0-9_]+)">([A-Z][A-Za-z0-9_() *&;,\n]+)</a>') + firstWord = re.compile(r'[A-Z0-9_]+') + for api, sig in re.findall(dirPattern, docs): + sigApi = re.split('\W+', sig)[0] + sigFlat = flattenSpaces(sig) + sigFlat = sigFlat.replace('alpha ', 'int ') + sigFlat = sigFlat.replace("document *", "int ") + sigFlat = sigFlat.rstrip() + if '(' in sigFlat or api.startswith("SCI_"): + name = sciToFeature[api] + sigFromFace = api + makeSig(face.features[name]) + if sigFlat != sigFromFace: + pass + print(sigFlat, sigFromFace) + #~ printCtag(api, docFileName) + #~ printCtag(" " + name, pathIface) + if api != sigApi: + print(sigApi, ";;", sig, ";;", api) + headers[api] = 1 + # Warns for most keyboard commands so not enabled + #~ for api in sorted(sciToFeature.keys()): + #~ if api not in headers: + #~ print("No header for ", api) + + # Examine definitions + #<b id="SCI_SETLAYOUTCACHE">SCI_SETLAYOUTCACHE(int cacheMode)</b> + defPattern = re.compile(r'<b id="([A-Z_0-9]+)">([A-Z][A-Za-z0-9_() *#\"=<>/&;,\n-]+?)</b>') + for api, sig in re.findall(defPattern, docs): + sigFlat = flattenSpaces(sig) + if '<a' in sigFlat : # Remove anchors + sigFlat = re.sub('<a.*>(.+)</a>', '\\1', sigFlat) + sigFlat = sigFlat.replace('alpha ', 'int ') + sigFlat = sigFlat.replace("document *", "int ") + sigFlat = sigFlat.replace(' NUL-terminated', '') + sigFlat = sigFlat.rstrip() + #~ sigFlat = sigFlat.replace(' NUL-terminated', '') + sigApi = re.split('\W+', sigFlat)[0] + #~ print(sigFlat, ";;", sig, ";;", api) + if '(' in sigFlat or api.startswith("SCI_"): + try: + name = sciToFeature[api] + sigFromFace = api + makeSig(face.features[name]) + if sigFlat != sigFromFace: + print(sigFlat, sigFromFace) + #~ printCtag('="' + api, docFileName) + #~ printCtag(" " + name, pathIface) + except KeyError: + pass # Feature removed but still has documentation + if api != sigApi: + print(sigApi, ";;", sig, ";;", api) + definitions[api] = 1 + # Warns for most keyboard commands so not enabled + #~ for api in sorted(sciToFeature.keys()): + #~ if api not in definitions: + #~ print("No definition for ", api) + + outName = docFileName.replace("Doc", "Dox") + with open(outName, "wt") as docFile: + docFile.write(docs) + + # Examine constant definitions + #<code>SC_CARETSTICKY_WHITESPACE</code> (2) + constPattern = re.compile(r'<code>(\w+)</code> *\((\w+)\)') + for name, val in re.findall(constPattern, docs): + try: + valOfName = sccToValue[name] + if val != valOfName: + print(val, "<-", name, ";;", valOfName) + except KeyError: + print("***", val, "<-", name) + +for identifier in sorted(symbols.keys()): + if not symbols[identifier] and identifier not in uninteresting: + print(identifier) + +checkDocumentation() |