Search in sources :

Example 36 with Position

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

the class CompletionRequester method addScopedCompletions.

private void addScopedCompletions(String token, ArrayList<QualifiedName> completions, String type) {
    AceEditor editor = (AceEditor) docDisplay_;
    // NOTE: this will be null in the console, so protect against that
    if (editor != null) {
        Position cursorPosition = editor.getSession().getSelection().getCursor();
        CodeModel codeModel = editor.getSession().getMode().getRCodeModel();
        JsArray<RScopeObject> scopeVariables = codeModel.getVariablesInScope(cursorPosition);
        String tokenLower = token.toLowerCase();
        for (int i = 0; i < scopeVariables.length(); i++) {
            RScopeObject variable = scopeVariables.get(i);
            if (variable.getType() == type && variable.getToken().toLowerCase().startsWith(tokenLower))
                completions.add(new QualifiedName(variable.getToken(), variable.getType(), false, RCompletionType.CONTEXT));
        }
    }
}
Also used : Position(org.rstudio.studio.client.workbench.views.source.editors.text.ace.Position) CodeModel(org.rstudio.studio.client.workbench.views.source.editors.text.ace.CodeModel) AceEditor(org.rstudio.studio.client.workbench.views.source.editors.text.AceEditor) JsArrayString(com.google.gwt.core.client.JsArrayString) RScopeObject(org.rstudio.studio.client.workbench.views.source.editors.text.ace.RScopeObject)

Example 37 with Position

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

the class CompletionRequester method addScopedArgumentCompletions.

private void addScopedArgumentCompletions(String token, ArrayList<QualifiedName> completions) {
    AceEditor editor = (AceEditor) docDisplay_;
    // NOTE: this will be null in the console, so protect against that
    if (editor != null) {
        Position cursorPosition = editor.getSession().getSelection().getCursor();
        CodeModel codeModel = editor.getSession().getMode().getRCodeModel();
        JsArray<RFunction> scopedFunctions = codeModel.getFunctionsInScope(cursorPosition);
        if (scopedFunctions.length() == 0)
            return;
        String tokenLower = token.toLowerCase();
        for (int i = 0; i < scopedFunctions.length(); i++) {
            RFunction scopedFunction = scopedFunctions.get(i);
            String functionName = scopedFunction.getFunctionName();
            JsArrayString argNames = scopedFunction.getFunctionArgs();
            for (int j = 0; j < argNames.length(); j++) {
                String argName = argNames.get(j);
                if (argName.toLowerCase().startsWith(tokenLower)) {
                    if (functionName == null || functionName == "") {
                        completions.add(new QualifiedName(argName, "<anonymous function>", false, RCompletionType.CONTEXT));
                    } else {
                        completions.add(new QualifiedName(argName, functionName, false, RCompletionType.CONTEXT));
                    }
                }
            }
        }
    }
}
Also used : Position(org.rstudio.studio.client.workbench.views.source.editors.text.ace.Position) CodeModel(org.rstudio.studio.client.workbench.views.source.editors.text.ace.CodeModel) AceEditor(org.rstudio.studio.client.workbench.views.source.editors.text.AceEditor) JsArrayString(com.google.gwt.core.client.JsArrayString) JsArrayString(com.google.gwt.core.client.JsArrayString) RFunction(org.rstudio.studio.client.workbench.views.source.editors.text.RFunction)

Example 38 with Position

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

the class RCompletionManager method getAutocompletionContext.

