Search in sources :

Example 6 with TokenCursor

use of org.rstudio.studio.client.workbench.views.source.editors.text.ace.TokenCursor in project rstudio by rstudio.

the class SignatureToolTipManager method setAnchor.

// Sets an anchored range for a cursor currently lying
// on an identifier before a '(' (a function call).
private void setAnchor(TokenCursor cursor) {
    if (anchor_ != null) {
        anchor_.detach();
        anchor_ = null;
    }
    TokenCursor endCursor = cursor.cloneCursor();
    if (!endCursor.moveToNextToken())
        return;
    if (!endCursor.valueEquals("("))
        return;
    // this function?
    if (!endCursor.fwdToMatchingToken())
        return;
    Position endPos = endCursor.currentPosition();
    TokenCursor startCursor = cursor.cloneCursor();
    Token lookbehind = startCursor.peekBwd(1);
    if (lookbehind.valueEquals("::") || lookbehind.valueEquals(":::")) {
        if (!startCursor.moveToPreviousToken())
            return;
        if (!startCursor.moveToPreviousToken())
            return;
    }
    Position startPos = startCursor.currentPosition();
    anchor_ = docDisplay_.createAnchoredSelection(startPos, endPos);
}
Also used : TokenCursor(org.rstudio.studio.client.workbench.views.source.editors.text.ace.TokenCursor) Position(org.rstudio.studio.client.workbench.views.source.editors.text.ace.Position) Token(org.rstudio.studio.client.workbench.views.source.editors.text.ace.Token)

Example 7 with TokenCursor

use of org.rstudio.studio.client.workbench.views.source.editors.text.ace.TokenCursor in project rstudio by rstudio.

the class TextEditingTargetRenameHelper method renameInScopeR.

private int renameInScopeR() {
    Position startPosition = editor_.hasSelection() ? editor_.getSelectionStart() : editor_.getCursorPosition();
    TokenCursor cursor = editor_.getSession().getMode().getCodeModel().getTokenCursor();
    if (!cursor.moveToPosition(startPosition, true))
        return 0;
    if (cursor.isRightBracket())
        if (!cursor.moveToPreviousToken())
            return 0;
    editor_.setCursorPosition(cursor.currentPosition());
    // Ensure the scope tree is built, since we use that for determining
    // the scope for the current refactor.
    editor_.buildScopeTree();
    // Validate that we're looking at an R identifier
    String targetValue = cursor.currentValue();
    String targetType = cursor.currentType();
    boolean isRefactorable = cursor.hasType("identifier", "constant.language", "string") || cursor.typeEquals("keyword");
    if (!isRefactorable)
        return 0;
    // If we're refactoring a string, just do it through the whole document.
    if (cursor.typeEquals("string")) {
        editor_.selectAll(cursor.currentValue());
        return editor_.getNativeSelection().getAllRanges().length;
    }
    // form and rename just that argument.
    if (cursor.peekFwd(1).valueEquals("=") && cursor.isWithinFunctionCall()) {
        String argName = cursor.currentValue();
        TokenCursor clone = cursor.cloneCursor();
        while (clone.findOpeningBracket("(", false)) {
            if (!clone.moveToPreviousToken())
                break;
            String functionName = clone.currentValue();
            if (!functionName.equals("function"))
                return renameFunctionArgument(functionName, argName);
        }
    }
    // Determine the appropriate refactoring scope.
    //
    // Algorithm:
    //
    //    1. Get the function scope.
    //    2. If we have an argument of the same name, or function
    //       of the same name, rename in that scope.
    //    3. Otherwise, walk forward from the start of that scope,
    //       looking for assignments.
    //    4. If we discover an assignment, rename in that scope
    //       from that position.
    //    5. Repeat while not at top level.
    //
    // TODO: if renaming a function argument, we should also rename
    //       named usages of that function argument where possible.
    Scope scope = editor_.getScopeAtPosition(cursor.currentPosition());
    // of a scope begins with the function identifier.
    if (cursor.peekFwd(1).isLeftAssign() && cursor.peekFwd(2).valueEquals("function") && !scope.isTopLevel()) {
        scope = scope.getParentScope();
    }
    while (!scope.isTopLevel()) {
        if (scope.isFunction()) {
            ScopeFunction scopeFn = (ScopeFunction) scope;
            String fnName = scopeFn.getFunctionName();
            if (fnName.equals(targetValue))
                return renameVariablesInScope(scope, targetValue, targetType);
            JsArrayString fnArgs = scopeFn.getFunctionArgs();
            for (int i = 0; i < fnArgs.length(); i++) if (fnArgs.get(i).equals(targetValue))
                return renameVariablesInScope(scope, targetValue, targetType);
        }
        if (scope.isChunk())
            return renameVariablesInScope(scope, targetValue, targetType);
        if (!cursor.moveToPosition(scope.getBodyStart(), true))
            continue;
        while (cursor.moveToNextToken()) {
            if (cursor.fwdToMatchingToken())
                continue;
            if (cursor.currentPosition().isAfterOrEqualTo(scope.getEnd()) || cursor.currentPosition().isAfter(startPosition)) {
                break;
            }
            if (cursor.peekFwd(1).isLeftAssign() && !cursor.peekBwd(1).isExtractionOperator()) {
                return renameVariablesInScope(scope, cursor.currentPosition(), targetValue, targetType);
            }
        }
        scope = scope.getParentScope();
    }
    return renameVariablesInScope(scope, targetValue, targetType);
}
Also used : TokenCursor(org.rstudio.studio.client.workbench.views.source.editors.text.ace.TokenCursor) Position(org.rstudio.studio.client.workbench.views.source.editors.text.ace.Position) JsArrayString(com.google.gwt.core.client.JsArrayString) JsArrayString(com.google.gwt.core.client.JsArrayString)

