private static bool GetFunction(AstRoot astRoot, ref int position, out FunctionCall functionCall, out Variable functionVariable) { functionVariable = null; functionCall = astRoot.GetNodeOfTypeFromPosition<FunctionCall>(position); if (functionCall == null && position > 0) { // Retry in case caret is at the very end of function signature // that does not have final close brace yet. functionCall = astRoot.GetNodeOfTypeFromPosition<FunctionCall>(position - 1, includeEnd: true); if(functionCall != null) { // But if signature does have closing brace and caret // is beyond it, we are really otuside of the signature. if(functionCall.CloseBrace != null && position >= functionCall.CloseBrace.End) { return false; } if (position > functionCall.SignatureEnd) { position = functionCall.SignatureEnd; } } } if (functionCall != null && functionCall.Children.Count > 0) { functionVariable = functionCall.Children[0] as Variable; return functionVariable != null; } return false; }
public ParameterInfo(string functionName, FunctionCall functionCall, int parameterIndex, string parameterName, bool namedParameter) { if (functionName == null) throw new ArgumentNullException("functionName"); if (functionCall == null) throw new ArgumentNullException("functionCall"); FunctionName = functionName; FunctionCall = functionCall; ParameterIndex = parameterIndex; ParameterName = parameterName; NamedParameter = namedParameter; }
private static bool ShouldProvideCompletions(RCompletionContext context, out FunctionCall funcCall) { // Safety checks funcCall = context.AstRoot.GetNodeOfTypeFromPosition<FunctionCall>(context.Position); if (funcCall == null || funcCall.OpenBrace == null || funcCall.Arguments == null) { return false; } if (context.Position < funcCall.OpenBrace.End || context.Position >= funcCall.SignatureEnd) { return false; } return true; }
private OperationType HandleOpenBrace(ParseContext context, out ParseErrorType errorType) { TokenStream<RToken> tokens = context.Tokens; errorType = ParseErrorType.None; // Separate expression from function call. In case of // function call previous token is either closing indexer // brace or closing function brace. Identifier with brace // is handled up above. // Indentifier followed by a brace needs to be analyzed // so we can tell between previous expression that ended // with identifier and identifier that is a function name: // // a <- 2*b // (expression) // // in this case b is not a function name. Similarly, // // a <- 2*b[1] // (expression) // // is not a function call operator over b[1]. if (_operators.Count > 1 || _operands.Count > 0) { // We are not in the beginning of the expression if (tokens.PreviousToken.TokenType == RTokenType.CloseBrace || tokens.PreviousToken.TokenType == RTokenType.CloseSquareBracket || tokens.PreviousToken.TokenType == RTokenType.CloseDoubleSquareBracket || tokens.PreviousToken.IsVariableKind()) { FunctionCall functionCall = new FunctionCall(); functionCall.Parse(context, null); errorType = HandleFunctionOrIndexer(functionCall); return OperationType.Function; } } Group group = new Group(); group.Parse(context, null); _operands.Push(group); return OperationType.Operand; }
private static ISignatureInfo ParseSignature(string functionName, ParseContext context, IReadOnlyDictionary<string, string> argumentsDescriptions = null) { SignatureInfo info = new SignatureInfo(functionName); List<IArgumentInfo> signatureArguments = new List<IArgumentInfo>(); // RD data may contain function name(s) without braces if (context.Tokens.CurrentToken.TokenType == RTokenType.OpenBrace) { FunctionCall functionCall = new FunctionCall(); functionCall.Parse(context, context.AstRoot); for (int i = 0; i < functionCall.Arguments.Count; i++) { IAstNode arg = functionCall.Arguments[i]; string argName = null; string argDefaultValue = null; bool isEllipsis = false; bool isOptional = false; ExpressionArgument expArg = arg as ExpressionArgument; if (expArg != null) { argName = context.TextProvider.GetText(expArg.ArgumentValue); } else { NamedArgument nameArg = arg as NamedArgument; if (nameArg != null) { argName = context.TextProvider.GetText(nameArg.NameRange); argDefaultValue = RdText.CleanRawRdText(context.TextProvider.GetText(nameArg.DefaultValue)); } else { MissingArgument missingArg = arg as MissingArgument; if (missingArg != null) { argName = string.Empty; } else { EllipsisArgument ellipsisArg = arg as EllipsisArgument; if (ellipsisArg != null) { argName = "..."; isEllipsis = true; } } } } ArgumentInfo argInfo = new ArgumentInfo(argName); argInfo.DefaultValue = argDefaultValue; argInfo.IsEllipsis = isEllipsis; argInfo.IsOptional = isOptional; // TODO: actually parse if (argumentsDescriptions != null) { string description; if (argumentsDescriptions.TryGetValue(argName, out description)) { argInfo.Description = description; } } signatureArguments.Add(argInfo); } } info.Arguments = signatureArguments; return info; }