private AutocompletionContext getAutocompletionContext() {
    AutocompletionContext context = new AutocompletionContext();
    String firstLine = input_.getText();
    int row = input_.getCursorPosition().getRow();
    // trim to cursor position
    firstLine = firstLine.substring(0, input_.getCursorPosition().getColumn());
    // file completions
    if (DocumentMode.isCursorInMarkdownMode(docDisplay_) && firstLine.matches(".*\\[.*\\]\\(.*"))
        return getAutocompletionContextForFileMarkdownLink(firstLine);
    // Get the token at the cursor position.
    String tokenRegex = ".*[^" + RegexUtil.wordCharacter() + "._:$@'\"`-]";
    String token = firstLine.replaceAll(tokenRegex, "");
    // If we're completing an object within a string, assume it's a
    // file-system completion. Note that we may need other contextual information
    // to decide if e.g. we only want directories.
    String firstLineStripped = StringUtil.stripBalancedQuotes(StringUtil.stripRComment(firstLine));
    boolean isFileCompletion = false;
    if (firstLineStripped.indexOf('\'') != -1 || firstLineStripped.indexOf('"') != -1) {
        isFileCompletion = true;
        addAutocompletionContextForFile(context, firstLine);
    }
    // pass the whole line as a token
    if (firstLine.startsWith("```{") || firstLine.startsWith("<<"))
        return new AutocompletionContext(firstLine, AutocompletionContext.TYPE_CHUNK);
    // If this line starts with a '?', assume it's a help query
    if (firstLine.matches("^\\s*[?].*"))
        return new AutocompletionContext(token, AutocompletionContext.TYPE_HELP);
    // escape early for roxygen
    if (firstLine.matches("\\s*#+'.*"))
        return new AutocompletionContext(token, AutocompletionContext.TYPE_ROXYGEN);
    // about the appropriate completion
    if (token.contains("$") || token.contains("@"))
        addAutocompletionContextForDollar(context);
    // 'debug(stats::rnorm)' we know not to auto-insert parens)
    if (token.contains("::"))
        addAutocompletionContextForNamespace(token, context);
    // If this is not a file completion, we need to further strip and
    // then set the token. Note that the token will have already been
    // set if this is a file completion.
    token = token.replaceAll(".*[$@:]", "");
    if (!isFileCompletion)
        context.setToken(token);
    // access to the R Code model
    AceEditor editor = (AceEditor) docDisplay_;
    if (editor == null)
        return context;
    CodeModel codeModel = editor.getSession().getMode().getRCodeModel();
    // We might need to grab content from further up in the document than
    // the current cursor position -- so tokenize ahead.
    codeModel.tokenizeUpToRow(row + 100);
    // Make a token cursor and place it at the first token previous
    // to the cursor.
    TokenCursor tokenCursor = codeModel.getTokenCursor();
    if (!tokenCursor.moveToPosition(input_.getCursorPosition()))
        return context;
    // names.
    if (tokenCursor.moveToNextToken()) {
        if (tokenCursor.currentValue() == ":" || tokenCursor.currentValue() == "::" || tokenCursor.currentValue() == ":::") {
            return new AutocompletionContext(token, AutocompletionContext.TYPE_PACKAGE);
        }
        tokenCursor.moveToPreviousToken();
    }
    TokenCursor startCursor = tokenCursor.cloneCursor();
    // Find an opening '(' or '[' -- this provides the function or object
    // for completion.
    int initialNumCommas = 0;
    if (tokenCursor.currentValue() != "(" && tokenCursor.currentValue() != "[") {
        int commaCount = tokenCursor.findOpeningBracketCountCommas(new String[] { "[", "(" }, true);
        // commaCount == -1 implies we failed to find an opening bracket
        if (commaCount == -1) {
            commaCount = tokenCursor.findOpeningBracketCountCommas("[", false);
            if (commaCount == -1)
                return context;
            else
                initialNumCommas = commaCount;
        } else {
            initialNumCommas = commaCount;
        }
    }
    // Figure out whether we're looking at '(', '[', or '[[',
    // and place the token cursor on the first token preceding.
    TokenCursor endOfDecl = tokenCursor.cloneCursor();
    int initialDataType = AutocompletionContext.TYPE_UNKNOWN;
    if (tokenCursor.currentValue() == "(") {
        initialDataType = AutocompletionContext.TYPE_FUNCTION;
        if (!tokenCursor.moveToPreviousToken())
            return context;
    } else if (tokenCursor.currentValue() == "[") {
        if (!tokenCursor.moveToPreviousToken())
            return context;
        if (tokenCursor.currentValue() == "[") {
            if (!endOfDecl.moveToPreviousToken())
                return context;
            initialDataType = AutocompletionContext.TYPE_DOUBLE_BRACKET;
            if (!tokenCursor.moveToPreviousToken())
                return context;
        } else {
            initialDataType = AutocompletionContext.TYPE_SINGLE_BRACKET;
        }
    }
    // Get the string marking the function or data
    if (!tokenCursor.findStartOfEvaluationContext())
        return context;
    // Try to get the function call string -- either there's
    // an associated closing paren we can use, or we should just go up
    // to the current cursor position.
    // First, attempt to determine where the closing paren is located. If
    // this fails, we'll just use the start cursor's position (and later
    // attempt to finish the expression to make it parsable)
    Position endPos = startCursor.currentPosition();
    endPos.setColumn(endPos.getColumn() + startCursor.currentValue().length());
    // try to look forward for closing paren
    if (endOfDecl.currentValue() == "(") {
        TokenCursor closingParenCursor = endOfDecl.cloneCursor();
        if (closingParenCursor.fwdToMatchingToken()) {
            endPos = closingParenCursor.currentPosition();
            endPos.setColumn(endPos.getColumn() + 1);
        }
    }
    // We can now set the function call string.
    //
    // We strip out the current statement under the cursor, so that
    // match.call() can later properly resolve the current argument.
    //
    // Attempt to find the start of the current statement.
    TokenCursor clone = startCursor.cloneCursor();
    do {
        String value = clone.currentValue();
        if (value.indexOf(",") != -1 || value.equals("("))
            break;
        if (clone.bwdToMatchingToken())
            continue;
    } while (clone.moveToPreviousToken());
    Position startPosition = clone.currentPosition();
    // Include the opening paren if that's what we found
    if (clone.currentValue().equals("("))
        startPosition.setColumn(startPosition.getColumn() + 1);
    String beforeText = editor.getTextForRange(Range.fromPoints(tokenCursor.currentPosition(), startPosition));
    // Now, attempt to find the end of the current statement.
    // Look for the ',' or ')' that ends the statement for the 
    // currently active argument.
    boolean lookupSucceeded = false;
    while (clone.moveToNextToken()) {
        String value = clone.currentValue();
        if (value.indexOf(",") != -1 || value.equals(")")) {
            lookupSucceeded = true;
            break;
        }
        // pairs properly, so finding one implies that we have a parse error).
        if (value.equals("]") || value.equals("}"))
            break;
        if (clone.fwdToMatchingToken())
            continue;
    }
    String afterText = "";
    if (lookupSucceeded) {
        afterText = editor.getTextForRange(Range.fromPoints(clone.currentPosition(), endPos));
    }
    context.setFunctionCallString((beforeText + afterText).trim());
    // Try to identify whether we're producing autocompletions for
    // a _named_ function argument; if so, produce completions tuned to
    // that argument.
    TokenCursor argsCursor = startCursor.cloneCursor();
    do {
        String argsValue = argsCursor.currentValue();
        // within a named argument, although this isn't perfect.
        if (argsValue.equals(",") || argsValue.equals("(") || argsValue.equals("$") || argsValue.equals("@") || argsValue.equals("::") || argsValue.equals(":::") || argsValue.equals("]") || argsValue.equals(")") || argsValue.equals("}")) {
            break;
        }
        // a function argument.
        if (argsValue.equals("=") && argsCursor.moveToPreviousToken()) {
            if (!isFileCompletion)
                context.setToken(token);
            context.add(argsCursor.currentValue(), AutocompletionContext.TYPE_ARGUMENT, 0);
            return context;
        }
    } while (argsCursor.moveToPreviousToken());
    String initialData = docDisplay_.getTextForRange(Range.fromPoints(tokenCursor.currentPosition(), endOfDecl.currentPosition())).trim();
    // And the first context
    context.add(initialData, initialDataType, initialNumCommas);
    // Get the rest of the single-bracket contexts for completions as well
    String assocData;
    int dataType;
    int numCommas;
    while (true) {
        int commaCount = tokenCursor.findOpeningBracketCountCommas("[", false);
        if (commaCount == -1)
            break;
        numCommas = commaCount;
        TokenCursor declEnd = tokenCursor.cloneCursor();
        if (!tokenCursor.moveToPreviousToken())
            return context;
        if (tokenCursor.currentValue() == "[") {
            if (!declEnd.moveToPreviousToken())
                return context;
            dataType = AutocompletionContext.TYPE_DOUBLE_BRACKET;
            if (!tokenCursor.moveToPreviousToken())
                return context;
        } else {
            dataType = AutocompletionContext.TYPE_SINGLE_BRACKET;
        }
        tokenCursor.findStartOfEvaluationContext();
        assocData = docDisplay_.getTextForRange(Range.fromPoints(tokenCursor.currentPosition(), declEnd.currentPosition())).trim();
        context.add(assocData, dataType, numCommas);
    }
    return context;
}
Also used : TokenCursor(org.rstudio.studio.client.workbench.views.source.editors.text.ace.TokenCursor) InputEditorPosition(org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorPosition) Position(org.rstudio.studio.client.workbench.views.source.editors.text.ace.Position) SourcePosition(org.rstudio.studio.client.workbench.views.source.model.SourcePosition) InputEditorLineWithCursorPosition(org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorLineWithCursorPosition) CodeModel(org.rstudio.studio.client.workbench.views.source.editors.text.ace.CodeModel) AceEditor(org.rstudio.studio.client.workbench.views.source.editors.text.AceEditor)

