-
Notifications
You must be signed in to change notification settings - Fork 109
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
352 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
228 changes: 228 additions & 0 deletions
228
src/main/java/org/github/_1c_syntax/bsl/languageserver/providers/FoldingRangeProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,228 @@ | ||
/* | ||
* This file is a part of BSL Language Server. | ||
* | ||
* Copyright © 2018-2019 | ||
* Alexey Sosnoviy <labotamy@gmail.com>, Nikita Gryzlov <nixel2007@gmail.com> and contributors | ||
* | ||
* SPDX-License-Identifier: LGPL-3.0-or-later | ||
* | ||
* BSL Language Server is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU Lesser General Public | ||
* License as published by the Free Software Foundation; either | ||
* version 3.0 of the License, or (at your option) any later version. | ||
* | ||
* BSL Language Server is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public | ||
* License along with BSL Language Server. | ||
*/ | ||
package org.github._1c_syntax.bsl.languageserver.providers; | ||
|
||
import org.antlr.v4.runtime.Token; | ||
import org.antlr.v4.runtime.tree.ParseTree; | ||
import org.antlr.v4.runtime.tree.TerminalNode; | ||
import org.eclipse.lsp4j.FoldingRange; | ||
import org.github._1c_syntax.bsl.languageserver.context.DocumentContext; | ||
import org.github._1c_syntax.bsl.parser.BSLParser; | ||
import org.github._1c_syntax.bsl.parser.BSLParserBaseVisitor; | ||
|
||
import java.util.ArrayDeque; | ||
import java.util.ArrayList; | ||
import java.util.Deque; | ||
import java.util.List; | ||
|
||
public final class FoldingRangeProvider { | ||
|
||
private static final String REGION_KIND = "region"; | ||
private static final String COMMENT_KIND = "comment"; | ||
|
||
private FoldingRangeProvider() { | ||
// only statics | ||
} | ||
|
||
public static List<FoldingRange> getFoldingRange(DocumentContext documentContext) { | ||
|
||
List<FoldingRange> foldingRanges = getCommentRanges(documentContext); | ||
|
||
CodeBlockRangeFinder codeBlockRangeFinder = new CodeBlockRangeFinder(); | ||
codeBlockRangeFinder.visitFile(documentContext.getAst()); | ||
List<FoldingRange> codeBlockRegionRanges = codeBlockRangeFinder.getRegionRanges(); | ||
|
||
RegionRangeFinder regionRangeFinder = new RegionRangeFinder(); | ||
regionRangeFinder.visitFile(documentContext.getAst()); | ||
List<FoldingRange> regionRanges = regionRangeFinder.getRegionRanges(); | ||
|
||
PreprocIfRegionRangeFinder preprocIfRegionRangeFinder = new PreprocIfRegionRangeFinder(); | ||
preprocIfRegionRangeFinder.visitFile(documentContext.getAst()); | ||
List<FoldingRange> preprocRegionRanges = preprocIfRegionRangeFinder.getRegionRanges(); | ||
|
||
foldingRanges.addAll(codeBlockRegionRanges); | ||
foldingRanges.addAll(regionRanges); | ||
foldingRanges.addAll(preprocRegionRanges); | ||
|
||
return foldingRanges; | ||
} | ||
|
||
private static List<FoldingRange> getCommentRanges(DocumentContext documentContext) { | ||
List<FoldingRange> foldingRanges = new ArrayList<>(); | ||
|
||
int lastRangeStart = -1; | ||
int previousLine = -1; | ||
List<Token> comments = documentContext.getComments(); | ||
for (Token token : comments) { | ||
int tokenLine = token.getLine(); | ||
|
||
if (tokenLine != previousLine + 1) { | ||
if (lastRangeStart != previousLine) { | ||
FoldingRange foldingRange = new FoldingRange(lastRangeStart - 1, previousLine - 1); | ||
foldingRange.setKind(COMMENT_KIND); | ||
|
||
foldingRanges.add(foldingRange); | ||
} | ||
// new range | ||
lastRangeStart = tokenLine; | ||
} | ||
|
||
previousLine = tokenLine; | ||
} | ||
|
||
// add last range | ||
if (lastRangeStart != previousLine) { | ||
FoldingRange foldingRange = new FoldingRange(lastRangeStart - 1, previousLine - 1); | ||
foldingRange.setKind(COMMENT_KIND); | ||
|
||
foldingRanges.add(foldingRange); | ||
} | ||
return foldingRanges; | ||
} | ||
|
||
private static class CodeBlockRangeFinder extends BSLParserBaseVisitor<ParseTree> { | ||
|
||
private List<FoldingRange> regionRanges = new ArrayList<>(); | ||
|
||
public List<FoldingRange> getRegionRanges() { | ||
return new ArrayList<>(regionRanges); | ||
} | ||
|
||
@Override | ||
public ParseTree visitProcedure(BSLParser.ProcedureContext ctx) { | ||
addRegionRange(ctx.procDeclaration().PROCEDURE_KEYWORD(), ctx.ENDPROCEDURE_KEYWORD()); | ||
return super.visitProcedure(ctx); | ||
} | ||
|
||
@Override | ||
public ParseTree visitFunction(BSLParser.FunctionContext ctx) { | ||
addRegionRange(ctx.funcDeclaration().FUNCTION_KEYWORD(), ctx.ENDFUNCTION_KEYWORD()); | ||
return super.visitFunction(ctx); | ||
} | ||
|
||
@Override | ||
public ParseTree visitIfStatement(BSLParser.IfStatementContext ctx) { | ||
addRegionRange(ctx.IF_KEYWORD(), ctx.ENDIF_KEYWORD()); | ||
return super.visitIfStatement(ctx); | ||
} | ||
|
||
@Override | ||
public ParseTree visitWhileStatement(BSLParser.WhileStatementContext ctx) { | ||
addRegionRange(ctx.WHILE_KEYWORD(), ctx.ENDDO_KEYWORD()); | ||
return super.visitWhileStatement(ctx); | ||
} | ||
|
||
@Override | ||
public ParseTree visitForStatement(BSLParser.ForStatementContext ctx) { | ||
addRegionRange(ctx.FOR_KEYWORD(), ctx.ENDDO_KEYWORD()); | ||
return super.visitForStatement(ctx); | ||
} | ||
|
||
@Override | ||
public ParseTree visitForEachStatement(BSLParser.ForEachStatementContext ctx) { | ||
addRegionRange(ctx.FOR_KEYWORD(), ctx.ENDDO_KEYWORD()); | ||
return super.visitForEachStatement(ctx); | ||
} | ||
|
||
@Override | ||
public ParseTree visitTryStatement(BSLParser.TryStatementContext ctx) { | ||
addRegionRange(ctx.TRY_KEYWORD(), ctx.ENDTRY_KEYWORD()); | ||
return super.visitTryStatement(ctx); | ||
} | ||
|
||
private void addRegionRange(TerminalNode start, TerminalNode stop) { | ||
int startLine = start.getSymbol().getLine(); | ||
int stopLine = stop.getSymbol().getLine(); | ||
|
||
if (stopLine > startLine) { | ||
FoldingRange foldingRange = new FoldingRange(startLine - 1, stopLine - 1); | ||
foldingRange.setKind(REGION_KIND); | ||
|
||
regionRanges.add(foldingRange); | ||
} | ||
} | ||
} | ||
|
||
private static class RegionRangeFinder extends BSLParserBaseVisitor<ParseTree> { | ||
|
||
private Deque<BSLParser.RegionStartContext> regionStack = new ArrayDeque<>(); | ||
private List<FoldingRange> regionRanges = new ArrayList<>(); | ||
|
||
public List<FoldingRange> getRegionRanges() { | ||
return new ArrayList<>(regionRanges); | ||
} | ||
|
||
@Override | ||
public ParseTree visitRegionStart(BSLParser.RegionStartContext ctx) { | ||
regionStack.push(ctx); | ||
return super.visitRegionStart(ctx); | ||
} | ||
|
||
@Override | ||
public ParseTree visitRegionEnd(BSLParser.RegionEndContext ctx) { | ||
|
||
BSLParser.RegionStartContext regionStart = regionStack.pop(); | ||
|
||
int start = regionStart.getStart().getLine(); | ||
int stop = ctx.getStop().getLine(); | ||
|
||
FoldingRange foldingRange = new FoldingRange(start - 1, stop - 1); | ||
foldingRange.setKind(REGION_KIND); | ||
|
||
regionRanges.add(foldingRange); | ||
|
||
return super.visitRegionEnd(ctx); | ||
} | ||
} | ||
|
||
private static class PreprocIfRegionRangeFinder extends BSLParserBaseVisitor<ParseTree> { | ||
|
||
private Deque<BSLParser.Preproc_ifContext> preprocIfRegionStack = new ArrayDeque<>(); | ||
private List<FoldingRange> regionRanges = new ArrayList<>(); | ||
|
||
public List<FoldingRange> getRegionRanges() { | ||
return new ArrayList<>(regionRanges); | ||
} | ||
|
||
@Override | ||
public ParseTree visitPreproc_if(BSLParser.Preproc_ifContext ctx) { | ||
preprocIfRegionStack.push(ctx); | ||
return super.visitPreproc_if(ctx); | ||
} | ||
|
||
@Override | ||
public ParseTree visitPreproc_endif(BSLParser.Preproc_endifContext ctx) { | ||
BSLParser.Preproc_ifContext regionStart = preprocIfRegionStack.pop(); | ||
|
||
int start = regionStart.getStart().getLine(); | ||
int stop = ctx.getStop().getLine(); | ||
|
||
FoldingRange foldingRange = new FoldingRange(start - 1, stop - 1); | ||
foldingRange.setKind(REGION_KIND); | ||
|
||
regionRanges.add(foldingRange); | ||
|
||
return super.visitPreproc_endif(ctx); | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 73 additions & 0 deletions
73
...est/java/org/github/_1c_syntax/bsl/languageserver/providers/FoldingRangeProviderTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
/* | ||
* This file is a part of BSL Language Server. | ||
* | ||
* Copyright © 2018-2019 | ||
* Alexey Sosnoviy <labotamy@gmail.com>, Nikita Gryzlov <nixel2007@gmail.com> and contributors | ||
* | ||
* SPDX-License-Identifier: LGPL-3.0-or-later | ||
* | ||
* BSL Language Server is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU Lesser General Public | ||
* License as published by the Free Software Foundation; either | ||
* version 3.0 of the License, or (at your option) any later version. | ||
* | ||
* BSL Language Server is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public | ||
* License along with BSL Language Server. | ||
*/ | ||
package org.github._1c_syntax.bsl.languageserver.providers; | ||
|
||
import org.apache.commons.io.FileUtils; | ||
import org.eclipse.lsp4j.FoldingRange; | ||
import org.github._1c_syntax.bsl.languageserver.context.DocumentContext; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.nio.charset.StandardCharsets; | ||
import java.util.List; | ||
|
||
import static org.assertj.core.api.Java6Assertions.assertThat; | ||
|
||
class FoldingRangeProviderTest { | ||
|
||
@Test | ||
void testFoldingRange() throws IOException { | ||
|
||
String fileContent = FileUtils.readFileToString( | ||
new File("./src/test/resources/providers/foldingRange.bsl"), | ||
StandardCharsets.UTF_8 | ||
); | ||
DocumentContext documentContext = new DocumentContext("fake-uri.bsl", fileContent); | ||
|
||
List<FoldingRange> foldingRanges = FoldingRangeProvider.getFoldingRange(documentContext); | ||
|
||
assertThat(foldingRanges).hasSize(9); | ||
|
||
// regions | ||
assertThat(foldingRanges) | ||
.filteredOn(foldingRange -> foldingRange.getKind().equals("region")) | ||
.anyMatch(foldingRange -> foldingRange.getStartLine() == 0 && foldingRange.getEndLine() == 23) | ||
.anyMatch(foldingRange -> foldingRange.getStartLine() == 2 && foldingRange.getEndLine() == 16) | ||
.anyMatch(foldingRange -> foldingRange.getStartLine() == 4 && foldingRange.getEndLine() == 14) | ||
.anyMatch(foldingRange -> foldingRange.getStartLine() == 8 && foldingRange.getEndLine() == 12) | ||
.anyMatch(foldingRange -> foldingRange.getStartLine() == 9 && foldingRange.getEndLine() == 11) | ||
.anyMatch(foldingRange -> foldingRange.getStartLine() == 20 && foldingRange.getEndLine() == 21) | ||
.anyMatch(foldingRange -> foldingRange.getStartLine() == 25 && foldingRange.getEndLine() == 26) | ||
; | ||
|
||
|
||
// comments | ||
assertThat(foldingRanges) | ||
.filteredOn(foldingRange -> foldingRange.getKind().equals("comment")) | ||
.hasSize(2) | ||
.anyMatch(foldingRange -> foldingRange.getStartLine() == 6 && foldingRange.getEndLine() == 7) | ||
.anyMatch(foldingRange -> foldingRange.getStartLine() == 18 && foldingRange.getEndLine() == 19) | ||
; | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#Область ИмяОбласти | ||
|
||
#Если Сервер Тогда | ||
|
||
#Область ВложеннаяОбласть | ||
|
||
// Комментарий | ||
// многострочный | ||
Процедура ИмяПроцедуры() | ||
Если Истина Тогда | ||
А = 0; | ||
КонецЕсли; | ||
КонецПроцедуры | ||
|
||
#КонецОбласти | ||
|
||
#КонецЕсли | ||
|
||
// Комментарий | ||
// многострочный | ||
Процедура ИмяПроцедуры2() | ||
КонецПроцедуры | ||
|
||
#КонецОбласти | ||
|
||
Процедура ИмяПроцедуры3() | ||
КонецПроцедуры |