From 8a91aeb1afd8f66bc6b841f17b75e9032e91ab98 Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Wed, 25 Aug 2021 19:23:43 +0300 Subject: [PATCH 1/4] =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=B4=D0=B5=D0=BB?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=B4=D0=B8=D0=B0=D0=B3=D0=BD=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D0=B8=D0=BA=D0=B8=20=D0=B2=20=D0=BF=D0=B5=D1=80=D0=B2=D0=BE?= =?UTF-8?q?=D0=BC=20=D0=BF=D1=80=D0=B8=D0=B1=D0=BB=D0=B8=D0=B6=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../languageserver/cfg/ControlFlowGraph.java | 2 +- .../UnreachableCodeDiagnostic.java | 114 ++++++++---------- 2 files changed, 52 insertions(+), 64 deletions(-) diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/cfg/ControlFlowGraph.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/cfg/ControlFlowGraph.java index df06952aa51..7f8c78c1c22 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/cfg/ControlFlowGraph.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/cfg/ControlFlowGraph.java @@ -34,7 +34,7 @@ public class ControlFlowGraph extends DefaultDirectedGraph { @Getter private ExitVertex exitPoint; - public ControlFlowGraph() { + ControlFlowGraph() { super(CfgEdge.class); exitPoint = new ExitVertex(); addVertex(exitPoint); diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnreachableCodeDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnreachableCodeDiagnostic.java index a6b3daa5df3..88aa610fb24 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnreachableCodeDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnreachableCodeDiagnostic.java @@ -21,6 +21,10 @@ */ package com.github._1c_syntax.bsl.languageserver.diagnostics; +import com.github._1c_syntax.bsl.languageserver.cfg.CfgBuildingParseTreeVisitor; +import com.github._1c_syntax.bsl.languageserver.cfg.CfgEdgeType; +import com.github._1c_syntax.bsl.languageserver.cfg.CfgVertex; +import com.github._1c_syntax.bsl.languageserver.cfg.ControlFlowGraph; import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticMetadata; import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticSeverity; import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticTag; @@ -37,7 +41,9 @@ import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.Deque; +import java.util.HashSet; import java.util.List; import java.util.stream.Collectors; @@ -61,83 +67,65 @@ public class UnreachableCodeDiagnostic extends AbstractVisitorDiagnostic { @Override public ParseTree visitFile(BSLParser.FileContext ctx) { errorRanges.clear(); - preprocessorRanges.clear(); - - // получим все блоки препроцессора в файле - List preprocessors = new ArrayList<>(Trees.findAllRuleNodes(ctx, BSLParser.RULE_preprocessor)); - - if (preprocessors.isEmpty()) { - return super.visitFile(ctx); - } + return super.visitFile(ctx); + } - Deque previousNodes = new ArrayDeque<>(); - for (ParseTree node : preprocessors) { + @Override + public ParseTree visitSubCodeBlock(BSLParser.SubCodeBlockContext ctx) { + findUnreachableCode(ctx.codeBlock()); + return ctx; + } - // если это начало блока, просто закинем его в стэк - if (((BSLParser.PreprocessorContext) node).preproc_if() != null) { - previousNodes.push(node); - } else if ((((BSLParser.PreprocessorContext) node).preproc_else() != null - || ((BSLParser.PreprocessorContext) node).preproc_elsif() != null)) { + @Override + public ParseTree visitFileCodeBlock(BSLParser.FileCodeBlockContext ctx) { + findUnreachableCode(ctx.codeBlock()); + return ctx; + } - // для веток условия сначала фиксируем блок который уже прошли - // затем новую ноду добавим - savePreprocessorRange(previousNodes, (BSLParser.PreprocessorContext) node); - previousNodes.push(node); + private void findUnreachableCode(BSLParser.CodeBlockContext codeBlock) { + var builder = new CfgBuildingParseTreeVisitor(); - } else { - // в конце условия просто зафиксим прошедший блок - savePreprocessorRange(previousNodes, (BSLParser.PreprocessorContext) node); - } + if (codeBlock == null) { + return; } - // сделано для поиска с конца, т.к. у нас есть вложенность, т.е. в большой вложен маленький - if (preprocessorRanges.size() > 1) { - Collections.reverse(preprocessorRanges); - } + var graph = builder.buildGraph(codeBlock); + var brokenCodeBlocks = new HashSet(); - return super.visitFile(ctx); - } + var deadBlocks = graph.vertexSet() + .stream() + .sequential() + .filter(vertex -> vertex != graph.getEntryPoint()) + .filter(vertex -> isDeadCodeVertex(graph, vertex)) + .flatMap(optional -> optional.getAst().stream()) + .sorted(Comparator.comparingInt(bslParserRuleContext -> bslParserRuleContext.getStart().getLine())) + .collect(Collectors.toList()); - private void savePreprocessorRange(Deque nodes, BSLParser.PreprocessorContext node) { - if (!nodes.isEmpty()) { - BSLParser.PreprocessorContext previous = (BSLParser.PreprocessorContext) nodes.pop(); - preprocessorRanges.add( - Ranges.create( - previous.getStop().getLine(), - previous.getStop().getCharPositionInLine() + previous.getStop().getText().length() + 1, - node.getStart().getLine(), - node.getStart().getCharPositionInLine() - 1)); - } - } + for (var astNode : deadBlocks) { + // оптимизация, если в методе нет повторов мертвого кода + if (deadBlocks.size() > 1) { + var owningCodeBlock = Trees.getAncestorByRuleIndex(astNode, BSLParser.RULE_codeBlock); + if (owningCodeBlock != null && brokenCodeBlocks.contains(owningCodeBlock)) { + continue; + } - @Override - public ParseTree visitContinueStatement(BSLParser.ContinueStatementContext ctx) { - findAndAddDiagnostic(ctx); - return super.visitContinueStatement(ctx); - } + if (owningCodeBlock != null) { + brokenCodeBlocks.add((BSLParser.CodeBlockContext) owningCodeBlock); + } + } - @Override - public ParseTree visitReturnStatement(BSLParser.ReturnStatementContext ctx) { - findAndAddDiagnostic(ctx); - return super.visitReturnStatement(ctx); - } + diagnosticStorage.addDiagnostic(astNode); - @Override - public ParseTree visitGotoStatement(BSLParser.GotoStatementContext ctx) { - findAndAddDiagnostic(ctx); - return super.visitGotoStatement(ctx); + } } - @Override - public ParseTree visitRaiseStatement(BSLParser.RaiseStatementContext ctx) { - findAndAddDiagnostic(ctx); - return super.visitRaiseStatement(ctx); - } + private boolean isDeadCodeVertex(ControlFlowGraph graph, CfgVertex vertex) { + var incoming = graph.incomingEdgesOf(vertex); + if (incoming.isEmpty()) { + return true; + } - @Override - public ParseTree visitBreakStatement(BSLParser.BreakStatementContext ctx) { - findAndAddDiagnostic(ctx); - return super.visitBreakStatement(ctx); + return incoming.stream().allMatch(edge -> edge.getType() == CfgEdgeType.LOOP_ITERATION); } private void findAndAddDiagnostic(BSLParserRuleContext ctx) { From bf6fcc2f772e02122d1bc5e5e91e78e5eec928a5 Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Thu, 26 Aug 2021 10:41:53 +0300 Subject: [PATCH 2/4] =?UTF-8?q?=D0=A0=D0=B5=D0=B6=D0=B8=D0=BC=20=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D0=BA=D0=BB=D0=B8=D1=87=D0=BD=D0=BE=D1=81=D1=82?= =?UTF-8?q?=D0=B8=20=D0=BF=D1=80=D0=B8=20=D0=BF=D0=BE=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=BE=D0=B5=D0=BD=D0=B8=D0=B8=20=D0=B3=D1=80=D0=B0=D1=84=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../languageserver/cfg/CfgBuildingParseTreeVisitor.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/cfg/CfgBuildingParseTreeVisitor.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/cfg/CfgBuildingParseTreeVisitor.java index f2d31bdc63a..9b46b1ca9ec 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/cfg/CfgBuildingParseTreeVisitor.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/cfg/CfgBuildingParseTreeVisitor.java @@ -36,6 +36,8 @@ public class CfgBuildingParseTreeVisitor extends BSLParserBaseVisitor private ControlFlowGraph graph; private Map jumpLabels; + private boolean produceLoopIterationsEnabled = true; + public ControlFlowGraph buildGraph(BSLParser.CodeBlockContext block) { blocks = new StatementsBlockWriter(); @@ -66,6 +68,10 @@ public ControlFlowGraph buildGraph(BSLParser.CodeBlockContext block) { return graph; } + public void produceLoopIterations(boolean flag) { + produceLoopIterationsEnabled = flag; + } + @Override public ParseTree visitCallStatement(BSLParser.CallStatementContext ctx) { blocks.addStatement(ctx); @@ -473,7 +479,8 @@ private void buildLoopSubgraph(BSLParser.CodeBlockContext ctx, LoopVertex loopSt graph.addEdge(loopStart, body.begin(), CfgEdgeType.TRUE_BRANCH); graph.addEdge(loopStart, blocks.getCurrentBlock().end(), CfgEdgeType.FALSE_BRANCH); - graph.addEdge(body.end(), loopStart, CfgEdgeType.LOOP_ITERATION); + if (produceLoopIterationsEnabled) + graph.addEdge(body.end(), loopStart, CfgEdgeType.LOOP_ITERATION); } private void connectGraphTail(StatementsBlockWriter.StatementsBlockRecord currentBlock, CfgVertex vertex) { From cc09fb074ad003fc4b88c66fd946d388493df64c Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Tue, 31 Aug 2021 22:01:31 +0300 Subject: [PATCH 3/4] =?UTF-8?q?Revert=20"=D0=BF=D0=B5=D1=80=D0=B5=D0=B4?= =?UTF-8?q?=D0=B5=D0=BB=D0=BA=D0=B0=20=D0=B4=D0=B8=D0=B0=D0=B3=D0=BD=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D0=B8=D0=BA=D0=B8=20=D0=B2=20=D0=BF=D0=B5=D1=80?= =?UTF-8?q?=D0=B2=D0=BE=D0=BC=20=D0=BF=D1=80=D0=B8=D0=B1=D0=BB=D0=B8=D0=B6?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B8"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 8a91aeb1afd8f66bc6b841f17b75e9032e91ab98. --- .../languageserver/cfg/ControlFlowGraph.java | 2 +- .../UnreachableCodeDiagnostic.java | 114 ++++++++++-------- 2 files changed, 64 insertions(+), 52 deletions(-) diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/cfg/ControlFlowGraph.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/cfg/ControlFlowGraph.java index 1ed88d6fc1e..37efd161f07 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/cfg/ControlFlowGraph.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/cfg/ControlFlowGraph.java @@ -34,7 +34,7 @@ public class ControlFlowGraph extends DefaultDirectedGraph { @Getter private ExitVertex exitPoint; - ControlFlowGraph() { + public ControlFlowGraph() { super(CfgEdge.class); exitPoint = new ExitVertex(); addVertex(exitPoint); diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnreachableCodeDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnreachableCodeDiagnostic.java index 88aa610fb24..a6b3daa5df3 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnreachableCodeDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnreachableCodeDiagnostic.java @@ -21,10 +21,6 @@ */ package com.github._1c_syntax.bsl.languageserver.diagnostics; -import com.github._1c_syntax.bsl.languageserver.cfg.CfgBuildingParseTreeVisitor; -import com.github._1c_syntax.bsl.languageserver.cfg.CfgEdgeType; -import com.github._1c_syntax.bsl.languageserver.cfg.CfgVertex; -import com.github._1c_syntax.bsl.languageserver.cfg.ControlFlowGraph; import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticMetadata; import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticSeverity; import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticTag; @@ -41,9 +37,7 @@ import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; import java.util.Deque; -import java.util.HashSet; import java.util.List; import java.util.stream.Collectors; @@ -67,65 +61,83 @@ public class UnreachableCodeDiagnostic extends AbstractVisitorDiagnostic { @Override public ParseTree visitFile(BSLParser.FileContext ctx) { errorRanges.clear(); - return super.visitFile(ctx); - } - - @Override - public ParseTree visitSubCodeBlock(BSLParser.SubCodeBlockContext ctx) { - findUnreachableCode(ctx.codeBlock()); - return ctx; - } - - @Override - public ParseTree visitFileCodeBlock(BSLParser.FileCodeBlockContext ctx) { - findUnreachableCode(ctx.codeBlock()); - return ctx; - } + preprocessorRanges.clear(); - private void findUnreachableCode(BSLParser.CodeBlockContext codeBlock) { - var builder = new CfgBuildingParseTreeVisitor(); + // получим все блоки препроцессора в файле + List preprocessors = new ArrayList<>(Trees.findAllRuleNodes(ctx, BSLParser.RULE_preprocessor)); - if (codeBlock == null) { - return; + if (preprocessors.isEmpty()) { + return super.visitFile(ctx); } - var graph = builder.buildGraph(codeBlock); - var brokenCodeBlocks = new HashSet(); + Deque previousNodes = new ArrayDeque<>(); + for (ParseTree node : preprocessors) { - var deadBlocks = graph.vertexSet() - .stream() - .sequential() - .filter(vertex -> vertex != graph.getEntryPoint()) - .filter(vertex -> isDeadCodeVertex(graph, vertex)) - .flatMap(optional -> optional.getAst().stream()) - .sorted(Comparator.comparingInt(bslParserRuleContext -> bslParserRuleContext.getStart().getLine())) - .collect(Collectors.toList()); + // если это начало блока, просто закинем его в стэк + if (((BSLParser.PreprocessorContext) node).preproc_if() != null) { + previousNodes.push(node); + } else if ((((BSLParser.PreprocessorContext) node).preproc_else() != null + || ((BSLParser.PreprocessorContext) node).preproc_elsif() != null)) { - for (var astNode : deadBlocks) { - // оптимизация, если в методе нет повторов мертвого кода - if (deadBlocks.size() > 1) { - var owningCodeBlock = Trees.getAncestorByRuleIndex(astNode, BSLParser.RULE_codeBlock); - if (owningCodeBlock != null && brokenCodeBlocks.contains(owningCodeBlock)) { - continue; - } + // для веток условия сначала фиксируем блок который уже прошли + // затем новую ноду добавим + savePreprocessorRange(previousNodes, (BSLParser.PreprocessorContext) node); + previousNodes.push(node); - if (owningCodeBlock != null) { - brokenCodeBlocks.add((BSLParser.CodeBlockContext) owningCodeBlock); - } + } else { + // в конце условия просто зафиксим прошедший блок + savePreprocessorRange(previousNodes, (BSLParser.PreprocessorContext) node); } + } - diagnosticStorage.addDiagnostic(astNode); - + // сделано для поиска с конца, т.к. у нас есть вложенность, т.е. в большой вложен маленький + if (preprocessorRanges.size() > 1) { + Collections.reverse(preprocessorRanges); } + + return super.visitFile(ctx); } - private boolean isDeadCodeVertex(ControlFlowGraph graph, CfgVertex vertex) { - var incoming = graph.incomingEdgesOf(vertex); - if (incoming.isEmpty()) { - return true; + private void savePreprocessorRange(Deque nodes, BSLParser.PreprocessorContext node) { + if (!nodes.isEmpty()) { + BSLParser.PreprocessorContext previous = (BSLParser.PreprocessorContext) nodes.pop(); + preprocessorRanges.add( + Ranges.create( + previous.getStop().getLine(), + previous.getStop().getCharPositionInLine() + previous.getStop().getText().length() + 1, + node.getStart().getLine(), + node.getStart().getCharPositionInLine() - 1)); } + } + + @Override + public ParseTree visitContinueStatement(BSLParser.ContinueStatementContext ctx) { + findAndAddDiagnostic(ctx); + return super.visitContinueStatement(ctx); + } + + @Override + public ParseTree visitReturnStatement(BSLParser.ReturnStatementContext ctx) { + findAndAddDiagnostic(ctx); + return super.visitReturnStatement(ctx); + } - return incoming.stream().allMatch(edge -> edge.getType() == CfgEdgeType.LOOP_ITERATION); + @Override + public ParseTree visitGotoStatement(BSLParser.GotoStatementContext ctx) { + findAndAddDiagnostic(ctx); + return super.visitGotoStatement(ctx); + } + + @Override + public ParseTree visitRaiseStatement(BSLParser.RaiseStatementContext ctx) { + findAndAddDiagnostic(ctx); + return super.visitRaiseStatement(ctx); + } + + @Override + public ParseTree visitBreakStatement(BSLParser.BreakStatementContext ctx) { + findAndAddDiagnostic(ctx); + return super.visitBreakStatement(ctx); } private void findAndAddDiagnostic(BSLParserRuleContext ctx) { From 4c7aadce737d605f6cdfaeec4a5cf4465c9fb312 Mon Sep 17 00:00:00 2001 From: EvilBeaver Date: Tue, 31 Aug 2021 22:45:43 +0300 Subject: [PATCH 4/4] =?UTF-8?q?=D0=9E=D0=B1=D1=8A=D0=B5=D0=B4=D0=B8=D0=BD?= =?UTF-8?q?=D0=B5=D0=BD=D0=BD=D1=8B=D0=B9=20=D0=B2=D0=B0=D1=80=D0=B8=D0=B0?= =?UTF-8?q?=D0=BD=D1=82=20=D1=81=D1=82=D0=B0=D1=80=D0=BE=D0=B9=20=D0=B8=20?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D0=BE=D0=B9=20=D0=B4=D0=B8=D0=B0=D0=B3=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=B8=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UnreachableCodeDiagnostic.java | 56 +++++++++++++++++++ .../UnreachableCodeDiagnosticTest.java | 9 +-- .../diagnostics/UnreachableCodeDiagnostic.bsl | 12 +++- 3 files changed, 72 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnreachableCodeDiagnostic.java b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnreachableCodeDiagnostic.java index a6b3daa5df3..976d8e2be08 100644 --- a/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnreachableCodeDiagnostic.java +++ b/src/main/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnreachableCodeDiagnostic.java @@ -21,6 +21,8 @@ */ package com.github._1c_syntax.bsl.languageserver.diagnostics; +import com.github._1c_syntax.bsl.languageserver.cfg.CfgBuildingParseTreeVisitor; +import com.github._1c_syntax.bsl.languageserver.cfg.ExitVertex; import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticMetadata; import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticSeverity; import com.github._1c_syntax.bsl.languageserver.diagnostics.metadata.DiagnosticTag; @@ -37,6 +39,7 @@ import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.Deque; import java.util.List; import java.util.stream.Collectors; @@ -110,6 +113,59 @@ private void savePreprocessorRange(Deque nodes, BSLParser.Preprocesso } } + @Override + public ParseTree visitSubCodeBlock(BSLParser.SubCodeBlockContext ctx) { + errorRanges.clear(); + super.visitSubCodeBlock(ctx); + appendUnreachableCode(ctx.codeBlock()); + return ctx; + } + + @Override + public ParseTree visitFileCodeBlock(BSLParser.FileCodeBlockContext ctx) { + errorRanges.clear(); + super.visitFileCodeBlock(ctx); + appendUnreachableCode(ctx.codeBlock()); + return ctx; + } + + private void appendUnreachableCode(BSLParser.CodeBlockContext ctx) { + var builder = new CfgBuildingParseTreeVisitor(); + builder.producePreprocessorConditions(true); + builder.produceLoopIterations(false); + builder.determineAdjacentDeadCode(false); + + var graph = builder.buildGraph(ctx); + var deadCode = graph.vertexSet().stream() + .filter(vertex -> vertex != graph.getEntryPoint() && vertex.getClass() != ExitVertex.class) + .filter(vertex -> graph.inDegreeOf(vertex) == 0) + .flatMap(vertex -> vertex.getAst().stream()) + .sorted(Comparator.comparingInt(bslParserRuleContext -> bslParserRuleContext.getStart().getLine())) + .map(Ranges::create) + .collect(Collectors.toList()); + + + var newRanges = new ArrayList(); + for (var range : deadCode) { + var alreadyDetected = false; + for (Range detectedRange : errorRanges) { + var pos = new Position(range.getStart().getLine(), range.getStart().getCharacter()); + if (Ranges.containsPosition(detectedRange, pos)) { + alreadyDetected = true; + break; + } + } + if(!alreadyDetected) { + newRanges.add(range); + } + } + + for (var range : newRanges) { + diagnosticStorage.addDiagnostic(range); + } + + } + @Override public ParseTree visitContinueStatement(BSLParser.ContinueStatementContext ctx) { findAndAddDiagnostic(ctx); diff --git a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnreachableCodeDiagnosticTest.java b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnreachableCodeDiagnosticTest.java index 3f7dd30b76c..f2c5c73ff25 100644 --- a/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnreachableCodeDiagnosticTest.java +++ b/src/test/java/com/github/_1c_syntax/bsl/languageserver/diagnostics/UnreachableCodeDiagnosticTest.java @@ -38,7 +38,7 @@ class UnreachableCodeDiagnosticTest extends AbstractDiagnosticTest diagnostics = getDiagnostics(); - assertThat(diagnostics).hasSize(15); + assertThat(diagnostics).hasSize(16); assertThat(diagnostics, true) .hasRange(12, 12, 20) .hasRange(21, 12, 20) @@ -52,9 +52,10 @@ void test() { .hasRange(102, 8, 17) .hasRange(108, 16, 111, 29) .hasRange(138, 4, 16) - .hasRange(161, 4, 13) - .hasRange(166, 4, 168, 13) - .hasRange(172, 0, 9); + .hasRange(163, 4, 22) + .hasRange(171, 4, 13) + .hasRange(176, 4, 178, 13) + .hasRange(182, 0, 9); } @Test diff --git a/src/test/resources/diagnostics/UnreachableCodeDiagnostic.bsl b/src/test/resources/diagnostics/UnreachableCodeDiagnostic.bsl index 6d4c9f5566d..fb9a163c8a8 100644 --- a/src/test/resources/diagnostics/UnreachableCodeDiagnostic.bsl +++ b/src/test/resources/diagnostics/UnreachableCodeDiagnostic.bsl @@ -154,6 +154,16 @@ КонецФункции #КонецОбласти +Функция ДосрочныйВыход() + Если А Тогда + Возврат 1; + Иначе + Возврат 2; + КонецЕсли; + + ТутОшибка = Истина; // <- недостижимый код +КонецФункции + #Если Сервер Тогда Возврат; #Иначе @@ -170,4 +180,4 @@ КонецЕсли; Возврат; -Метод2(); // Ошибка: После Возврат +Метод2(); // Ошибка: После Возврат \ No newline at end of file