protected void addExpressionStyles(int lineOffset, int lineLenght, Vector<StyleRange> styles) {
   final String content = document.get();
   for (Expression exp : expressions) {
     if (supportedTypes.keySet().contains(exp.getType())) {
       try {
         int i = lineOffset;
         IRegion index = null;
         index = finder.find(i, exp.getName(), true, true, true, false);
         while (index != null && index.getOffset() < lineOffset + lineLenght) {
           if (PatternLineStyleListener.isNotEscapeWord(content, index.getOffset())) {
             styles.add(
                 new StyleRange(
                     index.getOffset(),
                     index.getLength(),
                     Display.getDefault().getSystemColor(supportedTypes.get(exp.getType())),
                     null,
                     SWT.BOLD));
           }
           i = index.getOffset() + index.getLength();
           if (i < lineOffset + lineLenght) {
             index = finder.find(i, exp.getName(), true, true, true, false);
           } else {
             index = null;
           }
         }
       } catch (BadLocationException e) {
         // Ignore
       }
     }
   }
 }
  /**
   * Determines whether each line is prefixed by one of the prefixes.
   *
   * @param startLine Start line in document
   * @param endLine End line in document
   * @param prefixes Possible comment prefixes
   * @param document The document
   * @return <code>true</code> iff each line from <code>startLine</code> to and including <code>
   *     endLine</code> is prepended by one of the <code>prefixes</code>, ignoring whitespace at the
   *     begin of line
   */
  private boolean isBlockCommented(
      int startLine, int endLine, String[] prefixes, IDocument document) {

    try {

      // check for occurrences of prefixes in the given lines
      for (int i = startLine; i <= endLine; i++) {

        IRegion line = document.getLineInformation(i);
        String text = document.get(line.getOffset(), line.getLength());

        int[] found = TextUtilities.indexOf(prefixes, text, 0);

        if (found[0] == -1)
          // found a line which is not commented
          return false;

        String s = document.get(line.getOffset(), found[0]);
        s = s.trim();
        if (s.length() != 0)
          // found a line which is not commented
          return false;
      }

      return true;

    } catch (BadLocationException x) {
      // should not happen
      // FIXME			Activator.getPlugin().log(x);
    }

    return false;
  }