Example 8 with TokenCursor

use of org.rstudio.studio.client.workbench.views.source.editors.text.ace.TokenCursor in project rstudio by rstudio.

the class RoxygenHelper method insertRoxygenSkeleton.

public void insertRoxygenSkeleton() {
    if (!DocumentMode.isCursorInRMode(editor_))
        return;
    // We check these first because we might lie within an
    // anonymous function scope, whereas what we first want
    // to check is for an enclosing `setGeneric` etc.
    TokenCursor cursor = getTokenCursor();
    if (cursor.moveToPosition(editor_.getCursorPosition(), true)) {
        String enclosingScope = findEnclosingScope(cursor);
        if (enclosingScope.equals("setClass"))
            insertRoxygenSkeletonS4Class(cursor);
        else if (enclosingScope.equals("setGeneric"))
            insertRoxygenSkeletonSetGeneric(cursor);
        else if (enclosingScope.equals("setMethod"))
            insertRoxygenSkeletonSetMethod(cursor);
        else if (enclosingScope.equals("setRefClass"))
            insertRoxygenSkeletonSetRefClass(cursor);
        if (enclosingScope != null)
            return;
    }
    // If the above checks failed, we'll want to insert a
    // roxygen skeleton for a 'regular' function call.
    Scope scope = editor_.getCurrentScope();
    if (scope != null && scope.isFunction()) {
        insertRoxygenSkeletonFunction(scope);
    } else {
        globalDisplay_.showErrorMessage("Insert Roxygen Skeleton", "Unable to insert skeleton (the cursor is not currently " + "inside an R function definition).");
    }
}
Also used : TokenCursor(org.rstudio.studio.client.workbench.views.source.editors.text.ace.TokenCursor) Scope(org.rstudio.studio.client.workbench.views.source.editors.text.Scope) JsArrayString(com.google.gwt.core.client.JsArrayString)

Example 9 with TokenCursor

use of org.rstudio.studio.client.workbench.views.source.editors.text.ace.TokenCursor in project rstudio by rstudio.

