cleanup: trim helper parser commentary

This commit is contained in:
“Naeel”
2026-04-29 21:52:57 +04:00
parent 24841c5be5
commit 22d12ab070
3 changed files with 58 additions and 69 deletions
+27 -2
View File
@@ -549,8 +549,33 @@
Результат проверки:
- синтаксических ошибок в `v1/resources/instance_operation.cfc` не обнаружено
- синтаксических ошибок в `v1/resources/svc_operation_cfs_param_compute.cfc` не обнаружено
- `v1/resources/resource_realm_type_ls.cfc`
- `v1/resources/bookmark.cfc`
## Обновление: cleanup helper-парсера и API helper
Дата фиксации: 2026-04-29.
### Что планируется сделать
Следующий этап переносится на helper-слой:
- `v1/lib/rest_api_helper.cfc`
- `v1/lib/expression_parser.cfc`
Цель:
- убрать длинные блоки рассуждений и временные пояснения разработки
- удалить мёртвые закомментированные фрагменты и служебные следы отладки
- оставить только рабочую логику и короткие runtime-описания через `hint`, не меняя поведение методов
### Результат этапа
Выполнено:
- в `v1/lib/rest_api_helper.cfc` убраны служебные и устаревшие комментарии внутри helper-методов
- в `v1/lib/expression_parser.cfc` удалены длинные блоки рассуждений о контексте, временные заметки и закомментированные debug-хвосты
### Проверка
Результат проверки:
- синтаксических ошибок в `v1/lib/rest_api_helper.cfc` не обнаружено
- синтаксических ошибок в `v1/lib/expression_parser.cfc` не обнаружено
### Следующий мини-этап
+19 -52
View File
@@ -1,5 +1,4 @@
<cfcomponent>
<!--- разбирает и вычисляет выражения из вложенных функций для зависимых CFS параметров --->
<cfset this.args = []/>
<cfproperty name="entity" type="string"/>
@@ -12,25 +11,7 @@
<cffunction name="eval" returntype="any" access="public">
<cfargument name="expression" type="string"/>
<cfargument name="context" type="any"/><!--- {component,key,params} --->
<!--- Если параметр сохранен, то вся нужная информация может быть получена по его ключу. Просто и изящно, но.
Но если параметр, операция, инстанс не сохранены в базе - то нам придется предоставить с контекстом все, что может понадобиться
При этом контекст кажется вывернутым наизнанку: не инстанс / содержащий операции /содержащие параметры, а параметр, что-то знающий про операцию и инстанс
А бывают нужны
- параметры-зависимости (мы их специально перечисляем в отдельном поле)
- псевдопараметр resourceRealm, может наследоваться от предка (предок определен как раз параметром, инстансу существовать не обязательно) (нужно ли декларировать параметр-ссылку на предка в зависимостях?)
- стейт (есть только у созданного инстанса и вычисляется по ключу instance_uid)
Еще имя компонента
Например, контекст может содержать инстанс компонента, имя компонента и дополнительные параметры
По имени компонента мы можем сразу создать пустой (неинициализированный инстанс)
Ну и как ему передать параметры? У инстанса есть массив параметров. Точнее, map<any> (удобнее адресоваться именами). Так и передать. А дальше ресолвить по мере сил (это работа самого компонента)
Контекст сам выглядит компонентом, но поскольку его использование кажется локальным, мы можем взять произвольную структуру
Если компонент-параметр инстанциирован, мы можем получить из БД значения всех соседних параметров.
Но даже если компонент инстанциирован, непосредственно переданные значения параметров должны иметь приоритет перед сохраненными (мы сначала редактируем зависимые параметры, и только потом одним чохом записываем коллекцию параметров в БД
Логично использовать ленивую инициализацию
В этом рассуждении я упустил такой момент. Конкретно для параметра (хотя я хотел абстрагироваться от сущности) есть родительские сущности Операция и Инстанс,
и какая-то из них может быть задана. Это не так же точно, как собственный ключ, но несет некоторую полезную информацию. Может быть, передавать массив или map ключей?
--->
<cfargument name="context" type="any"/>
<cfset var args=[]/>
<cfset parse(args, tokenize(arguments.expression),0)/>
@@ -45,17 +26,6 @@
<cfreturn params/>
</cffunction>
<!---
expression parse-evaluate
для навигации по стейтам и конфигурациям платформ
*** размещаем здесь временно. скорее всего, парсер надо оформить компонентом
Отдельный вопрос, как адресоваться к аргументам. Или парсер может возвращать функцию, которая будет работать в адресном пространстве параметра? Тогда ему никакой доступ не нужен.
Было бы интересно сериализовывать скомпилированное выражение
Но сейчас все вычисления происходят в самом парсере
*** сначала мы хотим отработать генерацию зависимых списков в deck-tool
*** нужно обрабатывать исключения разбора
--->
<cffunction name="tokenize" returntype="array" access="private">
<cfargument name="expression" type="string"/>
@@ -80,20 +50,21 @@ expression parse-evaluate
<cfreturn "("/>
<cfelseif token EQ ")">
<cfreturn ")"/>
<cfelseif left(token,1) EQ '"'><!--- не вдаваясь в лишние подробности... внятнее было парсить строку посимвольно --->
<cfelseif left(token,1) EQ '"'>
<cfreturn "string"/>
<cfelseif find(".",token)>
<cfreturn "variable"/>
<cfelse>
<cfreturn "function"/><!--- будем проще: если дальше не найдем аргументов - бросим исключение --->
<cfreturn "function"/>
</cfif>
</cffunction>
<cffunction name="parse" returntype="numeric" access="private"><!--- returns last token position --->
<cfargument name="args" type="array"/><!--- puts here parsed tree with nested functions --->
<cffunction name="parse" returntype="numeric" access="private">
<cfargument name="args" type="array"/>
<cfargument name="tokens" type="array"/>
<cfargument name="positionBefore" type="numeric"/><!--- before first processed token, initially 0 --->
<cfargument name="positionBefore" type="numeric"/>
<cfset var i = arguments.positionBefore/>
<cfloop condition="++i LE arrayLen(arguments.tokens)">
@@ -110,29 +81,28 @@ expression parse-evaluate
<cfif i GE arrayLen(arguments.tokens)>
<cfthrow message="unexpected end of expression"/>
</cfif>
<cfif #tokenType(arguments.tokens[++i])# NEQ "("><!--- skip opening parenthesis ---><!--- *** possible out of range --->
<cfif #tokenType(arguments.tokens[++i])# NEQ "(">
<cfthrow message="function syntax incorrect" detail="function #arguments.tokens[i-1]#, token='#arguments.tokens[i]#' (#arrayToList(tokens,' ')#"/>
</cfif>
<cfset i = parse(f.args, arguments.tokens, i)/>
<cfset arrayAppend(arguments.args,f)/>
</cfcase>
<cfcase value=")">
<cfreturn i/><!--- returns last token position --->
<cfreturn i/>
</cfcase>
</cfswitch>
</cfloop>
</cffunction>
<cffunction name="parseForParams" returntype="numeric" access="private"><!--- returns last token position --->
<cfargument name="args" type="array"/><!--- puts here parsed params --->
<cffunction name="parseForParams" returntype="numeric" access="private">
<cfargument name="args" type="array"/>
<cfargument name="tokens" type="array"/>
<cfargument name="positionBefore" type="numeric"/><!--- before first processed token, initially 0 --->
<cfargument name="positionBefore" type="numeric"/>
<cfset var i = arguments.positionBefore/>
<cfloop condition="++i LE arrayLen(arguments.tokens)">
<cfswitch expression=#tokenType(arguments.tokens[i])#>
<cfcase value="string">
<!--- skip ---><!--- <cfset arrayAppend(arguments.args,mid(arguments.tokens[i],2,len(arguments.tokens[i])-2))/>--->
</cfcase>
<cfcase value="variable">
<cfset arrayAppend( arguments.args, tokens[i] )/>
@@ -142,27 +112,26 @@ expression parse-evaluate
<cfif i GE arrayLen(arguments.tokens)>
<cfthrow message="unexpected end of expression"/>
</cfif>
<cfif #tokenType(arguments.tokens[++i])# NEQ "("><!--- skip opening parenthesis ---><!--- *** possible out of range --->
<cfif #tokenType(arguments.tokens[++i])# NEQ "(">
<cfthrow message="function syntax incorrect" detail="function #arguments.tokens[i-1]#, token='#arguments.tokens[i]#' (#arrayToList(tokens,' ')#"/>
</cfif>
<cfset i = parseForParams(f.args, arguments.tokens, i)/>
<!--- <cfset arrayAppend(arguments.args,f)/> --->
</cfcase>
<cfcase value=")">
<cfreturn i/><!--- returns last token position --->
<cfreturn i/>
</cfcase>
</cfswitch>
</cfloop>
</cffunction>
<cffunction name="computeExpression" returntype="any" access="private"><!--- вычисление выражения снаружи внутрь --->
<cffunction name="computeExpression" returntype="any" access="private">
<cfargument name="function" type="string"/>
<cfargument name="args" type="array"/>
<cfargument name="context" type="any"/>
<cfloop index="i" from=1 to=#arrayLen(arguments.args)#><!--- тонкость: цикл item по массиву копирует элемент, а нам нужно его менять по ссылке --->
<cfif isStruct(arguments.args[i]) AND structKeyExists(arguments.args[i],"function")> <!--- и все равно это ненадежный способ отличать функцию от простого значения --->
<cfloop index="i" from=1 to=#arrayLen(arguments.args)#>
<cfif isStruct(arguments.args[i]) AND structKeyExists(arguments.args[i],"function")>
<cfset arguments.args[i] = computeExpression(
arguments.args[i].function,
arguments.args[i].args,
@@ -174,13 +143,11 @@ expression parse-evaluate
</cffunction>
<cffunction name="executeFunction" returntype="any" access="private"><!--- эта функция обращается к прикладным функциям, должна их видеть --->
<cfargument name="functionName"/><!--- а ссылку на функцию передать не получится? (замыкание даже наверно не нужно) --->
<cffunction name="executeFunction" returntype="any" access="private">
<cfargument name="functionName"/>
<cfargument name="args" type="array"/>
<cfargument name="context" type="any"/>
<!--- <cfdump var=#arguments#/> --->
<cfset var obj = createObject("component", arguments.context.component).init(arguments.context.keys, arguments.context.params)/>
<!--- <cfdump var=#obj# abort=true/> --->
<cfreturn invoke(obj, functionName, args)/>
</cffunction>
+11 -14
View File
@@ -36,7 +36,7 @@
<cfargument name="struct" type="struct" required="true" />
<cfargument name="key" type="string" required="true" />
<cfargument name="fieldMap" type="struct" required="true" /><!--- используется только список и опциональный атрибут formatter --->
<cfargument name="fieldMap" type="struct" required="true" />
<cfargument name="query" type="query" required="true" />
<cfargument name="fieldNameDecorator" type="function" required="false" default=#passThrough#/>
@@ -87,7 +87,7 @@
<cfset var urlParamName=snake2camel(lCase(local.item))/>
<cfif structKeyExists(urlParams,urlParamName)>
<cfloop array=#urlParams[urlParamName]# item="local.rawValue"><!--- Если параметр встречается в URL несколько раз, его значения образуют список через запятую. --->
<cfloop array=#urlParams[urlParamName]# item="local.rawValue">
<cfset var operator="EQ"/>
<cfset var value=#local.rawValue#/>
<cfif listLen(local.rawValue,":") GT 1>
@@ -95,7 +95,7 @@
<cfset var value=listGetAt(local.rawValue,2,":")/>
</cfif>
<cfif !isValidX(ARGUMENTS.params[local.item].type,value)>
<cfthrow type="invalidParamValue" message="Filter parameter #urlParamName# value is not a valid #ARGUMENTS.params[local.item].type#"/><!---не выводим значение, чтобы исключить XSS--->
<cfthrow type="invalidParamValue" message="Filter parameter #urlParamName# value is not a valid #ARGUMENTS.params[local.item].type#"/>
</cfif>
<cfif structKeyExists(ARGUMENTS.params[local.item], "expression") AND len(ARGUMENTS.params[local.item].expression)>
@@ -129,7 +129,7 @@
returntype="array"
output="true"
hint="Разбирает и собирает параметры фильтра; операторы задаются в filter_build">
<cfargument name="params" type="struct" required="true" /><!--- имена полей и колонок в snake_case --->
<cfargument name="params" type="struct" required="true" />
<cfset var local = {}/>
<cfset var out = []/>
@@ -139,7 +139,7 @@
<cfset var urlParamName=snake2camel(lCase(local.item))/>
<cfif structKeyExists(URL,urlParamName)>
<cfloop list=#URL[urlParamName]# item="local.rawValue"><!--- Если параметр встречается в URL несколько раз, его значения образуют список через запятую. --->
<cfloop list=#URL[urlParamName]# item="local.rawValue">
<cfset var operator="EQ"/>
<cfset var value=#local.rawValue#/>
<cfif listLen(local.rawValue,":") GT 1>
@@ -147,7 +147,7 @@
<cfset var value=listGetAt(local.rawValue,2,":")/>
</cfif>
<cfif !isValidX(ARGUMENTS.params[local.item].type,value)>
<cfthrow type="invalidParamValue" message="Filter parameter #urlParamName# value is not a valid #ARGUMENTS.params[local.item].type#"/><!---не выводим значение, чтобы исключить XSS--->
<cfthrow type="invalidParamValue" message="Filter parameter #urlParamName# value is not a valid #ARGUMENTS.params[local.item].type#"/>
</cfif>
<cfif structKeyExists(ARGUMENTS.params[local.item], "expression") AND len(ARGUMENTS.params[local.item].expression)>
@@ -181,7 +181,7 @@
<cffunction name="parseOrderBy"
returntype="struct"
output="false"
hint="Разбирает и собирает параметр сортировки"><!--- Устаревший метод --->
hint="Разбирает и собирает параметр сортировки">
<cfargument name="params" type="struct" required="true" />
<cfargument name="orderBy" type="string" required="true" />
@@ -195,7 +195,7 @@
<cfcase value="ASC"><cfset var asc=true/></cfcase>
<cfcase value="DESC"><cfset var asc=false/></cfcase>
<cfdefaultcase>
<cfthrow type="InvalidParamValue" message="Invalid orderBy format" detail="orderBy suffix should be '.asc' or '.desc'" /><!--- Суффикс не возвращается пользователю, чтобы не расширять XSS-поверхность. --->
<cfthrow type="InvalidParamValue" message="Invalid orderBy format" detail="orderBy suffix should be '.asc' or '.desc'" />
</cfdefaultcase>
</cfswitch>
<cfelse>
@@ -229,7 +229,7 @@
<cfcase value="ASC"><cfset var asc=true/></cfcase>
<cfcase value="DESC"><cfset var asc=false/></cfcase>
<cfdefaultcase>
<cfthrow type="InvalidParamValue" message="Invalid orderBy format" detail="orderBy suffix should be '.asc' or '.desc'" /><!--- Суффикс не возвращается пользователю, чтобы не расширять XSS-поверхность. --->
<cfthrow type="InvalidParamValue" message="Invalid orderBy format" detail="orderBy suffix should be '.asc' or '.desc'" />
</cfdefaultcase>
</cfswitch>
<cfelse>
@@ -244,7 +244,6 @@
</cfloop>
<cfreturn out/>
</cffunction>
<!--- Больше не используется --->
<cffunction name="query4json" access="public" returntype="any" output="false"
hint="Преобразует query в массив структур. Имена ключей приводятся к нижнему регистру, пустые поля считаются null">
@@ -258,7 +257,7 @@
<cfset out[i]=structNew()/>
<cfloop list=#ARGUMENTS.Query.ColumnList# index="local.col">
<cfset var value=ARGUMENTS.Query[local.col][currentRow]/>
<cfif isEmpty(value)><!---*** некорректно, но просто, пустые строки превращает в нулл--->
<cfif isEmpty(value)>
<cfset out[i][local.col]=javacast('null','')/>
<cfelse>
<cfset out[i][local.col]=ARGUMENTS.Query[local.col][currentRow]/>
@@ -369,7 +368,6 @@
</cfif>
</cffunction>
<!--- returns false if the key does not exist and throws exception on invalid format--->
<cffunction name="keyExistsAndValid" access="public" returntype="boolean">
<cfargument name="struct" type="struct" required=true/>
<cfargument name="key" type="string" required=true/>
@@ -399,7 +397,6 @@
</cfif>
</cffunction>
<!--- returns false if the key does not exist or has invalid format--->
<cffunction name="keyExistsAndValidGraceful" access="public" returntype="boolean">
<cfargument name="struct" type="struct" required=true/>
<cfargument name="key" type="string" required=true/>
@@ -408,7 +405,7 @@
<cftry>
<cfreturn keyExistsAndValid(ARGUMENTS.struct, ARGUMENTS.key, ARGUMENTS.type, ARGUMENTS.maxLength)/>
<cfcatch type="ANY"><!---<cfrethrow/>---></cfcatch>
<cfcatch type="ANY"></cfcatch>
</cftry>
<cfreturn false/>
</cffunction>