Beispiel #3
0
  /**
   * Returns the indentation of the line <code>line</code> in <code>document</code>. The returned
   * string may contain pairs of leading slashes that are considered part of the indentation. The
   * space before the asterix in a javadoc-like comment is not considered part of the indentation.
   *
   * @param document the document
   * @param line the line
   * @return the indentation of <code>line</code> in <code>document</code>
   * @throws BadLocationException if the document is changed concurrently
   */
  private static String getCurrentIndent(IDocument document, int line) throws BadLocationException {
    IRegion region = document.getLineInformation(line);
    int from = region.getOffset();
    int endOffset = region.getOffset() + region.getLength();

    // go behind line comments
    int to = from;
    while (to < endOffset - 2 && document.get(to, 2).equals(SLASHES)) to += 2;

    while (to < endOffset) {
      char ch = document.getChar(to);
      if (!Character.isWhitespace(ch)) break;
      to++;
    }

    // don't count the space before javadoc like, asterix-style comment lines
    if (to > from && to < endOffset - 1 && document.get(to - 1, 2).equals(" *")) { // $NON-NLS-1$
      String type =
          TextUtilities.getContentType(document, IJavaPartitions.JAVA_PARTITIONING, to, true);
      if (type.equals(IJavaPartitions.JAVA_DOC)
          || type.equals(IJavaPartitions.JAVA_MULTI_LINE_COMMENT)) to--;
    }

    return document.get(from, to - from);
  }
  /**
   * Indents line <code>line</code> in <code>document</code> with <code>indent</code>. Leaves
   * leading comment signs alone.
   *
   * @param document the document
   * @param line the line
   * @param indent the indentation to insert
   * @param tabLength the length of a tab
   * @throws BadLocationException on concurrent document modification
   */
  private void addIndent(Document document, int line, CharSequence indent, int tabLength)
      throws BadLocationException {
    IRegion region = document.getLineInformation(line);
    int insert = region.getOffset();
    int endOffset = region.getOffset() + region.getLength();

    // Compute insert after all leading line comment markers
    int newInsert = insert;
    while (newInsert < endOffset - 2 && document.get(newInsert, 2).equals(LINE_COMMENT))
      newInsert += 2;

    // Heuristic to check whether it is commented code or just a comment
    if (newInsert > insert) {
      int whitespaceCount = 0;
      int i = newInsert;
      while (i < endOffset - 1) {
        char ch = document.get(i, 1).charAt(0);
        if (!Character.isWhitespace(ch)) break;
        whitespaceCount = whitespaceCount + computeVisualLength(ch, tabLength);
        i++;
      }

      if (whitespaceCount != 0 && whitespaceCount >= CodeFormatterUtil.getIndentWidth(fProject))
        insert = newInsert;
    }

    // Insert indent
    document.replace(insert, 0, indent.toString());
  }
  public void run(IAction action) {
    PyEdit pyEdit = getPyEdit();
    PySelection ps = new PySelection(pyEdit);
    if (ps.getSelLength() != 0) {
      return;
    }
    try {
      IDocument doc = ps.getDoc();
      char c = doc.getChar(ps.getAbsoluteCursorOffset() - 1);
      boolean opening = StringUtils.isOpeningPeer(c);
      boolean closing = org.python.pydev.shared_core.string.StringUtils.isClosingPeer(c);

      if (opening || closing) {
        PythonPairMatcher matcher = new PythonPairMatcher();
        IRegion match = matcher.match(doc, ps.getAbsoluteCursorOffset());
        if (match != null) {
          if (closing) {
            pyEdit.setSelection(match.getOffset() + 1, 0);
          } else { // opening
            pyEdit.setSelection(match.getOffset() + match.getLength(), 0);
          }
        }
      }
    } catch (BadLocationException e) {
      return;
    }
  }
 /**
  * @see com.mulgasoft.emacsplus.commands.EmacsPlusCmdHandler#transform(ITextEditor, IDocument,
  *     ITextSelection, ExecutionEvent)
  */
 @Override
 protected int transform(
     ITextEditor editor, IDocument document, ITextSelection currentSelection, ExecutionEvent event)
     throws BadLocationException {
   int result = getCursorOffset(editor, currentSelection);
   // get the selection encompassing the appropriate set of lines
   ITextSelection selection = getLineSelection(editor, document, currentSelection);
   if (selection != null) {
     int offset = selection.getOffset();
     int endOffset = offset + selection.getLength();
     int begin = document.getLineOfOffset(offset);
     int end = document.getLineOfOffset(endOffset);
     if (begin != end && begin < end) {
       ArrayList<String> alst = new ArrayList<String>();
       IRegion region = document.getLineInformation(begin);
       // get text from point or mark
       alst.add(document.get(offset, region.getLength() - (offset - region.getOffset())));
       for (int i = begin + 1; i < end; i++) {
         region = document.getLineInformation(i);
         // get full line of text
         alst.add(document.get(region.getOffset(), region.getLength()));
       }
       region = document.getLineInformation(end);
       // get text to point or mark
       alst.add(document.get(region.getOffset(), endOffset - region.getOffset()));
       Collections.sort(alst, (getComparator(isUniversalPresent())));
       updateLines(document, selection, alst.toArray(new String[0]));
     } else {
       EmacsPlusUtils.showMessage(editor, NO_REGION, true);
     }
   } else {
     EmacsPlusUtils.showMessage(editor, NO_REGION, true);
   }
   return result;
 }