the class RCompletionManager method addAutocompletionContextForDollar.

private boolean addAutocompletionContextForDollar(AutocompletionContext context) {
    // Establish an evaluation context by looking backwards
    AceEditor editor = (AceEditor) docDisplay_;
    if (editor == null)
        return false;
    CodeModel codeModel = editor.getSession().getMode().getRCodeModel();
    codeModel.tokenizeUpToRow(input_.getCursorPosition().getRow());
    TokenCursor cursor = codeModel.getTokenCursor();
    if (!cursor.moveToPosition(input_.getCursorPosition()))
        return false;
    // Move back to the '$'
    while (cursor.currentValue() != "$" && cursor.currentValue() != "@") if (!cursor.moveToPreviousToken())
        return false;
    int type = cursor.currentValue() == "$" ? AutocompletionContext.TYPE_DOLLAR : AutocompletionContext.TYPE_AT;
    // Put a cursor here
    TokenCursor contextEndCursor = cursor.cloneCursor();
    // We allow for arbitrary elements previous, so we want to get e.g.
    //
    //     env::foo()$bar()[1]$baz
    // Get the string forming the context
    //
    //
    // If this fails, we still want to report an empty evaluation context
    // (the completion is still occurring in a '$' context, so we do want
    // to exclude completions from other scopes)
    String data = "";
    if (cursor.moveToPreviousToken() && cursor.findStartOfEvaluationContext()) {
        data = editor.getTextForRange(Range.fromPoints(cursor.currentPosition(), contextEndCursor.currentPosition()));
    }
    context.add(data, type);
    return true;
}
Also used : TokenCursor(org.rstudio.studio.client.workbench.views.source.editors.text.ace.TokenCursor) CodeModel(org.rstudio.studio.client.workbench.views.source.editors.text.ace.CodeModel) AceEditor(org.rstudio.studio.client.workbench.views.source.editors.text.AceEditor)

Example 10 with TokenCursor

use of org.rstudio.studio.client.workbench.views.source.editors.text.ace.TokenCursor in project rstudio by rstudio.

the class RCompletionManager method beginSuggest.

/**
    * If false, the suggest operation was aborted
    */