Example 39 with Position

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

the class RCompletionManager method getDplyrJoinString.

private String getDplyrJoinString(AceEditor editor, TokenCursor cursor) {
    while (true) {
        int commaCount = cursor.findOpeningBracketCountCommas("(", true);
        if (commaCount == -1)
            break;
        if (!cursor.moveToPreviousToken())
            return "";
        if (!cursor.currentValue().matches(".*join$"))
            continue;
        if (commaCount < 2)
            return "";
        Position start = cursor.currentPosition();
        if (!cursor.moveToNextToken())
            return "";
        if (!cursor.fwdToMatchingToken())
            return "";
        Position end = cursor.currentPosition();
        end.setColumn(end.getColumn() + 1);
        return editor.getTextForRange(Range.fromPoints(start, end));
    }
    return "";
}
Also used : InputEditorPosition(org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorPosition) Position(org.rstudio.studio.client.workbench.views.source.editors.text.ace.Position) SourcePosition(org.rstudio.studio.client.workbench.views.source.model.SourcePosition) InputEditorLineWithCursorPosition(org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorLineWithCursorPosition)

Example 40 with Position

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

the class RoxygenHelper method insertRoxygenSkeletonSetMethod.

private void insertRoxygenSkeletonSetMethod(TokenCursor cursor) {
    final Position startPos = cursor.currentPosition();
    String call = extractCall(cursor);
    if (call == null)
        return;
    server_.getSetMethodCall(call, new ServerRequestCallback<SetMethodCall>() {

        @Override
        public void onResponseReceived(SetMethodCall response) {
            if (hasRoxygenBlock(startPos)) {
                amendExistingRoxygenBlock(startPos.getRow() - 1, response.getGeneric(), response.getParameterNames(), response.getParameterTypes(), "param", RE_ROXYGEN_PARAM);
            } else {
                insertRoxygenTemplate(response.getGeneric(), response.getParameterNames(), response.getParameterTypes(), "param", "method", startPos);
            }
        }

        @Override
        public void onError(ServerError error) {
            Debug.logError(error);
        }
    });
}
Also used : Position(org.rstudio.studio.client.workbench.views.source.editors.text.ace.Position) ServerError(org.rstudio.studio.client.server.ServerError) JsArrayString(com.google.gwt.core.client.JsArrayString)