Beispiel #7
0
  /* (non-Javadoc)
   * @see org.eclipse.jface.text.ITextHover#getHoverInfo(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion)
   */
  public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
    ScriptStackFrame frame = getFrame();
    if (frame == null) {
      return null;
    }
    IDocument document = textViewer.getDocument();
    if (document == null) {
      return null;
    }
    try {
      String str =
          TextUtilities.getContentType(
              document,
              IDocumentExtension3.DEFAULT_PARTITIONING,
              hoverRegion.getOffset() + 1,
              true);

      String variableName = document.get(hoverRegion.getOffset(), hoverRegion.getLength());

      if (JSPartitionScanner.JS_KEYWORD.equals(str) && !"this".equals(variableName)) // $NON-NLS-1$
      {
        return null;
      }
      ScriptValue var = ((ScriptDebugTarget) frame.getDebugTarget()).evaluate(frame, variableName);
      if (var != null) {
        return getVariableText(var);
      }
    } catch (BadLocationException e) {
      return null;
    }
    return null;
  }
  /** @see IPresentationDamager#getDamageRegion(ITypedRegion, DocumentEvent, boolean) */
  public IRegion getDamageRegion(
      final ITypedRegion partition,
      final DocumentEvent event,
      final boolean documentPartitioningChanged) {
    if (!documentPartitioningChanged) {
      try {

        final IRegion info = fDocument.getLineInformationOfOffset(event.getOffset());
        final int start = Math.max(partition.getOffset(), info.getOffset());

        int end =
            event.getOffset()
                + (event.getText() == null ? event.getLength() : event.getText().length());

        if ((info.getOffset() <= end) && (end <= info.getOffset() + info.getLength())) {
          // optimize the case of the same line
          end = info.getOffset() + info.getLength();
        } else {
          end = endOfLineOf(end);
        }

        end = Math.min(partition.getOffset() + partition.getLength(), end);
        return new Region(start, end - start);

      } catch (final BadLocationException x) {
      }
    }

    return partition;
  }
 protected CompoundRegion[] getRegionsWithoutWhiteSpaces(
     IStructuredDocument model, IRegion reg, CSSCleanupStrategy stgy) {
   int start = reg.getOffset();
   int end = reg.getOffset() + reg.getLength() - 1;
   ArrayList list = new ArrayList();
   IStructuredDocumentRegion flatNode = model.getRegionAtCharacterOffset(start);
   while (flatNode != null && flatNode.getStartOffset() <= end) {
     ITextRegionList regionList = flatNode.getRegions();
     Iterator it = regionList.iterator();
     while (it.hasNext()) {
       ITextRegion region = (ITextRegion) it.next();
       if (flatNode.getStartOffset(region) < start) continue;
       if (end < flatNode.getStartOffset(region)) break;
       if (region.getType() != CSSRegionContexts.CSS_S
           || (isCleanup() && !stgy.isFormatSource())) // for
         // not
         // formatting
         // case
         // on
         // cleanup
         // action
         list.add(new CompoundRegion(flatNode, region));
     }
     flatNode = flatNode.getNext();
   }
   if (list.size() > 0) {
     CompoundRegion[] regions = new CompoundRegion[list.size()];
     list.toArray(regions);
     return regions;
   }
   return new CompoundRegion[0];
 }
 public static String getLineContentsToCursor(IDocument doc, int offset)
     throws BadLocationException {
   int lineOfOffset = doc.getLineOfOffset(offset);
   IRegion lineInformation = doc.getLineInformation(lineOfOffset);
   String lineToCursor =
       doc.get(lineInformation.getOffset(), offset - lineInformation.getOffset());
   return lineToCursor;
 }
