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);
}
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);
}
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).");
}
}
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;
}
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;
}
Aggregations