Нормализовать переводы строк в LF
Решение по TD-STYLE-ANALYZERS: LF — инструменты проекта (Python/Node) пишут LF, CRLF-.sh не работают на Linux CI (sh scripts/ci.sh), большинство файлов уже были LF. Добавлен .gitattributes (* text=auto eol=lf, бинарные исключения), .editorconfig переведён на lf, 1029 файлов конвертированы, git add --renormalize. Из индекса убраны закравшиеся archive/**/__pycache__/*.pyc.
This commit is contained in:
+155
-155
@@ -1,155 +1,155 @@
|
||||
"""Понижение XML-док комментариев с private/internal членов до обычных `//` (код-стайл «Дейл» §5).
|
||||
|
||||
Правило: XML-doc — только на public/protected. Приватные детали реализации — при необходимости короткий
|
||||
обычный комментарий. Скрипт сохраняет текст (теги <param>/<returns> и т.п. разворачиваются в читаемый вид).
|
||||
|
||||
Режимы:
|
||||
python scripts/fix_private_docs.py --preview [N] # показать N примеров (по умолчанию 10)
|
||||
python scripts/fix_private_docs.py --apply # применить
|
||||
python scripts/fix_private_docs.py --check # сколько блоков будет изменено
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
ROOT = r"C:\telbase\src"
|
||||
EXC = ("bin", "obj", "node_modules", ".git")
|
||||
DOC_RE = re.compile(r"^(\s*)///[ \t]?(.*)$")
|
||||
ACC_RE = re.compile(r"\b(public|protected|private|internal)\b")
|
||||
|
||||
|
||||
def demote(block_content):
|
||||
"""block_content: список строк после '///'. Возвращает список строк текста обычного комментария."""
|
||||
t = "\n".join(block_content)
|
||||
t = re.sub(r"<summary>\s*(.*?)\s*</summary>", r"\1", t, flags=re.S)
|
||||
t = re.sub(r"<remarks>\s*(.*?)\s*</remarks>", r"\1", t, flags=re.S)
|
||||
t = re.sub(r"<typeparamref\s+name=\"([^\"]+)\"\s*/?>", r"\1", t)
|
||||
t = re.sub(r"<paramref\s+name=\"([^\"]+)\"\s*/?>", r"\1", t)
|
||||
t = re.sub(r"<typeparam\s+name=\"([^\"]+)\"\s*>\s*(.*?)\s*</typeparam>", r"\1: \2", t, flags=re.S)
|
||||
t = re.sub(r"<param\s+name=\"([^\"]+)\"\s*>\s*(.*?)\s*</param>", r"\1: \2", t, flags=re.S)
|
||||
t = re.sub(r"<returns>\s*(.*?)\s*</returns>", r"Возвращает: \1", t, flags=re.S)
|
||||
t = re.sub(
|
||||
r"<exception\s+cref=\"([^\"]+)\"\s*>\s*(.*?)\s*</exception>",
|
||||
r"Исключение \1: \2",
|
||||
t,
|
||||
flags=re.S,
|
||||
)
|
||||
t = re.sub(r"<see\s+cref=\"([^\"]+)\"\s*/?>", r"\1", t)
|
||||
t = re.sub(r"<seealso\s+cref=\"[^\"]+\"\s*/?>", "", t)
|
||||
t = re.sub(r"<inheritdoc\s*/?>", "", t)
|
||||
t = re.sub(r"</?c>", "", t)
|
||||
t = re.sub(r"<[^>]+>", "", t)
|
||||
out = []
|
||||
for line in t.split("\n"):
|
||||
s = line.strip()
|
||||
if s:
|
||||
out.append(s)
|
||||
return out
|
||||
|
||||
|
||||
def iter_cs():
|
||||
for dp, dn, fn in os.walk(ROOT):
|
||||
dn[:] = [d for d in dn if d not in EXC]
|
||||
for f in fn:
|
||||
if f.endswith(".cs"):
|
||||
yield os.path.join(dp, f)
|
||||
|
||||
|
||||
def find_blocks(lines):
|
||||
"""Возвращает список (start, end, block_content, decl_index, decl)."""
|
||||
res = []
|
||||
i = 0
|
||||
while i < len(lines):
|
||||
m = DOC_RE.match(lines[i].rstrip("\r"))
|
||||
if not m:
|
||||
i += 1
|
||||
continue
|
||||
start = i
|
||||
block = []
|
||||
while i < len(lines):
|
||||
m2 = DOC_RE.match(lines[i].rstrip("\r"))
|
||||
if not m2:
|
||||
break
|
||||
block.append(m2.group(2))
|
||||
i += 1
|
||||
end = i # exclusive
|
||||
j = i
|
||||
decl = ""
|
||||
while j < len(lines):
|
||||
s = lines[j].strip()
|
||||
if s == "" or s.startswith("["):
|
||||
j += 1
|
||||
continue
|
||||
decl = s
|
||||
break
|
||||
if not decl:
|
||||
continue
|
||||
if not any("<summary>" in b or "</summary>" in b for b in block):
|
||||
continue
|
||||
am = ACC_RE.search(decl)
|
||||
if am and am.group(1) in ("private", "internal"):
|
||||
res.append((start, end, block, decl))
|
||||
return res
|
||||
|
||||
|
||||
def process_file(path, apply):
|
||||
raw = open(path, "rb").read().decode("utf-8")
|
||||
lines = raw.splitlines(keepends=True)
|
||||
plain = [l.rstrip("\r\n") for l in lines]
|
||||
endings = [l[len(l.rstrip("\r\n")):] for l in lines]
|
||||
blocks = find_blocks(plain)
|
||||
if not blocks:
|
||||
return 0, []
|
||||
changes = []
|
||||
for start, end, block, decl in blocks:
|
||||
indent = DOC_RE.match(plain[start]).group(1)
|
||||
comments = demote(block)
|
||||
new_lines = [indent + "//" + (" " + c if c else "") for c in comments]
|
||||
changes.append((start, end, new_lines, decl))
|
||||
# применяем с конца
|
||||
for start, end, new_lines, decl in reversed(changes):
|
||||
ending = endings[start] if endings[start] else (endings[end - 1] if end > start else "\n")
|
||||
replacement = [nl + ending for nl in new_lines]
|
||||
lines[start:end] = replacement
|
||||
if apply:
|
||||
open(path, "w", encoding="utf-8", newline="").write("".join(lines))
|
||||
return len(changes), [(b[0], b[3], demote(b[2])) for b in [(s, e, bl, d) for s, e, bl, d in blocks]]
|
||||
|
||||
|
||||
def main():
|
||||
if "--preview" in sys.argv:
|
||||
n = 10
|
||||
idx = sys.argv.index("--preview")
|
||||
if idx + 1 < len(sys.argv) and sys.argv[idx + 1].isdigit():
|
||||
n = int(sys.argv[idx + 1])
|
||||
shown = 0
|
||||
for path in iter_cs():
|
||||
raw = open(path, "rb").read().decode("utf-8")
|
||||
plain = [l.rstrip("\r\n") for l in raw.split("\n")]
|
||||
for start, end, block, decl in find_blocks(plain):
|
||||
print("FILE:", os.path.relpath(path, r"C:\telbase"), f"line {start + 1}")
|
||||
print(" DECL:", decl[:100])
|
||||
print(" BEFORE:")
|
||||
for b in plain[start:end]:
|
||||
print(" ", b)
|
||||
print(" AFTER:")
|
||||
for c in demote(block):
|
||||
print(" // " + c)
|
||||
print()
|
||||
shown += 1
|
||||
if shown >= n:
|
||||
return
|
||||
return
|
||||
apply = "--apply" in sys.argv
|
||||
total = 0
|
||||
files = 0
|
||||
for path in iter_cs():
|
||||
cnt, _ = process_file(path, apply)
|
||||
if cnt:
|
||||
files += 1
|
||||
total += cnt
|
||||
print(("APPLIED" if apply else "DRY-RUN"), "blocks:", total, "files:", files)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
"""Понижение XML-док комментариев с private/internal членов до обычных `//` (код-стайл «Дейл» §5).
|
||||
|
||||
Правило: XML-doc — только на public/protected. Приватные детали реализации — при необходимости короткий
|
||||
обычный комментарий. Скрипт сохраняет текст (теги <param>/<returns> и т.п. разворачиваются в читаемый вид).
|
||||
|
||||
Режимы:
|
||||
python scripts/fix_private_docs.py --preview [N] # показать N примеров (по умолчанию 10)
|
||||
python scripts/fix_private_docs.py --apply # применить
|
||||
python scripts/fix_private_docs.py --check # сколько блоков будет изменено
|
||||
"""
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
ROOT = r"C:\telbase\src"
|
||||
EXC = ("bin", "obj", "node_modules", ".git")
|
||||
DOC_RE = re.compile(r"^(\s*)///[ \t]?(.*)$")
|
||||
ACC_RE = re.compile(r"\b(public|protected|private|internal)\b")
|
||||
|
||||
|
||||
def demote(block_content):
|
||||
"""block_content: список строк после '///'. Возвращает список строк текста обычного комментария."""
|
||||
t = "\n".join(block_content)
|
||||
t = re.sub(r"<summary>\s*(.*?)\s*</summary>", r"\1", t, flags=re.S)
|
||||
t = re.sub(r"<remarks>\s*(.*?)\s*</remarks>", r"\1", t, flags=re.S)
|
||||
t = re.sub(r"<typeparamref\s+name=\"([^\"]+)\"\s*/?>", r"\1", t)
|
||||
t = re.sub(r"<paramref\s+name=\"([^\"]+)\"\s*/?>", r"\1", t)
|
||||
t = re.sub(r"<typeparam\s+name=\"([^\"]+)\"\s*>\s*(.*?)\s*</typeparam>", r"\1: \2", t, flags=re.S)
|
||||
t = re.sub(r"<param\s+name=\"([^\"]+)\"\s*>\s*(.*?)\s*</param>", r"\1: \2", t, flags=re.S)
|
||||
t = re.sub(r"<returns>\s*(.*?)\s*</returns>", r"Возвращает: \1", t, flags=re.S)
|
||||
t = re.sub(
|
||||
r"<exception\s+cref=\"([^\"]+)\"\s*>\s*(.*?)\s*</exception>",
|
||||
r"Исключение \1: \2",
|
||||
t,
|
||||
flags=re.S,
|
||||
)
|
||||
t = re.sub(r"<see\s+cref=\"([^\"]+)\"\s*/?>", r"\1", t)
|
||||
t = re.sub(r"<seealso\s+cref=\"[^\"]+\"\s*/?>", "", t)
|
||||
t = re.sub(r"<inheritdoc\s*/?>", "", t)
|
||||
t = re.sub(r"</?c>", "", t)
|
||||
t = re.sub(r"<[^>]+>", "", t)
|
||||
out = []
|
||||
for line in t.split("\n"):
|
||||
s = line.strip()
|
||||
if s:
|
||||
out.append(s)
|
||||
return out
|
||||
|
||||
|
||||
def iter_cs():
|
||||
for dp, dn, fn in os.walk(ROOT):
|
||||
dn[:] = [d for d in dn if d not in EXC]
|
||||
for f in fn:
|
||||
if f.endswith(".cs"):
|
||||
yield os.path.join(dp, f)
|
||||
|
||||
|
||||
def find_blocks(lines):
|
||||
"""Возвращает список (start, end, block_content, decl_index, decl)."""
|
||||
res = []
|
||||
i = 0
|
||||
while i < len(lines):
|
||||
m = DOC_RE.match(lines[i].rstrip("\r"))
|
||||
if not m:
|
||||
i += 1
|
||||
continue
|
||||
start = i
|
||||
block = []
|
||||
while i < len(lines):
|
||||
m2 = DOC_RE.match(lines[i].rstrip("\r"))
|
||||
if not m2:
|
||||
break
|
||||
block.append(m2.group(2))
|
||||
i += 1
|
||||
end = i # exclusive
|
||||
j = i
|
||||
decl = ""
|
||||
while j < len(lines):
|
||||
s = lines[j].strip()
|
||||
if s == "" or s.startswith("["):
|
||||
j += 1
|
||||
continue
|
||||
decl = s
|
||||
break
|
||||
if not decl:
|
||||
continue
|
||||
if not any("<summary>" in b or "</summary>" in b for b in block):
|
||||
continue
|
||||
am = ACC_RE.search(decl)
|
||||
if am and am.group(1) in ("private", "internal"):
|
||||
res.append((start, end, block, decl))
|
||||
return res
|
||||
|
||||
|
||||
def process_file(path, apply):
|
||||
raw = open(path, "rb").read().decode("utf-8")
|
||||
lines = raw.splitlines(keepends=True)
|
||||
plain = [l.rstrip("\r\n") for l in lines]
|
||||
endings = [l[len(l.rstrip("\r\n")):] for l in lines]
|
||||
blocks = find_blocks(plain)
|
||||
if not blocks:
|
||||
return 0, []
|
||||
changes = []
|
||||
for start, end, block, decl in blocks:
|
||||
indent = DOC_RE.match(plain[start]).group(1)
|
||||
comments = demote(block)
|
||||
new_lines = [indent + "//" + (" " + c if c else "") for c in comments]
|
||||
changes.append((start, end, new_lines, decl))
|
||||
# применяем с конца
|
||||
for start, end, new_lines, decl in reversed(changes):
|
||||
ending = endings[start] if endings[start] else (endings[end - 1] if end > start else "\n")
|
||||
replacement = [nl + ending for nl in new_lines]
|
||||
lines[start:end] = replacement
|
||||
if apply:
|
||||
open(path, "w", encoding="utf-8", newline="").write("".join(lines))
|
||||
return len(changes), [(b[0], b[3], demote(b[2])) for b in [(s, e, bl, d) for s, e, bl, d in blocks]]
|
||||
|
||||
|
||||
def main():
|
||||
if "--preview" in sys.argv:
|
||||
n = 10
|
||||
idx = sys.argv.index("--preview")
|
||||
if idx + 1 < len(sys.argv) and sys.argv[idx + 1].isdigit():
|
||||
n = int(sys.argv[idx + 1])
|
||||
shown = 0
|
||||
for path in iter_cs():
|
||||
raw = open(path, "rb").read().decode("utf-8")
|
||||
plain = [l.rstrip("\r\n") for l in raw.split("\n")]
|
||||
for start, end, block, decl in find_blocks(plain):
|
||||
print("FILE:", os.path.relpath(path, r"C:\telbase"), f"line {start + 1}")
|
||||
print(" DECL:", decl[:100])
|
||||
print(" BEFORE:")
|
||||
for b in plain[start:end]:
|
||||
print(" ", b)
|
||||
print(" AFTER:")
|
||||
for c in demote(block):
|
||||
print(" // " + c)
|
||||
print()
|
||||
shown += 1
|
||||
if shown >= n:
|
||||
return
|
||||
return
|
||||
apply = "--apply" in sys.argv
|
||||
total = 0
|
||||
files = 0
|
||||
for path in iter_cs():
|
||||
cnt, _ = process_file(path, apply)
|
||||
if cnt:
|
||||
files += 1
|
||||
total += cnt
|
||||
print(("APPLIED" if apply else "DRY-RUN"), "blocks:", total, "files:", files)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user