From e09b1a978b14ebcfd02aa231a50a2b10a3a7d293 Mon Sep 17 00:00:00 2001
From: Snjezana Peco <snjezana.peco@redhat.com>
Date: Tue, 28 Apr 2020 22:54:36 +0200
Subject: [PATCH] Code folding is buggy

Signed-off-by: Snjezana Peco <snjezana.peco@redhat.com>
---
 .../handlers/FoldingRangeHandler.java         | 32 ++++++++++++-------
 .../java/org/sample/InvalidInputRange.java    | 11 +++++++
 .../handlers/FoldingRangeHandlerTest.java     | 10 ++++++
 3 files changed, 42 insertions(+), 11 deletions(-)
 create mode 100644 org.eclipse.jdt.ls.tests/projects/maven/foldingRange/src/main/java/org/sample/InvalidInputRange.java

diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/FoldingRangeHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/FoldingRangeHandler.java
index ddc1a6009b..eb908bf4e0 100644
--- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/FoldingRangeHandler.java
+++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/FoldingRangeHandler.java
@@ -82,7 +82,7 @@ private void computeFoldingRanges(List<FoldingRange> foldingRanges, ITypeRoot un
 			scanner.resetTo(shift, shift + range.getLength());
 
 			int start = shift;
-			int token = scanner.getNextToken();
+			int token = 0;
 			Stack<Integer> regionStarts = new Stack<>();
 			while (token != ITerminalSymbols.TokenNameEOF) {
 				start = scanner.getCurrentTokenStartPosition();
@@ -109,19 +109,29 @@ private void computeFoldingRanges(List<FoldingRange> foldingRanges, ITypeRoot un
 					default:
 						break;
 				}
-				token = scanner.getNextToken();
+				token = getNextToken(scanner);
 			}
-
 			computeTypeRootRanges(foldingRanges, unit, scanner);
-		} catch (CoreException |
-
-				InvalidInputException e) {
+		} catch (CoreException e) {
 			JavaLanguageServerPlugin.logException("Problem with folding range for " + unit.getPath().toPortableString(), e);
 			monitor.setCanceled(true);
 		}
 	}
 
-	private void computeTypeRootRanges(List<FoldingRange> foldingRanges, ITypeRoot unit, IScanner scanner) throws CoreException, InvalidInputException {
+	private int getNextToken(IScanner scanner) {
+		int token = 0;
+		while (token == 0) {
+			try {
+				token = scanner.getNextToken();
+			} catch (InvalidInputException e) {
+				// ignore
+				// JavaLanguageServerPlugin.logException("Problem with folding range", e);
+			}
+		}
+		return token;
+	}
+
+	private void computeTypeRootRanges(List<FoldingRange> foldingRanges, ITypeRoot unit, IScanner scanner) throws CoreException {
 		if (unit.hasChildren()) {
 			for (IJavaElement child : unit.getChildren()) {
 				if (child instanceof IImportContainer) {
@@ -136,7 +146,7 @@ private void computeTypeRootRanges(List<FoldingRange> foldingRanges, ITypeRoot u
 		}
 	}
 
-	private void computeTypeRanges(List<FoldingRange> foldingRanges, IType unit, IScanner scanner) throws CoreException, InvalidInputException {
+	private void computeTypeRanges(List<FoldingRange> foldingRanges, IType unit, IScanner scanner) throws CoreException {
 		ISourceRange typeRange = unit.getSourceRange();
 		foldingRanges.add(new FoldingRange(scanner.getLineNumber(unit.getNameRange().getOffset()) - 1, scanner.getLineNumber(typeRange.getOffset() + typeRange.getLength()) - 1));
 		IJavaElement[] children = unit.getChildren();
@@ -149,7 +159,7 @@ private void computeTypeRanges(List<FoldingRange> foldingRanges, IType unit, ISc
 		}
 	}
 
-	private void computeMethodRanges(List<FoldingRange> foldingRanges, IMethod method, IScanner scanner) throws CoreException, InvalidInputException {
+	private void computeMethodRanges(List<FoldingRange> foldingRanges, IMethod method, IScanner scanner) throws CoreException {
 		ISourceRange sourceRange = method.getSourceRange();
 		final int shift = sourceRange.getOffset();
 		scanner.resetTo(shift, shift + sourceRange.getLength());
@@ -157,7 +167,7 @@ private void computeMethodRanges(List<FoldingRange> foldingRanges, IMethod metho
 		foldingRanges.add(new FoldingRange(scanner.getLineNumber(method.getNameRange().getOffset()) - 1, scanner.getLineNumber(shift + sourceRange.getLength()) - 1));
 
 		int start = shift;
-		int token = scanner.getNextToken();
+		int token = 0;
 		Stack<Integer> leftParens = null;
 		int prevCaseLine = -1;
 		Map<Integer, Integer> candidates = new HashMap<>();
@@ -208,7 +218,7 @@ private void computeMethodRanges(List<FoldingRange> foldingRanges, IMethod metho
 				default:
 					break;
 			}
-			token = scanner.getNextToken();
+			token = getNextToken(scanner);
 		}
 
 		for (Map.Entry<Integer, Integer> entry : candidates.entrySet()) {
diff --git a/org.eclipse.jdt.ls.tests/projects/maven/foldingRange/src/main/java/org/sample/InvalidInputRange.java b/org.eclipse.jdt.ls.tests/projects/maven/foldingRange/src/main/java/org/sample/InvalidInputRange.java
new file mode 100644
index 0000000000..d11c68d99a
--- /dev/null
+++ b/org.eclipse.jdt.ls.tests/projects/maven/foldingRange/src/main/java/org/sample/InvalidInputRange.java
@@ -0,0 +1,11 @@
+package org.sample;
+
+/**
+ * InvalidInputRange
+ */
+public class InvalidInputRange {
+
+    void foo() {
+        char c = '';
+    }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/FoldingRangeHandlerTest.java b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/FoldingRangeHandlerTest.java
index 63b6b92c56..52a5392396 100644
--- a/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/FoldingRangeHandlerTest.java
+++ b/org.eclipse.jdt.ls.tests/src/org/eclipse/jdt/ls/core/internal/handlers/FoldingRangeHandlerTest.java
@@ -70,6 +70,16 @@ public void testErrorTypes() throws Exception {
 		assertHasFoldingRange(5, 7, null, foldingRanges);
 	}
 
+	@Test
+	public void testInvalidInput() throws Exception {
+		String className = "org.sample.InvalidInputRange";
+		List<FoldingRange> foldingRanges = getFoldingRanges(className);
+		assertTrue(foldingRanges.size() == 3);
+		assertHasFoldingRange(2, 4, "comment", foldingRanges);
+		assertHasFoldingRange(5, 10, null, foldingRanges);
+		assertHasFoldingRange(7, 9, null, foldingRanges);
+	}
+
 	@Test
 	public void testRegionFoldingRanges() throws Exception {
 		String className = "org.sample.RegionFoldingRange";