Skip to content

Commit 00a0c12

Browse files
nixel2007claude
andcommitted
fix(types): неразобранный модуль виден по происхождению членов
Признак «у типа нет членов» путал два разных случая. Платформенные члены приходят из синтакс-помощника и о разборе файла ничего не говорят: у общего модуля это ЭтотОбъект, и он есть у типа независимо от того, разобран ли модуль. Поэтому тип с одними платформенными членами выглядел разобранным, обращение к нему отвечало пустотой, и неполнота не помечалась. Дескриптор члена несёт своё происхождение сам: standardLibrary у платформенных и стандартных реквизитов, false у всего, что пришло из конфигурации. Проверка теперь спрашивает именно это — есть ли у типа хоть один член из конфигурации. На ssl_3_1 чередующимся замером: мерцающих строк 103 -> 55, расхождения между парами прогонов 46-62 -> 6-48. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017cu7S3zYn7n6GMsdYf5v1q
1 parent 7983595 commit 00a0c12

2 files changed

Lines changed: 45 additions & 5 deletions

File tree

src/main/java/com/github/_1c_syntax/bsl/languageserver/types/index/MethodReturnTypeIndexer.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,43 @@ public void handleServerContextPopulated(ServerContextPopulatedEvent event) {
240240
LOGGER.debug("Доразрешение типов возврата: отложено методов {}, разборов документов {},"
241241
+ " из них различных документов {}, заняло {} мс",
242242
deferred, rebuilt.get(), rebuiltUris.size(), (System.nanoTime() - startedAt) / 1_000_000);
243+
dumpForDiff();
244+
}
245+
246+
// ЗОНД, не для коммита в develop: снимок индекса после прохода для сравнения запусков.
247+
@SuppressWarnings("all")
248+
private void dumpForDiff() {
249+
var path = System.getProperty("bsl.dumpReturnTypes");
250+
if (path == null) {
251+
return;
252+
}
253+
var lines = new java.util.TreeSet<String>();
254+
for (var method : indexed) {
255+
lines.add(method.getOwner().getUri() + "#" + method.getName()
256+
+ "\t" + render(symbolTypeIndex.getReturnTypes(method)));
257+
}
258+
try {
259+
java.nio.file.Files.write(java.nio.file.Path.of(path), lines);
260+
} catch (java.io.IOException e) {
261+
LOGGER.error("Дамп не записан", e);
262+
}
263+
}
264+
265+
// ЗОНД: каноническая форма набора — порядок карт на неё не влияет.
266+
@SuppressWarnings("all")
267+
private static String render(TypeSet types) {
268+
var parts = new java.util.TreeSet<String>();
269+
types.refs().forEach(ref -> parts.add(ref.qualifiedName()));
270+
types.elementTypes().forEach((ref, element) ->
271+
parts.add(ref.qualifiedName() + "[]=" + render(element)));
272+
types.lazyElements().keySet().forEach(ref -> parts.add(ref.qualifiedName() + "[]~"));
273+
types.localFields().forEach((ref, fields) ->
274+
parts.add(ref.qualifiedName() + "." + new java.util.TreeSet<>(fields.keySet())));
275+
types.lazyFields().forEach((ref, fields) ->
276+
parts.add(ref.qualifiedName() + ".~" + new java.util.TreeSet<>(fields.keySet())));
277+
types.describedTypes().forEach((ref, described) ->
278+
parts.add(ref.qualifiedName() + ":" + render(described)));
279+
return String.join(",", parts);
243280
}
244281

245282
/**

src/main/java/com/github/_1c_syntax/bsl/languageserver/types/inferencer/ExpressionTypeInferencer.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -709,12 +709,15 @@ private TypeSet inferDereference(BinaryOperationNode node, InferenceContext ctx)
709709
// совпадает с element-ref'ом коллекции.
710710
var elementSet = leftTypes.getElementTypes(leftType);
711711
var members = typeRegistry.getMembers(leftType, ctx.documentContext.getFileType());
712-
// Тип конфигурационного модуля без единого члена — модуль, чей файл ещё не разобран:
713-
// сами по себе типы объявлены заранее, а члены приходят с разбором. Пока области
714-
// наполняются, до части модулей очередь не дошла, и обращение в такой модуль
715-
// отвечает пустотой, ничем не отличимой от честной. Расчёт придётся повторить.
712+
// Тип конфигурации, у которого нет ни одного члена из самой конфигурации, — модуль,
713+
// чей файл ещё не разобран: типы объявлены заранее, а члены приносит разбор.
714+
// Платформенные члены (у общего модуля это ЭтотОбъект) не в счёт: они приходят из
715+
// синтакс-помощника и о разборе ничего не говорят — потому и различаются по
716+
// standardLibrary. Пока область наполняется, обращение в такой модуль отвечает
717+
// пустотой, ничем не отличимой от честной; расчёт придётся повторить.
716718
unparsedModule = unparsedModule
717-
|| (leftType.kind() == TypeKind.CONFIGURATION && members.isEmpty());
719+
|| (leftType.kind() == TypeKind.CONFIGURATION
720+
&& members.stream().allMatch(MemberDescriptor::standardLibrary));
718721
for (var member : members) {
719722
result = result.union(typesOfMember(member, memberName, expectedKind, elementSet, ctx));
720723
}

0 commit comments

Comments
 (0)