feat(inlayhints): кликабельные LabelPart для хинтов вызова метода#4111
Conversation
Подсказки имён параметров для вызовов source-defined методов теперь рендерятся не голой строкой, а единственной частью InlayHintLabelPart со ссылкой (location) на объявление соответствующего параметра в сигнатуре вызываемого метода — клик по подсказке выполняет переход к объявлению параметра. Учитывается inlayHint.resolveSupport клиента: если клиент объявил отложенное разрешение свойства label.location, ссылка строится лениво на inlayHint/resolve (в data хинта кладутся координаты объявления параметра), иначе проставляется жадно. Флаг поддержки кэшируется на LanguageServerInitializeRequestReceivedEvent, как и у других провайдеров. Платформенные методы не имеют исходного расположения, поэтому их хинты остаются голыми строками без ссылок. Хинты типа переменной также без ссылок — в 1С нет понятия определения типа. Co-Authored-By: Claude Fable 5 <[email protected]>
|
Warning Review limit reached
More reviews will be available in 12 minutes and 53 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (9)
📝 WalkthroughWalkthrough
ChangesLazy inlayHint/resolve for source-defined method calls
Sequence Diagram(s)sequenceDiagram
participant Client
participant InlayHintProvider
participant SourceDefinedMethodCallInlayHintSupplier
participant MethodCallInlayHintData
Client->>InlayHintProvider: textDocument/inlayHint request
InlayHintProvider->>SourceDefinedMethodCallInlayHintSupplier: getInlayHints(documentContext)
alt labelLocationResolveSupport = false
SourceDefinedMethodCallInlayHintSupplier->>SourceDefinedMethodCallInlayHintSupplier: setLabelAndPadding → attach Location to InlayHintLabelPart
SourceDefinedMethodCallInlayHintSupplier-->>InlayHintProvider: InlayHint (label.location set, data=null)
else labelLocationResolveSupport = true
SourceDefinedMethodCallInlayHintSupplier->>MethodCallInlayHintData: embed targetUri + startLine/startChar/endLine/endChar
SourceDefinedMethodCallInlayHintSupplier-->>InlayHintProvider: InlayHint (label.location unset, data=MethodCallInlayHintData)
end
InlayHintProvider-->>Client: InlayHint list
opt Client resolves hint
Client->>InlayHintProvider: inlayHint/resolve
InlayHintProvider->>SourceDefinedMethodCallInlayHintSupplier: resolve(documentContext, unresolved, data)
SourceDefinedMethodCallInlayHintSupplier->>MethodCallInlayHintData: read range coordinates
SourceDefinedMethodCallInlayHintSupplier-->>InlayHintProvider: InlayHint (label.location set, data=null)
InlayHintProvider-->>Client: resolved InlayHint
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
У оскрипта вполне есть пользовательские типы, как классы, так и модули. Для менеджеров объектов можно показывать ссылку на символ модуля. Аналогично для общих модулей. |
Хинт выведенного типа переменной теперь рендерится частью метки InlayHintLabelPart: когда тип объявлен в исходниках (общий модуль, модуль менеджера объекта конфигурации, класс/модуль OneScript), к части привязывается ссылка на объявление — клик выполняет переход к модулю/классу. Платформенные и примитивные типы объявляющего символа не имеют — для них метка остаётся без ссылки. Маппинг тип -> объявляющий символ вынесен в TypeService.definingSymbol: USER-типы берут объявление из UserType.getDeclaration(), CONFIGURATION-типы (общие модули и менеджеры объектов) находят документ-модуль обратным индексом GlobalScopeProvider.moduleUriByType и берут его getSymbolTree().getModule(). Построение ссылки учитывает inlayHint.resolveSupport клиента так же, как хинты вызова метода: при поддержке label.location ссылка откладывается на inlayHint/resolve (координаты в data), иначе проставляется жадно. Co-Authored-By: Claude Fable 5 <[email protected]>
|
Учёл. Расширил: типовой хинт теперь кликабелен, когда тип резолвится в исходный символ —
Единый резолвер |
|
Вопрос к обсуждению: можно ли обойтись без нового обратного индекса
Предложение: общие/OScript — на существующие API; менеджеры — добавить |
| if (labelLocationResolveSupport) { | ||
| // Ссылка строится лениво на inlayHint/resolve — в data кладём координаты | ||
| // объявления параметра, остальное (value/position/kind) жадно. | ||
| inlayHint.setData(new MethodCallInlayHintData( |
There was a problem hiding this comment.
В этом нет смысла в данном контексте. Если location УЖЕ рассчитан, его надо просто вернуть, а не отправлять dto на 6 параметров
There was a problem hiding this comment.
Согласен — раз location уже посчитан, слать DTO на резолв смысла нет. Теперь ссылка части метки проставляется жадно прямо при построении хинта (и для вызовов методов, и для ссылки на объявление типа). DTO MethodCallInlayHintData удалён, у хинта вызова метода вообще пропала надобность в data/resolve. VariableTypeInlayHintData ужат до полей ленивого tooltip (uri/id/typeName) — tooltip как тяжёлое поле остаётся за inlayHint/resolve, как в #4100. (372be70)
| * объявляющего символа в исходниках (платформенный/примитивный тип) или | ||
| * документ-модуль больше не загружен. | ||
| */ | ||
| public Optional<SourceDefinedSymbol> definingSymbol(TypeRef typeRef, DocumentContext requestingContext) { |
There was a problem hiding this comment.
Кажется, здесь полностью опущен сценарий, когда тип задаётся ссылкой См. с указанием имени функции
There was a problem hiding this comment.
Разобрался — это не пропущенная ветка definingSymbol, а отсутствие самого понятия «тип задан ссылкой См. Функция» в модели типов.
Что есть сейчас:
См.-ссылка живёт только в модели описаний парсера:HyperlinkTypeDescription/TypeDescription.Variant.HYPERLINK(bsl-parser), несёт строку ссылки.- В модель типов (
TypeKind/TypeRef) она НЕ попадает.SymbolTypeIndex.resolveTypeDescription(SymbolTypeIndex.java:247-253) дляHYPERLINKотдаётTypeSet.EMPTY, а потребители (SymbolTypeIndex.resolveHyperlink:110,ExpressionTypeInferencer.parameterHyperlinkTypes:1304) разворачивают ссылку в тип возвращаемого значения целевой функции и складывают обычныеTypeRef. Идентичность самой функции при этом теряется. TypeRef— это пара(kind, qualifiedName)(TypeRef.java:47), провенанса «откуда взялся тип» в нём нет.
Поэтому в definingSymbol приходит уже обычный TypeRef разрешённого типа-значения (его объявление корректно отдают ветки USER/CONFIGURATION) — отдельной формы TypeRef/TypeKind для «тип = См. Функция» нет, и добавлять для неё ветку некуда. А в VariableTypeInlayHintSupplier цепочка вообще схлопывается до inferredType.qualifiedName() (:148-149, :180-181), так что провенанс теряется ещё и на границе ленивого resolve.
Сделать хинт выведенного типа ссылающимся на саму функцию из См. (а не на объявление разрешённого типа-значения) — это не ветка в definingSymbol, а отдельная работа по выводу типов: нужно протащить провенанс ссылки (функция-источник) через весь конвейер инференса и через границу inlayHint/resolve.
Предлагаю вынести это отдельной задачей по type-inference. Завести issue и не блокировать этот PR? Или видишь более лёгкий путь, который я упустил?
…енивого резолва Объявление параметра/типа уже разрешено на этапе построения хинта, поэтому ссылка части метки (InlayHintLabelPart.location) проставляется жадно, без отложенного inlayHint/resolve. - SourceDefinedMethodCallInlayHintSupplier: убран ленивый путь location и гейтинг по inlayHint.resolveSupport(label.location); хинт вызова метода не несёт тяжёлых отложенных полей, поэтому переведён на DefaultInlayHintData и больше не кладёт data/не переопределяет resolve. Удалён неиспользуемый DTO MethodCallInlayHintData. - VariableTypeInlayHintData: оставлены только поля для ленивого tooltip (uri, id, typeName); убраны targetUri, координаты и hasLocation/NO_LOCATION. - VariableTypeInlayHintSupplier: location проставляется жадно, tooltip по-прежнему дорассчитывается лениво через inlayHint/resolve (как в #4100). - Тесты: убраны проверки ленивого round-trip'а location, оставлены жадные проверки location и ленивая проверка tooltip. Co-Authored-By: Claude Fable 5 <[email protected]>
|




Что сделано
Подсказки имён параметров для вызовов source-defined методов
(
SourceDefinedMethodCallInlayHintSupplier) теперь рендерятся не голойстрокой, а единственной частью
InlayHintLabelPartсо ссылкой(
location) на объявление соответствующего параметра в сигнатуревызываемого метода. Клик по подсказке выполняет переход к объявлению
параметра.
Откуда берётся location параметра
Сапплаер уже резолвит вызываемый метод (через
ReferenceIndex) радипоказа имён его параметров. Эта же резолюция переиспользуется для ссылки:
URI берётся из
MethodSymbol.getOwner().getUri(), диапазон — изParameterDefinition.getRange()соответствующего параметра.resolveSupport
Учитывается клиентская возможность
inlayHint.resolveSupport:label.location—ссылка строится лениво на
inlayHint/resolve(вInlayHint.dataкладётся новый DTO
MethodCallInlayHintDataс координатами объявленияпараметра; на резолве из них собирается
Locationи проставляетсяединственной части метки);
Флаг
labelLocationResolveSupportкэшируется один раз на@EventListener(LanguageServerInitializeRequestReceivedEvent.class)—как у
CompletionProvider/SignatureHelpProvider, не на каждый запрос.Резолв диспатчится существующей инфраструктурой
InlayHintProvider(
getInlayHintDataClass()→MethodCallInlayHintData, авторегистрацияjackson-сабтайпа по id сапплаера).
Явный scope без type-link
PlatformMethodCallInlayHintSupplier) неимеют исходного расположения — их хинты остаются голыми строками без
ссылок, никаких фабрикованных location.
VariableTypeInlayHintSupplier) оставленыкак есть: в 1С нет понятия «определение типа», ссылки на типы в проекте
отклонены ранее. Кликабельность добавлена только хинтам вызова метода,
ведущим на реальные исходные расположения.
Тесты
путь, без resolveSupport);
inlayHint/resolve(round-trip данных),dataочищается;StringсталаList<InlayHintLabelPart>с сохранением видимого текста.Все
*InlayHint*тесты зелёные,compileJava/compileTestJava—BUILD SUCCESSFUL.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Refactor
Tests