Aggregations

Position (org.rstudio.studio.client.workbench.views.source.editors.text.ace.Position)64 InputEditorPosition (org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorPosition)20 JsArrayString (com.google.gwt.core.client.JsArrayString)16 Breakpoint (org.rstudio.studio.client.common.debugging.model.Breakpoint)11 Range (org.rstudio.studio.client.workbench.views.source.editors.text.ace.Range)11 ScheduledCommand (com.google.gwt.core.client.Scheduler.ScheduledCommand)7 FileChangeHandler (org.rstudio.studio.client.workbench.views.files.events.FileChangeHandler)7 TokenCursor (org.rstudio.studio.client.workbench.views.source.editors.text.ace.TokenCursor)7 SourcePosition (org.rstudio.studio.client.workbench.views.source.model.SourcePosition)7 Handler (org.rstudio.core.client.command.Handler)6 EnsureHeightHandler (org.rstudio.core.client.events.EnsureHeightHandler)6 EnsureVisibleHandler (org.rstudio.core.client.events.EnsureVisibleHandler)6 ChangeFontSizeHandler (org.rstudio.studio.client.application.events.ChangeFontSizeHandler)6 ServerError (org.rstudio.studio.client.server.ServerError)6 AceEditor (org.rstudio.studio.client.workbench.views.source.editors.text.AceEditor)6 Token (org.rstudio.studio.client.workbench.views.source.editors.text.ace.Token)6 HideMessageHandler (org.rstudio.studio.client.workbench.views.source.editors.text.status.StatusBar.HideMessageHandler)6 RecordNavigationPositionHandler (org.rstudio.studio.client.workbench.views.source.events.RecordNavigationPositionHandler)6 InputEditorLineWithCursorPosition (org.rstudio.studio.client.workbench.views.console.shell.editor.InputEditorLineWithCursorPosition)4 CodeModel (org.rstudio.studio.client.workbench.views.source.editors.text.ace.CodeModel)4