private boolean beginSuggest(boolean flushCache, boolean implicit, boolean canAutoInsert) {
    suggestTimer_.cancel();
    if (!input_.isSelectionCollapsed())
        return false;
    invalidatePendingRequests(flushCache, false);
    InputEditorSelection selection = input_.getSelection();
    if (selection == null)
        return false;
    int cursorCol = selection.getStart().getPosition();
    String firstLine = input_.getText().substring(0, cursorCol);
    // of roxygen comments (e.g. at "#' |")
    if (isLineInComment(firstLine) && !isLineInRoxygenComment(firstLine))
        return false;
    // if the insertion character was a tab (unless the user has opted in)
    if (!uiPrefs_.allowTabMultilineCompletion().getValue()) {
        if (nativeEvent_ != null && nativeEvent_.getKeyCode() == KeyCodes.KEY_TAB)
            if (firstLine.matches("^\\s*$"))
                return false;
    }
    AutocompletionContext context = getAutocompletionContext();
    // but is effectively a bandaid until the autocompletion revamp.
    if (context.getToken().startsWith("-"))
        context.setToken(context.getToken().substring(1));
    // the comment marker
    if (context.getToken().equals("'@"))
        context.setToken(context.getToken().substring(1));
    context_ = new CompletionRequestContext(invalidation_.getInvalidationToken(), selection, canAutoInsert);
    RInfixData infixData = RInfixData.create();
    AceEditor editor = (AceEditor) docDisplay_;
    if (editor != null) {
        CodeModel codeModel = editor.getSession().getMode().getRCodeModel();
        TokenCursor cursor = codeModel.getTokenCursor();
        if (cursor.moveToPosition(input_.getCursorPosition())) {
            String token = "";
            if (cursor.hasType("identifier"))
                token = cursor.currentValue();
            String cursorPos = "left";
            if (cursor.currentValue() == "=")
                cursorPos = "right";
            TokenCursor clone = cursor.cloneCursor();
            if (clone.moveToPreviousToken())
                if (clone.currentValue() == "=")
                    cursorPos = "right";
            // Try to get a dplyr join completion
            DplyrJoinContext joinContext = codeModel.getDplyrJoinContextFromInfixChain(cursor);
            // If that failed, try a non-infix lookup
            if (joinContext == null) {
                String joinString = getDplyrJoinString(editor, cursor);
                if (!StringUtil.isNullOrEmpty(joinString)) {
                    requester_.getDplyrJoinCompletionsString(token, joinString, cursorPos, implicit, context_);
                    return true;
                }
            } else {
                requester_.getDplyrJoinCompletions(joinContext, implicit, context_);
                return true;
            }
            // completions
            if (cursor.moveToPosition(input_.getCursorPosition()))
                infixData = codeModel.getDataFromInfixChain(cursor);
        }
    }
    String filePath = getSourceDocumentPath();
    String docId = getSourceDocumentId();
    requester_.getCompletions(context.getToken(), context.getAssocData(), context.getDataType(), context.getNumCommas(), context.getFunctionCallString(), infixData.getDataName(), infixData.getAdditionalArgs(), infixData.getExcludeArgs(), infixData.getExcludeArgsFromObject(), filePath, docId, implicit, context_);
    return true;
}
Also used : InputEditorSelection(org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorSelection) DplyrJoinContext(org.rstudio.studio.client.workbench.views.source.editors.text.ace.DplyrJoinContext) TokenCursor(org.rstudio.studio.client.workbench.views.source.editors.text.ace.TokenCursor) RInfixData(org.rstudio.studio.client.workbench.views.source.editors.text.ace.RInfixData) CodeModel(org.rstudio.studio.client.workbench.views.source.editors.text.ace.CodeModel) AceEditor(org.rstudio.studio.client.workbench.views.source.editors.text.AceEditor)

Aggregations

TokenCursor (org.rstudio.studio.client.workbench.views.source.editors.text.ace.TokenCursor)12 Position (org.rstudio.studio.client.workbench.views.source.editors.text.ace.Position)7 AceEditor (org.rstudio.studio.client.workbench.views.source.editors.text.AceEditor)6 JsArrayString (com.google.gwt.core.client.JsArrayString)5 CodeModel (org.rstudio.studio.client.workbench.views.source.editors.text.ace.CodeModel)4 ServerError (org.rstudio.studio.client.server.ServerError)2 InputEditorLineWithCursorPosition (org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorLineWithCursorPosition)2 ScopeFunction (org.rstudio.studio.client.workbench.views.source.editors.text.ScopeFunction)2 Token (org.rstudio.studio.client.workbench.views.source.editors.text.ace.Token)2 SourcePosition (org.rstudio.studio.client.workbench.views.source.model.SourcePosition)2 Element (com.google.gwt.dom.client.Element)1 Stack (java.util.Stack)1 FileSystemItem (org.rstudio.core.client.files.FileSystemItem)1 GlobalProgressDelayer (org.rstudio.studio.client.common.GlobalProgressDelayer)1 FileFunctionDefinition (org.rstudio.studio.client.workbench.codesearch.model.FileFunctionDefinition)1 ObjectDefinition (org.rstudio.studio.client.workbench.codesearch.model.ObjectDefinition)1 SearchPathFunctionDefinition (org.rstudio.studio.client.workbench.codesearch.model.SearchPathFunctionDefinition)1 SendToConsoleEvent (org.rstudio.studio.client.workbench.views.console.events.SendToConsoleEvent)1 InputEditorPosition (org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorPosition)1 InputEditorSelection (org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorSelection)1