Files
Sun1602/Tools/ScriptChecker/classes.rb
T
2022-10-26 12:25:11 +08:00

128 lines
4.0 KiB
Ruby

# 스크립트 기반 클래스
# 각 스크립트별 규칙 검증를 위한 하위 클래스들은 이 기반 클래스에서 파생
class Script
attr_accessor :name, :path, :checker
def initialize(required, name, path)
@required = required # 필수 스크립트인가
@name = name # 스크립트 이름
@path = path # 디렉토리 기준 파일 경로
@checker = nil
@head_array = [] # 컬럼 헤더 문자열 배열
@head_hash = {} # 컬럼 헤더 => 컬럼 인덱스 해시
@line_num = 0 # 현재 처리 중인 행 번호
@should_check_space = true
end
def check(dir)
unless File.exist?(File.join(dir, path))
if @required
puts "[ERROR] #{@name} : 파일을 찾을 수 없음"
set_error
else
puts "[WARNING] #{@name} : 파일을 찾을 수 없음"
end
return
end
@line_num = 0
got_head_line = false
IO.foreach(File.join(dir, path)) do |line|
@line_num += 1
s = line.lstrip # 선행 공백 삭제
next if s[0..1] == '//' # 주석 라인은 건너뛴다
tokens = s.split("\t") # 각 컬럼은 탭("\t")으로 구분
next unless tokens
if @should_check_space
# 탭("\t")으로 분리된 토큰 중 공백 문자(" ")가 포함된 것이 있는가
# 토큰 중간의 공백 문자는 파서 오류를 유발한다
col_num = Script.has_inner_space(tokens)
if col_num >= 0
puts "[ERROR] #{@name} : 잘못된 공백 문자 (line #{@line_num} col #{col_num})"
set_error
next
end
end
unless got_head_line
@head_array = tokens # 주석이 아닌 첫 라인은 컬럼 헤더여야 한다
col_index = -1
@head_array.each do |col_name|
col_index += 1
if col_name.strip != '' and @head_hash.has_key?(col_name)
puts "[ERROR] Duplicated column header '#{col_name}' (line #{@line_num})"
set_error
next
end
@head_hash[col_name] = col_index
end
got_head_line = true
else
# 현재 포맷에서 내용 컬럼 수 체크 의미 없음
# 스크립트별 상세 검증
check_rule(tokens)
end
end
end
def check_rule(columns)
# 모든 스크립트에 공통되는 사항이 아니라면 하위 클래스에서 구현
end
def col_index(col_name)
@head_hash[col_name]
end
def Script.has_inner_space(tokens)
col_num = 0
tokens.each do |token|
col_num += 1
stripped = token.strip
break if stripped.include?('//') # '//' 이후로 검사하지 않음
next unless stripped.include?(' ')
return col_num
end
return -1
end
end
class ScriptChecker
attr_accessor :dir, :item_table
def initialize
@script_array = []
@script_hash = {}
@dir = '.'
@item_table = {}
end
# 검증 대상 스크립트 추가
def add(required, name, path = name)
if @script_hash.has_key?(name)
if script_hash[name].path != path
puts "[ERROR] Duplicated script name '#{name}'"
set_error
end
return
end
script = ScriptFactory.create(required, name, path)
script.checker = self
@script_array.push(script)
@script_hash[name] = script
end
# 검증 대상 스크립트 갯수 얻기
def num_scripts
@script_array.length
end
# 주어진 이름에 맵핑된 스크립트 객체 얻기
def get_script(name)
@script_hash[name]
end
# 검증 실행
def run
@script_array.each do |script|
begin
puts "Checking #{script.name}"
script.check(@dir)
rescue Exception => e
puts '[ERROR] ' + e
set_error
end
end
end
end