Beispiel #11
0
  /**
   * Formats the given selection
   *
   * @see IFormatter
   */
  public void formatSelection(
      IDocument doc, int[] regionsForSave, IPyEdit edit, PySelection ps, FormatStd formatStd) {
    //        Formatter formatter = new Formatter();
    //        formatter.formatSelection(doc, startLine, endLineIndex, edit, ps);

    @SuppressWarnings({"rawtypes", "unchecked"})
    List<Tuple3<Integer, Integer, String>> replaces = new ArrayList();

    String docContents = doc.get();
    String delimiter = PySelection.getDelimiter(doc);
    IDocument formatted;
    try {
      formatted = new Document(formatAll(formatStd, true, docContents, delimiter));
    } catch (SyntaxErrorException e) {
      return;
    }
    // Actually replace the formatted lines: in our formatting, lines don't change, so, this is OK
    // :)
    try {
      for (int i : regionsForSave) {
        IRegion r = doc.getLineInformation(i);
        int iStart = r.getOffset();
        int iEnd = r.getOffset() + r.getLength();

        String line = PySelection.getLine(formatted, i);
        replaces.add(new Tuple3<Integer, Integer, String>(iStart, iEnd - iStart, line));
      }

    } catch (BadLocationException e) {
      Log.log(e);
      return;
    }

    // Apply the formatting from bottom to top (so that the indexes are still valid).
    Collections.reverse(replaces);
    for (Tuple3<Integer, Integer, String> tup : replaces) {
      try {
        doc.replace(tup.o1, tup.o2, tup.o3);
      } catch (BadLocationException e) {
        Log.log(e);
      }
    }

    if (formatStd.addNewLineAtEndOfFile) {
      try {
        int len = doc.getLength();
        if (len > 0) {
          char lastChar = doc.getChar(len - 1);
          if (lastChar != '\r' && lastChar != '\n') {
            doc.replace(len, 0, PySelection.getDelimiter(doc));
          }
        }
      } catch (Throwable e) {
        Log.log(e);
      }
    }
  }
 private int getCodeEnd(IRegion li, String lineText, List<CommonToken> tokens) {
   int j = lineText.length() - 1;
   for (; j >= 0; j--) {
     int offset = li.getOffset() + j;
     if (!skipToken(tokens, offset)) break;
   }
   int endOfCodeInLine = li.getOffset() + j;
   return endOfCodeInLine;
 }
 /**
  * This function replaces all the contents in the current line before the cursor for the contents
  * passed as parameter
  */
 public void replaceLineContentsToSelection(String newContents) throws BadLocationException {
   int lineOfOffset = getDoc().getLineOfOffset(getAbsoluteCursorOffset());
   IRegion lineInformation = getDoc().getLineInformation(lineOfOffset);
   getDoc()
       .replace(
           lineInformation.getOffset(),
           getAbsoluteCursorOffset() - lineInformation.getOffset(),
           newContents);
 }
 private int getCodeStart(IRegion li, String lineText, List<CommonToken> tokens) {
   int k = 0;
   for (; k < lineText.length(); k++) {
     int offset = li.getOffset() + k;
     if (!skipToken(tokens, offset)) break;
   }
   int startOfCodeInLine = li.getOffset() + k;
   return startOfCodeInLine;
 }
 private int getStartOfPreviousLine(int offset) throws BadLocationException {
   int line = document.getLineOfOffset(offset);
   IRegion lineInfo;
   do {
     if (line == 0) return 0;
     lineInfo = document.getLineInformation(--line);
   } while (lineInfo.getLength() == 0 || isQuoted(lineInfo.getOffset()));
   return lineInfo.getOffset();
 }
 /** @return if the region passed is composed of a single line */
 public static boolean endsInSameLine(IDocument document, IRegion region) {
   try {
     int startLine = document.getLineOfOffset(region.getOffset());
     int end = region.getOffset() + region.getLength();
     int endLine = document.getLineOfOffset(end);
     return startLine == endLine;
   } catch (BadLocationException e) {
     return false;
   }
 }
 public static IRegion overlappedRegion(IRegion region, int start, int end) {
   if (overlaps(region, start, end)) {
     int offset = (region.getOffset() <= start) ? start : region.getOffset();
     int length =
         ((end <= region.getOffset() + region.getLength())
                 ? end
                 : region.getOffset() + region.getLength())
             - offset;
     return new FormatRegion(offset, length);
   }
   return null;
 }
 /**
  * Returns the index of the first line whose start offset is in the given text range.
  *
  * @param region the text range in characters where to find the line
  * @param document The document
  * @return the first line whose start index is in the given range, -1 if there is no such line
  */
 private int getFirstCompleteLineOfRegion(IRegion region, IDocument document) {
   try {
     int startLine = document.getLineOfOffset(region.getOffset());
     int offset = document.getLineOffset(startLine);
     if (offset >= region.getOffset()) return startLine;
     offset = document.getLineOffset(startLine + 1);
     return (offset > region.getOffset() + region.getLength() ? -1 : startLine + 1);
   } catch (BadLocationException x) {
     // should not happen
   }
   return -1;
 }
 protected final void formatChildren(ICSSNode node, IRegion region, StringBuffer source) {
   ICSSNode child = node.getFirstChild();
   int start = region.getOffset();
   int end = region.getOffset() + region.getLength();
   boolean first = true;
   while (child != null) {
     int curEnd = ((IndexedRegion) child).getEndOffset();
     StringBuffer childSource = null;
     boolean toFinish = false;
     if (start < curEnd) {
       int curStart = ((IndexedRegion) child).getStartOffset();
       if (curStart < end) {
         // append child
         CSSSourceFormatter formatter =
             (CSSSourceFormatter) ((INodeNotifier) child).getAdapterFor(CSSSourceFormatter.class);
         if (formatter == null) {
           formatter =
               CSSSourceFormatterFactory.getInstance().getSourceFormatter((INodeNotifier) child);
         }
         if (includes(region, curStart, curEnd))
           childSource = ((AbstractCSSSourceFormatter) formatter).formatProc(child);
         else
           childSource =
               ((AbstractCSSSourceFormatter) formatter)
                   .formatProc(child, overlappedRegion(region, curStart, curEnd));
       } else toFinish = true;
     }
     // append between children
     if (!first) {
       curEnd = ((IndexedRegion) child).getStartOffset(); // change
       // only
       // start
       if (start < curEnd) {
         int curStart = ((IndexedRegion) child.getPreviousSibling()).getEndOffset();
         if (curStart < end) {
           String toAppend = (childSource != null) ? new String(childSource) : ""; // $NON-NLS-1$
           if (includes(region, curStart, curEnd))
             formatBefore(node, child, toAppend, source, null);
           else
             formatBefore(
                 node, child, overlappedRegion(region, curStart, curEnd), toAppend, source);
         }
       }
     }
     if (childSource != null) {
       source.append(childSource);
     }
     first = false;
     if (toFinish) break;
     child = child.getNextSibling();
   }
 }
