Skip to content

Commit f38aa52

Browse files
authored
Область расположения гиперссылки (#351)
1. для SimpleRange добавлен EMPTY 2. для HyperLink добавлен range, в которой расположена ссылка (без параметров)
1 parent 1b38317 commit f38aa52

File tree

10 files changed

+278
-51
lines changed

10 files changed

+278
-51
lines changed

src/main/java/com/github/_1c_syntax/bsl/parser/description/SimpleTypeDescription.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public class SimpleTypeDescription implements TypeDescription {
4141
"",
4242
"",
4343
Collections.emptyList(),
44-
new DescriptionElement(SimpleRange.create(0, 0, 0, 0), DescriptionElement.Type.UNKNOWN)
44+
new DescriptionElement(SimpleRange.EMPTY, DescriptionElement.Type.UNKNOWN)
4545
);
4646

4747
@Accessors(fluent = true)

src/main/java/com/github/_1c_syntax/bsl/parser/description/reader/MethodDescriptionReader.java

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ private static MethodDescription read(String descriptionText, SimpleRange range)
102102
var reader = new MethodDescriptionReader(range);
103103
reader.builder
104104
.description(descriptionText.strip())
105-
.links(ReaderUtils.readLinks(ast))
105+
.links(ReaderUtils.readLinks(ast, reader.lineShift, reader.firstLineCharShift))
106106
.range(range);
107107
reader.visitMethodDescription(ast);
108108
return reader.builder.build();
@@ -300,11 +300,11 @@ private TempParameterData(String name, SimpleRange range, boolean empty) {
300300
}
301301

302302
private static TempParameterData fake() {
303-
return new TempParameterData("", SimpleRange.create(0, 0, 0, 0), false);
303+
return new TempParameterData("", SimpleRange.EMPTY, false);
304304
}
305305

306306
private static TempParameterData empty() {
307-
return new TempParameterData("", SimpleRange.create(0, 0, 0, 0), true);
307+
return new TempParameterData("", SimpleRange.EMPTY, true);
308308
}
309309

310310
private static TempParameterData create(@Nullable ParserRuleContext ctx) {
@@ -349,11 +349,7 @@ private Optional<TempParameterTypeData> lastType() {
349349
}
350350

351351
private ParameterDescription build(int lineShift, int firstLineCharShift) {
352-
var newRange = SimpleRange.create(
353-
range.startLine() + lineShift,
354-
range.startCharacter() + (range.startLine() == 0 ? firstLineCharShift : 0),
355-
range.endLine() + lineShift,
356-
range.endCharacter() + (range.endLine() == 0 ? firstLineCharShift : 0));
352+
var newRange = SimpleRange.shift(range, lineShift, firstLineCharShift);
357353
return new ParameterDescription(
358354
name,
359355
new DescriptionElement(newRange, DescriptionElement.Type.PARAMETER_NAME),
@@ -463,7 +459,8 @@ private static final class TempParameterTypeData {
463459
private final List<TempParameterData> fields;
464460
private final TypeDescription.Variant variant;
465461
private TempParameterTypeData valueType;
466-
private Hyperlink hyperlink;
462+
private Token linkToken;
463+
private Token linkParamsToken;
467464

468465
private final SimpleRange range;
469466

@@ -472,7 +469,8 @@ private TempParameterTypeData(TypeDescription.Variant variant, int level, Simple
472469
this.variant = variant;
473470
this.level = level;
474471
this.description = new StringJoiner("\n");
475-
this.hyperlink = Hyperlink.EMPTY;
472+
this.linkToken = null;
473+
this.linkParamsToken = null;
476474
this.fields = new ArrayList<>();
477475
this.valueType = null;
478476
this.range = range;
@@ -483,7 +481,8 @@ private TempParameterTypeData(Token link,
483481
int level) {
484482
this(TypeDescription.Variant.HYPERLINK, level, SimpleRange.create(link));
485483
this.name = link.getText();
486-
this.hyperlink = Hyperlink.create(this.name, linkParams == null ? "" : linkParams.getText());
484+
this.linkToken = link;
485+
this.linkParamsToken = linkParams;
487486
}
488487

489488
private TempParameterTypeData(Token typeName, TypeDescription.Variant variant, int level) {
@@ -544,12 +543,7 @@ private TypeDescription build(int lineShift, int firstLineCharShift) {
544543
.map(fld -> fld.build(lineShift, firstLineCharShift))
545544
.toList();
546545

547-
var newRange = SimpleRange.create(
548-
range.startLine() + lineShift,
549-
range.startCharacter() + (range.startLine() == 0 ? firstLineCharShift : 0),
550-
range.endLine() + lineShift,
551-
range.endCharacter() + (range.endLine() == 0 ? firstLineCharShift : 0));
552-
546+
var newRange = SimpleRange.shift(range, lineShift, firstLineCharShift);
553547
var element = new DescriptionElement(newRange, DescriptionElement.Type.TYPE_NAME);
554548

555549
return switch (variant) {
@@ -560,7 +554,8 @@ private TypeDescription build(int lineShift, int firstLineCharShift) {
560554
fieldList
561555
);
562556
case HYPERLINK -> HyperlinkTypeDescription.create(
563-
hyperlink, element,
557+
Hyperlink.create(name, linkParamsToken == null ? "" : linkParamsToken.getText(), newRange),
558+
element,
564559
description.toString(),
565560
fieldList
566561
);

src/main/java/com/github/_1c_syntax/bsl/parser/description/reader/ReaderUtils.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import com.github._1c_syntax.bsl.parser.BSLDescriptionParser;
2525
import com.github._1c_syntax.bsl.parser.description.support.Hyperlink;
26+
import com.github._1c_syntax.bsl.parser.description.support.SimpleRange;
2627
import edu.umd.cs.findbugs.annotations.Nullable;
2728
import lombok.experimental.UtilityClass;
2829
import org.antlr.v4.runtime.ParserRuleContext;
@@ -66,17 +67,21 @@ public String extractText(@Nullable ParserRuleContext ctx) {
6667
* Извлекает все ссылки из всех подчиненных узлов указанного
6768
*
6869
* @param ast Корневой узел дерева для извлечения ссылок
70+
* @param lineShift Сдвиг строк для корректировки позиций
71+
* @param firstLineCharShift Сдвиг символов в первой строке для корректировки позиций
6972
* @return Список ссылок
7073
*/
71-
public List<Hyperlink> readLinks(ParserRuleContext ast) {
74+
public List<Hyperlink> readLinks(ParserRuleContext ast, int lineShift, int firstLineCharShift) {
7275
Collection<BSLDescriptionParser.HyperlinkContext> links = Trees.findAllRuleNodes(ast, BSLDescriptionParser.RULE_hyperlink);
7376
if (!links.isEmpty()) {
7477
return links.stream()
7578
.map(
7679
(BSLDescriptionParser.HyperlinkContext hyperlinkContext) -> {
7780
var link = hyperlinkContext.link == null ? "" : hyperlinkContext.link.getText();
7881
var params = hyperlinkContext.linkParams == null ? "" : hyperlinkContext.linkParams.getText();
79-
return Hyperlink.create(link, params);
82+
var range = SimpleRange.create(hyperlinkContext.getStart(), hyperlinkContext.getStop());
83+
var shiftedRange = SimpleRange.shift(range, lineShift, firstLineCharShift);
84+
return Hyperlink.create(link, params, shiftedRange);
8085
})
8186
.toList();
8287
}

src/main/java/com/github/_1c_syntax/bsl/parser/description/reader/VariableDescriptionReader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ private static VariableDescription read(String descriptionText,
9494
var reader = new VariableDescriptionReader(range);
9595
reader.builder
9696
.description(descriptionText.strip())
97-
.links(ReaderUtils.readLinks(ast))
97+
.links(ReaderUtils.readLinks(ast, reader.lineShift, reader.firstLineCharShift))
9898
.range(range)
9999
.trailingDescription(trailingDescription);
100100
reader.visitMethodDescription(ast);

src/main/java/com/github/_1c_syntax/bsl/parser/description/support/Hyperlink.java

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,13 @@
3030
*
3131
* @param link Сама ссылка (до скобок)
3232
* @param params Параметры ссылки (в скобках)
33+
* @param range Область расположения гиперссылки
3334
*/
34-
public record Hyperlink(String link, String params) {
35+
public record Hyperlink(String link, String params, SimpleRange range) {
3536
/**
3637
* Пустая ссылка
3738
*/
38-
public static final Hyperlink EMPTY = new Hyperlink("", "");
39+
public static final Hyperlink EMPTY = new Hyperlink("", "", SimpleRange.EMPTY);
3940

4041
/**
4142
* Создает новый экземпляр {@link Hyperlink} с указанными ссылкой и параметрами.
@@ -46,13 +47,7 @@ public record Hyperlink(String link, String params) {
4647
* @return новый экземпляр {@link Hyperlink}, или пустой экземпляр, если ссылка равна null или пустая
4748
*/
4849
public static Hyperlink create(@Nullable String link, @Nullable String params) {
49-
var linkText = link == null ? "" : link;
50-
if (linkText.isEmpty()) { // если ссылка пустая, то возвращаем пустой объект
51-
return EMPTY;
52-
}
53-
54-
var paramsText = params == null ? "" : params;
55-
return new Hyperlink(linkText.intern(), paramsText);
50+
return create(link, params, SimpleRange.EMPTY);
5651
}
5752

5853
/**
@@ -76,14 +71,32 @@ public static Hyperlink create(String presentation) {
7671
}
7772
}
7873

74+
/**
75+
* Создает новый экземпляр {@link Hyperlink} с указанными ссылкой, параметрами и областью расположения.
76+
*
77+
* @param link ссылка, может быть null
78+
* @param params параметры ссылки, может быть null
79+
* @param range область расположения гиперссылки
80+
* @return новый экземпляр {@link Hyperlink}, или пустой экземпляр, если ссылка равна null или пустая
81+
*/
82+
public static Hyperlink create(@Nullable String link, @Nullable String params, SimpleRange range) {
83+
var linkText = link == null ? "" : link;
84+
if (linkText.isEmpty()) { // если ссылка пустая, то возвращаем пустой объект
85+
return EMPTY;
86+
}
87+
88+
var paramsText = params == null ? "" : params;
89+
return new Hyperlink(linkText.intern(), paramsText, range);
90+
}
91+
7992
@Override
8093
public boolean equals(@Nullable Object other) {
8194
if (this == other) {
8295
return true;
8396
} else if (!(other instanceof Hyperlink otherLink)) {
8497
return false;
8598
} else {
86-
return link.equals(otherLink.link) && params.equals(otherLink.params);
99+
return link.equals(otherLink.link) && params.equals(otherLink.params) && range.equals(otherLink.range);
87100
}
88101
}
89102

@@ -94,6 +107,6 @@ public String toString() {
94107

95108
@Override
96109
public int hashCode() {
97-
return Objects.hash(link, params);
110+
return Objects.hash(link, params, range);
98111
}
99112
}

src/main/java/com/github/_1c_syntax/bsl/parser/description/support/SimpleRange.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@
3535
*/
3636
public record SimpleRange(int startLine, int startCharacter, int endLine, int endCharacter) {
3737

38+
/**
39+
* Пустая область
40+
*/
41+
public static final SimpleRange EMPTY = create(0, 0, 0, 0);
42+
3843
/**
3944
* Проверяет вхождение второй области в первую
4045
*
@@ -114,7 +119,7 @@ public static SimpleRange create(Token token, int lineShift, int firstLineCharSh
114119
*/
115120
public static SimpleRange create(List<Token> tokens) {
116121
if (tokens.isEmpty()) {
117-
return new SimpleRange(0, 0, 0, 0);
122+
return EMPTY;
118123
}
119124
var firstElement = tokens.get(0);
120125
var lastElement = tokens.get(tokens.size() - 1);
@@ -186,4 +191,25 @@ public boolean contains(SimpleRange smaller) {
186191
public int length() {
187192
return Math.max(0, endCharacter - startCharacter);
188193
}
194+
195+
/**
196+
* Создает новый диапазон с учетом сдвигов строк и символов
197+
*
198+
* @param range Диапазон, который нужно сдвинуть
199+
* @param lineShift Сдвиг номера строки
200+
* @param firstLineCharShift Сдвиг первого символа для токенов в первой строке
201+
* @return Новый сдвинутый диапазон
202+
*/
203+
public static SimpleRange shift(SimpleRange range, int lineShift, int firstLineCharShift) {
204+
if (lineShift == 0 && firstLineCharShift == 0) {
205+
return range;
206+
}
207+
208+
return SimpleRange.create(
209+
range.startLine() + lineShift,
210+
range.startCharacter() + (range.startLine() == 0 ? firstLineCharShift : 0),
211+
range.endLine() + lineShift,
212+
range.endCharacter() + (range.endLine() == 0 ? firstLineCharShift : 0)
213+
);
214+
}
189215
}

src/test/java/com/github/_1c_syntax/bsl/parser/description/BSLDescriptionReaderTest.java

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,8 @@ void parseMethodDescription2() {
138138
assertThat(methodDescription.getDeprecationInfo()).isEmpty();
139139
assertThat(methodDescription.getExamples()).isEmpty();
140140
assertThat(methodDescription.getLinks())
141-
.hasSize(1)
142-
.contains(Hyperlink.create("ФайловаяСистемаКлиент.ПараметрыЗагрузкиФайла"));
141+
.hasSize(1);
142+
assertThat(methodDescription.getLinks().get(0).link()).isEqualTo("ФайловаяСистемаКлиент.ПараметрыЗагрузкиФайла");
143143
assertThat(methodDescription.getParameters()).hasSize(1);
144144
checkParameter(methodDescription.getParameters().get(0),
145145
"РежимДиалога", 1, "", false);
@@ -459,8 +459,8 @@ void parseMethodDescription11() {
459459
assertThat(methodDescription.getDeprecationInfo()).isEmpty();
460460
assertThat(methodDescription.getExamples()).isEmpty();
461461
assertThat(methodDescription.getLinks())
462-
.hasSize(1)
463-
.containsExactly(Hyperlink.create("CommonModule.MyModule.MyFunc()"));
462+
.hasSize(1);
463+
assertThat(methodDescription.getLinks().get(0).link()).isEqualTo("CommonModule.MyModule.MyFunc");
464464
assertThat(methodDescription.getParameters()).hasSize(1);
465465
checkParameter(methodDescription.getParameters().get(0),
466466
"CommonModule.MyModule.MyFunc", 1, "CommonModule.MyModule.MyFunc()", true);
@@ -485,8 +485,8 @@ void parseMethodDescription12() {
485485
assertThat(methodDescription.getDeprecationInfo()).isEmpty();
486486
assertThat(methodDescription.getExamples()).isEmpty();
487487
assertThat(methodDescription.getLinks())
488-
.hasSize(1)
489-
.containsExactly(Hyperlink.create("CommonModule.MyModule.MyFunc()"));
488+
.hasSize(1);
489+
assertThat(methodDescription.getLinks().get(0).link()).isEqualTo("CommonModule.MyModule.MyFunc");
490490
assertThat(methodDescription.getParameters()).isEmpty();
491491
assertThat(methodDescription.getReturnedValue()).isEmpty();
492492

@@ -501,8 +501,8 @@ void parseMethodDescription13() {
501501
assertThat(methodDescription.getDeprecationInfo()).isEmpty();
502502
assertThat(methodDescription.getExamples()).isEmpty();
503503
assertThat(methodDescription.getLinks())
504-
.hasSize(1)
505-
.containsExactly(Hyperlink.create("МойКлассныйМодуль.МойКлассныйКонструктор"));
504+
.hasSize(1);
505+
assertThat(methodDescription.getLinks().get(0).link()).isEqualTo("МойКлассныйМодуль.МойКлассныйКонструктор");
506506
assertThat(methodDescription.getParameters()).hasSize(1);
507507

508508
var firstParameter = methodDescription.getParameters().get(0);
@@ -590,8 +590,8 @@ void parseVariableDescription3() {
590590
assertThat(variableDescription.getDeprecationInfo()).isEqualTo("см. НоваяПеременная");
591591
assertThat(variableDescription.isDeprecated()).isTrue();
592592
assertThat(variableDescription.getLinks())
593-
.hasSize(1)
594-
.contains(Hyperlink.create("НоваяПеременная"));
593+
.hasSize(1);
594+
assertThat(variableDescription.getLinks().get(0).link()).isEqualTo("НоваяПеременная");
595595

596596
assertThat(
597597
Objects.equals(variableDescription.getRange(), create(1, 22)))
@@ -616,8 +616,8 @@ void parseVariableDescription4() {
616616
assertThat(variableDescription.getDeprecationInfo()).isEmpty();
617617
assertThat(variableDescription.isDeprecated()).isFalse();
618618
assertThat(variableDescription.getLinks())
619-
.hasSize(1)
620-
.contains(Hyperlink.create("НоваяПеременная"));
619+
.hasSize(1);
620+
assertThat(variableDescription.getLinks().get(0).link()).isEqualTo("НоваяПеременная");
621621

622622
assertThat(
623623
Objects.equals(variableDescription.getRange(), create(0, 22)))
@@ -717,8 +717,9 @@ void parseCollectionType() {
717717
assertThat(methodDescription.getDeprecationInfo()).isEmpty();
718718
assertThat(methodDescription.getExamples()).isEmpty();
719719
assertThat(methodDescription.getLinks())
720-
.hasSize(1)
721-
.contains(Hyperlink.create("Мой.Метод(СПараметром)"));
720+
.hasSize(1);
721+
assertThat(methodDescription.getLinks().get(0).link()).isEqualTo("Мой.Метод");
722+
assertThat(methodDescription.getLinks().get(0).params()).isEqualTo("СПараметром");
722723
assertThat(methodDescription.getParameters()).hasSize(1);
723724
assertThat(methodDescription.getReturnedValue()).isEmpty();
724725

@@ -739,6 +740,36 @@ void parseCollectionType() {
739740
.containsAll(methodDescription.getParameters().get(0).allElements());
740741
}
741742

743+
@Test
744+
void parseHyperlinkWithShift() {
745+
var exampleString = "// See CommonModule.MyModule.MyFunc()";
746+
var tokens = getTokensFromString(exampleString);
747+
var methodDescription = MethodDescription.create(tokens);
748+
749+
assertThat(methodDescription.getLinks()).hasSize(1);
750+
var hyperlink = methodDescription.getLinks().get(0);
751+
assertThat(hyperlink.link()).isEqualTo("CommonModule.MyModule.MyFunc");
752+
753+
// Проверяем, что диапазон гиперссылки учитывает сдвиг
754+
// Гиперссылка начинается с 3 символа и заканчивается на 37 символе
755+
assertThat(hyperlink.range()).isEqualTo(SimpleRange.create(0, 3, 0, 37));
756+
}
757+
758+
@Test
759+
void parseHyperlinkWithLineShift() {
760+
var exampleString = "\n\n// See CommonModule.MyModule.MyFunc()";
761+
var tokens = getTokensFromString(exampleString);
762+
var methodDescription = MethodDescription.create(tokens);
763+
764+
assertThat(methodDescription.getLinks()).hasSize(1);
765+
var hyperlink = methodDescription.getLinks().get(0);
766+
assertThat(hyperlink.link()).isEqualTo("CommonModule.MyModule.MyFunc");
767+
768+
// Проверяем, что диапазон гиперссылки учитывает сдвиг строк
769+
// Комментарий начинается на 3-й строке (индекс 1 после токенизации), гиперссылка начинается с 3 символа и заканчивается на 37 символе
770+
assertThat(hyperlink.range()).isEqualTo(SimpleRange.create(1, 3, 1, 37));
771+
}
772+
742773
private List<Token> getTokensFromString(String exampleString) {
743774
var tokenizer = new BSLTokenizer(exampleString);
744775
return tokenizer.getTokens().stream()
@@ -752,7 +783,9 @@ private void checkParameter(ParameterDescription parameter,
752783
String link,
753784
boolean isHyperlink) {
754785
assertThat(parameter.name()).isEqualTo(name);
755-
assertThat(parameter.link()).isEqualTo(Hyperlink.create(link));
786+
var expectedHyperlink = Hyperlink.create(link);
787+
assertThat(parameter.link().link()).isEqualTo(expectedHyperlink.link());
788+
assertThat(parameter.link().params()).isEqualTo(expectedHyperlink.params());
756789
assertThat(parameter.types()).hasSize(countTypes);
757790
assertThat(parameter.isHyperlink()).isEqualTo(isHyperlink);
758791
assertThat(parameter.element().range().length()).isEqualTo(parameter.name().length());
@@ -769,7 +802,10 @@ private void checkType(TypeDescription type,
769802
assertThat(type.variant() == TypeDescription.Variant.HYPERLINK).isEqualTo(isHyperlink);
770803
if (isHyperlink) {
771804
assertThat(type).isInstanceOf(HyperlinkTypeDescription.class);
772-
assertThat(((HyperlinkTypeDescription) type).hyperlink()).isEqualTo(Hyperlink.create(link));
805+
var expectedHyperlink = Hyperlink.create(link);
806+
var actualHyperlink = ((HyperlinkTypeDescription) type).hyperlink();
807+
assertThat(actualHyperlink.link()).isEqualTo(expectedHyperlink.link());
808+
assertThat(actualHyperlink.params()).isEqualTo(expectedHyperlink.params());
773809
}
774810
assertThat(type.fields()).hasSize(countParameters);
775811
if (type instanceof CollectionTypeDescription colType) {

0 commit comments

Comments
 (0)