Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
nixel2007 committed May 27, 2019
2 parents e21b329 + f9f70a2 commit ce92db5
Show file tree
Hide file tree
Showing 7 changed files with 352 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

* Форматирование файла
* Форматирование выбранного диапазона
* Определение сворачиваемых областей - `#Область`, `#Если`, процедуры и функции, блоки кода
* Диагностики
* Запуск движка диагностик из командной строки

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public CompletableFuture<InitializeResult> initialize(InitializeParams params) {
//capabilities.setHoverProvider(Boolean.TRUE);
capabilities.setDocumentRangeFormattingProvider(Boolean.TRUE);
capabilities.setDocumentFormattingProvider(Boolean.TRUE);
capabilities.setFoldingRangeProvider(Boolean.TRUE);

InitializeResult result = new InitializeResult(capabilities);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
import org.eclipse.lsp4j.DocumentRangeFormattingParams;
import org.eclipse.lsp4j.DocumentSymbol;
import org.eclipse.lsp4j.DocumentSymbolParams;
import org.eclipse.lsp4j.FoldingRange;
import org.eclipse.lsp4j.FoldingRangeRequestParams;
import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.ReferenceParams;
Expand All @@ -56,6 +58,7 @@
import org.github._1c_syntax.bsl.languageserver.context.DocumentContext;
import org.github._1c_syntax.bsl.languageserver.context.ServerContext;
import org.github._1c_syntax.bsl.languageserver.providers.DiagnosticProvider;
import org.github._1c_syntax.bsl.languageserver.providers.FoldingRangeProvider;
import org.github._1c_syntax.bsl.languageserver.providers.FormatProvider;
import org.github._1c_syntax.bsl.languageserver.providers.HoverProvider;

Expand Down Expand Up @@ -170,6 +173,16 @@ public CompletableFuture<List<? extends TextEdit>> onTypeFormatting(DocumentOnTy
throw new UnsupportedOperationException();
}

@Override
public CompletableFuture<List<FoldingRange>> foldingRange(FoldingRangeRequestParams params) {
DocumentContext documentContext = context.getDocument(params.getTextDocument().getUri());
if (documentContext == null) {
return CompletableFuture.completedFuture(null);
}

return CompletableFuture.supplyAsync(() -> FoldingRangeProvider.getFoldingRange(documentContext));
}

@Override
public CompletableFuture<WorkspaceEdit> rename(RenameParams params) {
throw new UnsupportedOperationException();
Expand Down
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);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,16 @@ private FormatProvider() {
}

public static List<TextEdit> getFormatting(DocumentFormattingParams params, DocumentContext documentContext) {
List<Token> tokens = documentContext.getTokens();
if (tokens.isEmpty()) {
return Collections.emptyList();
}
Token firstToken = tokens.get(0);
Token lastToken = tokens.get(tokens.size() - 1);

return getTextEdits(
documentContext.getTokens(),
RangeHelper.newRange(documentContext.getAst()), 0, params.getOptions()
tokens,
RangeHelper.newRange(firstToken, lastToken), firstToken.getCharPositionInLine(), params.getOptions()
);
}

Expand Down
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)
;

}
}
27 changes: 27 additions & 0 deletions src/test/resources/providers/foldingRange.bsl
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#Область ИмяОбласти

#Если Сервер Тогда

#Область ВложеннаяОбласть

// Комментарий
// многострочный
Процедура ИмяПроцедуры()
Если Истина Тогда
А = 0;
КонецЕсли;
КонецПроцедуры

#КонецОбласти

#КонецЕсли

// Комментарий
// многострочный
Процедура ИмяПроцедуры2()
КонецПроцедуры

#КонецОбласти

Процедура ИмяПроцедуры3()
КонецПроцедуры

0 comments on commit ce92db5

Please sign in to comment.