Beispiel #20
0
  protected int endOfLineOf(int offset) throws BadLocationException {

    IRegion info = document.getLineInformationOfOffset(offset);
    if (offset <= info.getOffset() + info.getLength()) return info.getOffset() + info.getLength();

    int line = document.getLineOfOffset(offset);
    try {
      info = document.getLineInformation(line + 1);
      return info.getOffset() + info.getLength();
    } catch (BadLocationException x) {
      return document.getLength();
    }
  }
Beispiel #21
0
  private IRegion modelRange2WidgetRange(IRegion region) {
    ISourceViewer viewer = fEditor.getViewer();
    if (viewer instanceof ITextViewerExtension5) {
      ITextViewerExtension5 extension = (ITextViewerExtension5) viewer;
      return extension.modelRange2WidgetRange(region);
    }

    IRegion visibleRegion = viewer.getVisibleRegion();
    int start = region.getOffset() - visibleRegion.getOffset();
    int end = start + region.getLength();
    if (end > visibleRegion.getLength()) end = visibleRegion.getLength();

    return new Region(start, end - start);
  }
 private String lineFor(final ITextViewer textViewer, final IRegion region) {
   try {
     return textViewer.getDocument().get(region.getOffset(), region.getLength()).trim();
   } catch (final BadLocationException e) {
     FeatureEditorPlugin.instance()
         .error(
             "Couldn't get line at region ("
                 + region.getOffset()
                 + ", "
                 + region.getLength()
                 + ")");
   }
   return null;
 }
  /** In event of partial selection, used to select the full lines involved. */
  public void selectCompleteLine() {
    if (doc.getNumberOfLines() == 1) {
      this.textSelection = new TextSelection(doc, 0, doc.getLength());
      return;
    }
    IRegion endLine = getEndLine();
    IRegion startLine = getStartLine();

    this.textSelection =
        new TextSelection(
            doc,
            startLine.getOffset(),
            endLine.getOffset() + endLine.getLength() - startLine.getOffset());
  }
 /**
  * Creates a region describing the text block (something that starts at the beginning of a line)
  * completely containing the current selection.
  *
  * @param selection The selection to use
  * @param document The document
  * @return the region describing the text block comprising the given selection
  */
 private IRegion getTextBlockFromSelection(ITextSelection selection, IDocument document) {
   try {
     IRegion line = document.getLineInformationOfOffset(selection.getOffset());
     int length =
         selection.getLength() == 0
             ? line.getLength()
             : selection.getLength() + (selection.getOffset() - line.getOffset());
     return new Region(line.getOffset(), length);
   } catch (BadLocationException x) {
     // should not happen
     // JavaPlugin.log(x);
   }
   return null;
 }
