public ArrayList<StructureSkipSuggestion> getParentSkipSuggestions(int failureIndex) {
   ArrayList<StructureSkipSuggestion> parentSkips = new ArrayList<StructureSkipSuggestion>();
   int errorLineIndex = failureIndex;
   int maxBW = Math.max(failureIndex - MAX_NR_OF_LINES, 0);
   int nrOfStructs = 0;
   while (errorLineIndex > maxBW && nrOfStructs < MAX_NR_OF_STRUCTURES) {
     nrOfStructs++;
     int startSkipIndex = findParentBegin(errorLineIndex);
     ArrayList<StructureSkipSuggestion> skips = selectRegion(startSkipIndex);
     if (skips.isEmpty()) {
       StructureSkipSuggestion closingSkip = new StructureSkipSuggestion();
       closingSkip.setSkipLocations(
           IndentInfo.cloneIndentInfo(getHistory().getLine(startSkipIndex)),
           IndentInfo.cloneIndentInfo(getHistory().getLine(failureIndex)),
           startSkipIndex,
           failureIndex);
       parentSkips.add(closingSkip);
     }
     parentSkips.addAll(skips);
     if (skips.size() > 0) errorLineIndex = skips.get(0).getIndexHistoryStart();
     else errorLineIndex = -1;
   }
   addNextRegionMerges(parentSkips);
   return parentSkips;
 }
 private ArrayList<StructureSkipSuggestion> getCurrentAndNextSkipSuggestions(int failureIndex) {
   ArrayList<StructureSkipSuggestion> nextRegions = new ArrayList<StructureSkipSuggestion>();
   ArrayList<StructureSkipSuggestion> currRegions = selectRegion(failureIndex);
   int fwMax = failureIndex + MAX_NR_OF_LINES;
   int lineIndex = failureIndex;
   int nrOfStructs = 0;
   int indentValueStart = -1;
   if (currRegions.size() > 0)
     indentValueStart = currRegions.get(0).getStartSkip().getIndentValue();
   do {
     nrOfStructs++;
     for (StructureSkipSuggestion r : currRegions) {
       if (r.getAdditionalTokens().length == 0) nextRegions.add(r);
     }
     if (!currRegions.isEmpty()) {
       lineIndex = currRegions.get(0).getIndexHistoryEnd();
       if (currRegions.get(0).getStartSkip().getIndentValue() >= indentValueStart) {
         // System.out.println(currRegions.get(0).getIndexHistoryStart()+" => "+
         // currRegions.get(0).getIndexHistoryEnd());
         currRegions = selectRegion(currRegions.get(0).getIndexHistoryEnd());
       } else currRegions.clear(); // no dedent allowed
     }
   } while (nrOfStructs < MAX_NR_OF_STRUCTURES && lineIndex < fwMax && !currRegions.isEmpty());
   return nextRegions;
 }
 public ArrayList<StructureSkipSuggestion> getSibblingSurroundingSuggestions(int failureIndex) {
   ArrayList<StructureSkipSuggestion> surroundingSkips = new ArrayList<StructureSkipSuggestion>();
   ArrayList<StructureSkipSuggestion> priorSiblings = getPriorRegions(failureIndex);
   ArrayList<StructureSkipSuggestion> nextSiblings =
       getCurrentAndNextSkipSuggestions(failureIndex);
   if (nextSiblings.size() > 1 && priorSiblings.size() > 0) {
     nextSiblings.remove(0);
     StructureSkipSuggestion nextSuggestion = null;
     StructureSkipSuggestion priorSuggestion = null;
     int j = 0;
     int i = 0;
     while (i < nextSiblings.size() || j < priorSiblings.size()) {
       if (i < nextSiblings.size()) {
         nextSuggestion = nextSiblings.get(i);
         i++;
       }
       if (j < priorSiblings.size()) {
         priorSuggestion = priorSiblings.get(j);
         j++;
       }
       StructureSkipSuggestion mergedSkip = mergeRegions(nextSuggestion, priorSuggestion);
       surroundingSkips.add(mergedSkip);
       if (j < priorSiblings.size()) {
         priorSuggestion = priorSiblings.get(j);
         if (priorSuggestion.getAdditionalTokens().length != 0) {
           StructureSkipSuggestion mergedSkipPlus = mergeRegions(nextSuggestion, priorSuggestion);
           surroundingSkips.add(mergedSkipPlus);
           j++;
         }
       }
     }
   }
   return surroundingSkips;
 }
 private void addNextRegionMerges(ArrayList<StructureSkipSuggestion> result) {
   ArrayList<StructureSkipSuggestion> includeNexts = new ArrayList<StructureSkipSuggestion>();
   for (StructureSkipSuggestion skip : result) {
     for (StructureSkipSuggestion skipFW : selectRegion(skip.getIndexHistoryEnd())) {
       includeNexts.add(mergeRegions(skipFW, skip));
     }
   }
   result.addAll(includeNexts);
 }
 public StructureSkipSuggestion getErroneousPrefix(int failureIndex) {
   StructureSkipSuggestion prefix = new StructureSkipSuggestion();
   if (getHistory().getIndexLastLine() >= 0)
     prefix.setSkipLocations(
         IndentInfo.cloneIndentInfo(getHistory().getLine(0)),
         IndentInfo.cloneIndentInfo(getHistory().getLine(failureIndex)),
         0,
         failureIndex);
   return prefix;
 }
 public ArrayList<StructureSkipSuggestion> getBlockSuggestions(int structStartIndex) {
   ArrayList<StructureSkipSuggestion> result = getCurrentRegionSkips(structStartIndex);
   int endIndex =
       Math.min(getHistory().getIndexLastLine() + 1, structStartIndex + MAX_NR_OF_LINES);
   for (int i = structStartIndex; i < endIndex; i++) {
     IndentInfo startSkip = IndentInfo.cloneIndentInfo(getHistory().getLine(structStartIndex));
     IndentInfo endSkip = IndentInfo.cloneIndentInfo(getHistory().getLine(i));
     StructureSkipSuggestion block = new StructureSkipSuggestion();
     block.setSkipLocations(startSkip, endSkip, structStartIndex, i);
     result.add(block);
   }
   return result;
 }
 private ArrayList<StructureSkipSuggestion> selectRegion(int indexLine) {
   if (isScopeClosingLine(indexLine)) return new ArrayList<StructureSkipSuggestion>();
   ArrayList<Integer> endLocations = findCurrentEnd(indexLine);
   ArrayList<StructureSkipSuggestion> skipSuggestions = new ArrayList<StructureSkipSuggestion>();
   IndentInfo startLine = IndentInfo.cloneIndentInfo(getHistory().getLine(indexLine));
   for (Integer endSkipIndex : endLocations) {
     if (endSkipIndex > indexLine) {
       IndentInfo endSkip = IndentInfo.cloneIndentInfo(getHistory().getLine(endSkipIndex));
       StructureSkipSuggestion skipConstruct = new StructureSkipSuggestion();
       skipConstruct.setSkipLocations(startLine, endSkip, indexLine, endSkipIndex);
       skipSuggestions.add(skipConstruct);
       addSeparatorIncludingRegion_Forwards(skipSuggestions, skipConstruct);
       addSeperatorIncludingRegion_Backwards(skipSuggestions, skipConstruct);
     }
   }
   return skipSuggestions;
 }
 public ArrayList<StructureSkipSuggestion> getSibblingBackwardSuggestions(int failureIndex) {
   ArrayList<StructureSkipSuggestion> bwSkips = new ArrayList<StructureSkipSuggestion>();
   ArrayList<StructureSkipSuggestion> priorSiblings = getPriorRegions(failureIndex);
   ArrayList<StructureSkipSuggestion> currentRegionSuggestions = selectRegion(failureIndex);
   if (currentRegionSuggestions.isEmpty())
     currentRegionSuggestions = selectPrevRegion(failureIndex);
   for (StructureSkipSuggestion currSugestion : currentRegionSuggestions) {
     for (int i = 0; i < priorSiblings.size(); i++) {
       StructureSkipSuggestion priorSuggestion = priorSiblings.get(i);
       if (currSugestion.getAdditionalTokens().length
           == 0) { // ignore suggestions based on adding the separator
         StructureSkipSuggestion mergedSkip = mergeRegions(currSugestion, priorSuggestion);
         bwSkips.add(mergedSkip);
       }
     }
   }
   return bwSkips;
 }
 private StructureSkipSuggestion mergeRegions(
     StructureSkipSuggestion fwSuggestion, StructureSkipSuggestion bwSuggestion) {
   StructureSkipSuggestion mergedSkip = new StructureSkipSuggestion();
   mergedSkip.setSkipLocations(
       IndentInfo.cloneIndentInfo(bwSuggestion.getStartSkip()),
       IndentInfo.cloneIndentInfo(fwSuggestion.getEndSkip()),
       bwSuggestion.getIndexHistoryStart(),
       fwSuggestion.getIndexHistoryEnd());
   mergedSkip.setAdditionalTokens(bwSuggestion.getAdditionalTokens());
   return mergedSkip;
 }
 public ArrayList<StructureSkipSuggestion> getZoomOnPreviousSuggestions(
     StructureSkipSuggestion prevRegion) {
   ArrayList<StructureSkipSuggestion> result = new ArrayList<StructureSkipSuggestion>();
   if (!prevRegion.canBeDecomposed()) {
     return result;
   }
   ArrayList<Integer> indentLevels = new ArrayList<Integer>();
   int startIndexZoom =
       Math.max(
           prevRegion.getIndexHistoryStart(), prevRegion.getIndexHistoryEnd() - MAX_NR_OF_LINES);
   for (int i = startIndexZoom; i < prevRegion.getIndexHistoryEnd(); i++) {
     int indentOfLine = getHistory().getLine(i).getIndentValue();
     if (!indentLevels.contains(indentOfLine)) indentLevels.add(indentOfLine);
   }
   Collections.sort(indentLevels);
   indentLevels.remove(0);
   // System.out.println(indentLevels);
   int indentOfLevel;
   int lineIndex;
   for (int level = 0; level < indentLevels.size(); level++) {
     indentOfLevel = indentLevels.get(level);
     lineIndex = startIndexZoom;
     while (lineIndex < prevRegion.getIndexHistoryEnd()) {
       int indentOfLine = getHistory().getLine(lineIndex).getIndentValue();
       if (indentOfLine == indentOfLevel) {
         ArrayList<StructureSkipSuggestion> regions = selectRegion(lineIndex);
         if (regions.size() > 0) {
           // System.out.println("index: "+lineIndex +" indent: "+indentOfLevel);
           lineIndex = regions.get(0).getIndexHistoryEnd();
           // System.out.println();
           // System.out.println(getHistory().getFragment(regions.get(0)));
           // System.out.println();
           // System.out.println("new index: "+lineIndex +" end indent:
           // "+getHistory().getLine(lineIndex).getIndentValue());
           Collections.reverse(regions);
           result.addAll(regions);
         } else lineIndex++;
       } else lineIndex++;
     }
   }
   Collections.reverse(result);
   return result;
 }
 private void addSeparatorIncludingRegion_Forwards(
     ArrayList<StructureSkipSuggestion> regions, StructureSkipSuggestion aRegion) {
   if (isSeparatorStartingLine(aRegion.getIndexHistoryEnd())) {
     IndentInfo startSkip = IndentInfo.cloneIndentInfo(aRegion.getStartSkip());
     IndentInfo endSkip = IndentInfo.cloneIndentInfo(aRegion.getEndSkip());
     int indentShift = separatorIndent(aRegion.getIndexHistoryEnd()) - endSkip.getIndentValue();
     endSkip.setTokensSeen(endSkip.getTokensSeen() + indentShift);
     StructureSkipSuggestion previousRegion3 = new StructureSkipSuggestion();
     previousRegion3.setSkipLocations(
         startSkip, endSkip, aRegion.getIndexHistoryStart(), aRegion.getIndexHistoryEnd());
     regions.add(previousRegion3);
   }
 }
 private ArrayList<StructureSkipSuggestion> selectPrevRegion(int indexEnd) {
   ArrayList<StructureSkipSuggestion> prevRegions = new ArrayList<StructureSkipSuggestion>();
   boolean onClosing = isScopeClosingLine(indexEnd);
   int indexStart = findPreviousBegin(indexEnd, onClosing);
   if (onClosing) {
     if (indexEnd > 0) {
       if (isScopeClosingLine(indexEnd - 1)) prevRegions.addAll(selectPrevRegion(indexEnd - 1));
       else prevRegions.addAll(selectRegion(indexEnd - 1));
     }
     indexEnd++;
   }
   IndentInfo endSkip = IndentInfo.cloneIndentInfo(getHistory().getLine(indexEnd));
   if (indexStart < 0) return prevRegions;
   IndentInfo startSkip = IndentInfo.cloneIndentInfo(getHistory().getLine(indexStart));
   StructureSkipSuggestion previousRegion = new StructureSkipSuggestion();
   previousRegion.setSkipLocations(startSkip, endSkip, indexStart, indexEnd);
   prevRegions.add(previousRegion);
   addSeperatorIncludingRegion_Backwards(prevRegions, previousRegion);
   addSeparatorIncludingRegion_Forwards(prevRegions, previousRegion);
   return prevRegions;
 }
 private void addSeperatorIncludingRegion_Backwards(
     ArrayList<StructureSkipSuggestion> prevRegions, StructureSkipSuggestion previousRegion) {
   int indexStart = previousRegion.getIndexHistoryStart();
   if (indexStart > 0 && isSeparatorEndingLine(indexStart - 1)) {
     char[] toParse = structTokens.removeSeparatorAtTheEnd(readLine(indexStart - 1));
     IndentInfo startSkip2 = IndentInfo.cloneIndentInfo(getHistory().getLine(indexStart - 1));
     IndentInfo endSkip2 = IndentInfo.cloneIndentInfo(previousRegion.getEndSkip());
     StructureSkipSuggestion previousRegion2 = new StructureSkipSuggestion();
     previousRegion2.setSkipLocations(
         startSkip2, endSkip2, indexStart - 1, previousRegion.getIndexHistoryEnd());
     previousRegion2.setAdditionalTokens(toParse);
     prevRegions.add(previousRegion2);
   }
 }