67 lines
3.5 KiB
Python
67 lines
3.5 KiB
Python
#!/usr/bin/env python3
|
|
"""모듈 규칙 검사: (1) 파일 700줄 이하 (400줄 넘으면 경고) (2) 모듈 간 import 방향."""
|
|
import os, re, sys, pathlib
|
|
|
|
MAX, WARN = 700, 400
|
|
# 허용 방향: 왼쪽 모듈은 오른쪽 모듈만 import 할 수 있다.
|
|
ALLOW = {
|
|
"core": set(),
|
|
"platform": set(),
|
|
"platform_android": {"core", "platform", "storage"},
|
|
"storage": {"platform"},
|
|
"keys": {"core", "platform"},
|
|
"sharing": {"storage"},
|
|
"sync": {"core", "storage"},
|
|
"transport": {"core"},
|
|
"discovery": {"platform"},
|
|
"inference": {"core"},
|
|
"layout": {"core"},
|
|
"visibility": {"core"},
|
|
"kinship": set(),
|
|
"groups": {"core"},
|
|
"work": set(),
|
|
"circles": set(),
|
|
"events": set(),
|
|
"app": {"core", "platform", "storage", "sharing", "sync", "discovery", "inference", "layout", "visibility", "kinship", "events", "groups", "work", "circles"},
|
|
"ui": {"app", "core", "platform", "storage", "discovery", "inference", "layout", "visibility", "kinship", "events", "groups", "work", "circles"},
|
|
}
|
|
# 모듈 입구가 둘 이상인 경우: 입구 파일이 모듈 이름.dart 외에 허용되는 것들.
|
|
EXTRA_BARRELS = {"platform": {"platform_ui.dart"}, "storage": {"storage_sqlite.dart"}}
|
|
# 모듈 폴더 밖(main.dart, composition/)은 조립 코드라서 어느 모듈 입구든 쓸 수 있다.
|
|
# 플랫폼마다 다른 플러그인은 platform_android 에서만 쓴다 (나중에 iOS 등을 붙이기 쉽게).
|
|
PLATFORM_ONLY = ("flutter_secure_storage", "sensors_plus", "nsd", "mobile_scanner", "sqflite_sqlcipher", "geolocator", "call_log", "flutter_contacts", "url_launcher", "flutter_local_notifications", "timezone")
|
|
root = pathlib.Path(__file__).resolve().parent.parent / "lib"
|
|
bad = 0
|
|
for f in sorted(root.rglob("*.dart")):
|
|
n = len(f.read_text(encoding="utf-8").splitlines())
|
|
rel = f.relative_to(root)
|
|
if n > MAX:
|
|
print(f"오류 {rel}: {n}줄 (최대 {MAX})"); bad += 1
|
|
elif n > WARN:
|
|
print(f"경고 {rel}: {n}줄 ({WARN}줄 넘음)")
|
|
parts = rel.parts
|
|
in_platform = len(parts) >= 2 and parts[1].startswith("platform_")
|
|
for m in re.finditer(r"import\s+'package:(\w+)/", f.read_text(encoding="utf-8")):
|
|
if m.group(1) in PLATFORM_ONLY and not in_platform:
|
|
print(f"오류 {rel}: {m.group(1)} 는 platform_* 모듈에서만 import"); bad += 1
|
|
if len(parts) >= 3 and parts[0] == "modules":
|
|
me = parts[1]
|
|
for m in re.finditer(r"import\s+'([^']+)'", f.read_text(encoding="utf-8")):
|
|
p = m.group(1)
|
|
if p.startswith("package:friendly_map/"):
|
|
target = pathlib.PurePosixPath(p[len("package:friendly_map/"):])
|
|
elif p.startswith("."):
|
|
target = pathlib.PurePosixPath(
|
|
os.path.normpath(os.path.join(os.path.dirname(rel.as_posix()), p)).replace(os.sep, "/"))
|
|
else:
|
|
continue
|
|
tp = target.parts
|
|
if len(tp) >= 3 and tp[0] == "modules" and tp[1] != me:
|
|
other = tp[1]
|
|
if other not in ALLOW.get(me, set()):
|
|
print(f"오류 {rel}: {me} 모듈은 {other} 모듈을 쓸 수 없음"); bad += 1
|
|
elif target.as_posix() not in {f"modules/{other}/{other}.dart", *(f"modules/{other}/{x}" for x in EXTRA_BARRELS.get(other, ()))}:
|
|
print(f"오류 {rel}: {other} 모듈은 {other}.dart 로만 import"); bad += 1
|
|
print("통과" if not bad else f"규칙 위반 {bad}건")
|
|
sys.exit(1 if bad else 0)
|