Beispiel #25
0
  /**
   * Indents line <code>line</code> in <code>document</code> with <code>indent</code>. Leaves
   * leading comment signs alone.
   *
   * @param document the document
   * @param line the line
   * @param indent the indentation to insert
   * @param commentlines
   * @throws BadLocationException on concurrent document modification
   */
  private static void addIndent(
      IDocument document, int line, CharSequence indent, boolean[] commentlines, int relative)
      throws BadLocationException {
    IRegion region = document.getLineInformation(line);
    int insert = region.getOffset();
    int endOffset = region.getOffset() + region.getLength();

    // go behind line comments
    if (!commentlines[relative]) {
      while (insert < endOffset - 2 && document.get(insert, 2).equals(SLASHES)) insert += 2;
    }

    // insert indent
    document.replace(insert, 0, indent.toString());
  }
  private List<IRegion> getAttributeValueELRegions(ITextViewer viewer) {
    List<IRegion> regions = getAttributeValueRegions(viewer);
    List<IRegion> elRegions = new ArrayList<IRegion>();
    String documentContent = document.get();

    if (documentContent != null) {
      for (IRegion r : regions) {
        int offset = indexOfElBOB(documentContent, r.getOffset());
        if (offset != -1 && offset < r.getOffset() + r.getLength()) {
          elRegions.add(r);
        }
      }
    }
    return elRegions;
  }
  /**
   * @param change
   * @return Map &lt;Integer oldOffset, Integer updatedOffset&gt;
   */
  private static Map<Integer, Integer> getEditChangeOffsetUpdates(TextChange change) {
    TextEditChangeGroup[] editChanges = change.getTextEditChangeGroups();
    Map<Integer, Integer> offsetUpdates = new HashMap<>(editChanges.length);
    for (int i = 0; i < editChanges.length; i++) {
      TextEditChangeGroup editChange = editChanges[i];
      IRegion oldRegion = editChange.getRegion();
      if (oldRegion == null) continue;
      IRegion updatedRegion =
          TextEdit.getCoverage(change.getPreviewEdits(editChange.getTextEdits()));
      if (updatedRegion == null) continue;

      offsetUpdates.put(new Integer(oldRegion.getOffset()), new Integer(updatedRegion.getOffset()));
    }
    return offsetUpdates;
  }
  public static List<IRegion> getRegions(IDocument document, IRegion region) {
    List<IRegion> exclude = new ArrayList<>();

    try {
      Matcher m = JAVA_DOC_TAG.matcher(document.get(region.getOffset(), region.getLength()));

      while (m.find()) {
        exclude.add(new Region(m.start() + region.getOffset(), m.end() - m.start()));
      }
    } catch (BadLocationException e) {
      // OK, do not exclude any regions.
    }

    return SpellingUtils.excludeRegions(region, exclude);
  }
 /**
  * Returns the variable and function names at the current line, or <code>null</code> if none.
  *
  * @param part text editor
  * @param selection text selection
  * @return the variable and function names at the current line, or <code>null</code> if none. The
  *     array has two elements, the first is the variable name, the second is the function name.
  */
 protected String[] getVariableAndFunctionName(IWorkbenchPart part, ISelection selection) {
   ITextEditor editor = getEditor(part);
   if (editor != null && selection instanceof ITextSelection) {
     ITextSelection textSelection = (ITextSelection) selection;
     IDocumentProvider documentProvider = editor.getDocumentProvider();
     try {
       documentProvider.connect(this);
       IDocument document = documentProvider.getDocument(editor.getEditorInput());
       IRegion region = document.getLineInformationOfOffset(textSelection.getOffset());
       String string = document.get(region.getOffset(), region.getLength()).trim();
       if (string.startsWith("var ")) { // $NON-NLS-1$
         String varName = string.substring(4).trim();
         String fcnName =
             getFunctionName(
                 document, varName, document.getLineOfOffset(textSelection.getOffset()));
         return new String[] {varName, fcnName};
       }
     } catch (CoreException e) {
     } catch (BadLocationException e) {
     } finally {
       documentProvider.disconnect(this);
     }
   }
   return null;
 }
  /**
   * Calculates the common scope between the end of one line and the beginning of the next.
   *
   * @param document
   * @param line
   * @param endOfLineScope
   * @return
   * @throws BadLocationException
   */
  private String getScope(IDocument document, int line, String endOfLineScope)
      throws BadLocationException {
    // if this is the last line, just use the scope at the end of it.
    int lines = document.getNumberOfLines();
    if (line + 1 >= lines) {
      return endOfLineScope;
    }

    // now grab the scope at the beginning of the next line...
    IRegion nextLine = document.getLineInformation(line + 1);
    // If the next line is empty, take our end of line scope
    if (nextLine.getLength() == 0) {
      return endOfLineScope;
    }
    String startOfNextLineScope =
        getScopeManager().getScopeAtOffset(document, nextLine.getOffset());

    // Calculate the common prefix between the two!
    StringBuilder builder = new StringBuilder();
    int length = Math.min(endOfLineScope.length(), startOfNextLineScope.length());
    for (int i = 0; i < length; i++) {
      char c = endOfLineScope.charAt(i);
      char o = startOfNextLineScope.charAt(i);
      if (c == o) {
        builder.append(c);
      }
    }
    return builder.toString();
  }