private static int CompareCallExpression(ICallExpression left, ICallExpression right) { // Standard left,right and null checks if (left == null && right == null) { return(0); } if (left == null) { return(1); } if (right == null) { return(-1); } var result = CompareExpression(left.Expression, right.Expression); if (result != 0) { return(result); } result = CompareNodeArrays(left.TypeArguments, right.TypeArguments, (l, r) => CompareNodeAsText(l, r)); if (result != 0) { return(result); } return(CompareNodeArrays(left.Arguments, right.Arguments, (l, r) => CompareExpression(l, r))); }
/// <summary> /// Whether the <paramref name="node"/> is an <code>importFrom(...)</code> or <code>importFile(...)</code> with the required number of arguments (i.e. with 1 argument). /// </summary> public static bool IsImportCall( [NotNull] this INode node, out ICallExpression callExpression, out DScriptImportFunctionKind importKind, out IExpression argumentAsExpression, out ILiteralExpression argumentAsLiteral) { Contract.Requires(node != null); const int parameterCount = 1; callExpression = node.As <ICallExpression>(); var expressionIdentifier = callExpression?.Expression.As <IIdentifier>(); if ( (expressionIdentifier?.Text == Names.InlineImportFunction || expressionIdentifier?.Text == Names.InlineImportFileFunction) && (callExpression.TypeArguments == null || callExpression.TypeArguments.Count == 0) && callExpression.Arguments.Length >= parameterCount) { importKind = expressionIdentifier.Text == Names.InlineImportFunction ? DScriptImportFunctionKind.ImportFrom : DScriptImportFunctionKind.ImportFile; argumentAsExpression = callExpression.Arguments[0]; argumentAsLiteral = argumentAsExpression.As <ILiteralExpression>(); return(true); } importKind = DScriptImportFunctionKind.None; argumentAsExpression = null; argumentAsLiteral = null; return(false); }
/// <summary> /// Finds the parameter that either contains this node or _is_ this node. /// </summary> /// <param name="callExpression">The containing call expression for this node</param> /// <param name="nodeAtPosition">The current node in the editor</param> /// <returns>The index of the argument (or 0 if this didn't correspond to any argument)</returns> public static int GetActiveParameterIndex(ICallExpression callExpression, INode nodeAtPosition) { var arguments = callExpression?.Arguments?.Elements.ToArray(); if (arguments == null) { return(DefaultArgIndex); } // first check the top level arguments (much cheaper and also very likely) for (int i = 0; i < arguments.Length; ++i) { if (ReferenceEquals(arguments[i], nodeAtPosition)) { return(i); } } // let's try the slightly more expensive check within subfields for (int i = 0; i < arguments.Length; ++i) { var result = NodeWalker.ForEachChildRecursively(arguments[i], node => ReferenceEquals(node, nodeAtPosition) ? node : null); if (result != null) { return(i); } } return(DefaultArgIndex); }
internal static bool IsInlineImport(this ICallExpression callExpression) { Contract.Requires(callExpression != null); var identifier = callExpression.Expression.As <IIdentifier>(); var functionName = identifier?.Text; // Currently, BuildXL script support two types of inline require. One of them would be obsoleted! return(functionName == Names.InlineImportFunction || functionName == Names.InlineImportFileFunction); }
private static bool TryCheckIsUnitTestDecorator(Logger logger, ISourceFile sourceFile, IDecorator decorator, out bool isUnitTestDecorator) { isUnitTestDecorator = false; var expression = decorator.Expression; ICallExpression callExpression = null; if (expression.Kind == SyntaxKind.CallExpression) { callExpression = (ICallExpression)expression; expression = callExpression.Expression; } if (expression.Kind == SyntaxKind.PropertyAccessExpression) { var propertyAccess = (IPropertyAccessExpression)expression; expression = propertyAccess.Name; } if (expression.Kind == SyntaxKind.Identifier) { var identifier = (IIdentifier)expression; if (string.Equals(UnitTestName, identifier.Text, StringComparison.Ordinal)) { isUnitTestDecorator = true; } else if (string.Equals(UnitTestName, identifier.Text, StringComparison.OrdinalIgnoreCase)) { logger.LogError(sourceFile, decorator, C($"Decorator '{identifier.Text}' is using the wrong casing. Please use '{UnitTestName}'")); return(false); } } // If this is a unit test and it came from a function call, perform some extra checks if (isUnitTestDecorator && callExpression != null) { if (callExpression.Arguments.Count > 0) { logger.LogError(sourceFile, decorator, "UnitTest decorators are not allowed to have arguments"); return(false); } if (callExpression.TypeArguments != null && callExpression.TypeArguments.Count > 0) { logger.LogError(sourceFile, decorator, "UnitTest decorators are not allowed to be generic"); return(false); } } return(true); }
public Expression ConvertExpression(ICallExpression node, FunctionScope localScope, bool useSemanticNameResolution) { try { return(m_decoratee.ConvertExpression(node, localScope, useSemanticNameResolution)); } catch (Exception e) { string sourceFragment = node.GetText().SubstringMax(0, MaxSourceLength); string message = "Failed to convert expression.\r\n" + sourceFragment; throw new ConversionException(message, e); } }
private void AnalyzeModuleFromImportFrom(ICallExpression node, bool saveIdentifierOnStack = false) { var moduleName = GetModuleNameFromImportFrom(node); if (!string.IsNullOrEmpty(moduleName)) { string fullNameString = string.Concat(Names.InlineImportFunction, ".", moduleName); if (saveIdentifierOnStack) { m_currentLocationStack.Push(fullNameString); } else { AddOrCreateInteractionSymbol(SymbolKind.ImportedModule, fullNameString); } } }
/// <summary> /// Return true iff callExpression is a call to 'config' ('configure' as well for compat reasons), 'package' or 'qualifierSpace' the only allowed top-level function calls. /// </summary> private static bool IsAllowedTopLevelFunctionCall(ICallExpression callExpression) { // Call expression should be at the top level to be considered valid. // Namespace level calls to predefine functions are invalid. // Need to check parent's parent, because for ICallExpression Parent is ExpressionStaement but not a SourceFile directly. if (callExpression.Parent.IsTopLevelDeclaration()) { var expressionName = callExpression.Expression.As <IIdentifier>(); if (expressionName != null) { return(expressionName.Text == Names.ConfigurationFunctionCall || expressionName.Text == Names.LegacyModuleConfigurationFunctionCall || expressionName.Text == Names.ModuleConfigurationFunctionCall); } } return(false); }
public static IExpression TypeOf(ICallExpression call) { if (call.Method.Method.IsGetTypeFromHandle()) { if (call.Arguments.Count != 1) { throw new InvalidOperationException(); } var typeRef = call.Arguments[0] as ITypeReferenceExpression; if (typeRef == null) { throw new InvalidOperationException(); } return(new TypeOfExpression(typeRef.Type)); } return(null); }
private static int FitsOnOneLine(ICallExpression expression, int remainingSpace) { var space = remainingSpace; space = FitsOnOneLine(expression.Expression, space); if (space > 0 && expression.TypeArguments != null) { space -= 2; // The pointy brackets. space = FitsOnOneLine(expression.TypeArguments, 2, space); } if (space > 0 && expression.Arguments != null) { space -= 2; // Parenthesis; space = FitsOnOneLine(expression.Arguments, 2, space); } return(space); }
/// <summary> /// Tries to parse the input call expression <param name="callExpression"/> into a GlobDescriptor object. /// </summary> /// <remarks> /// The <param name="basePath"/> and <param name="pathTable"/> must be provided to compute the absolute path of the /// 'root' parameter in the call expression. /// </remarks> public static Possible <GlobDescriptor> TryCreateGlobDescriptorFromCallExpression( ICallExpression callExpression, AbsolutePath basePath, PathTable pathTable) { var functionName = callExpression.Expression.Cast <IIdentifier>(); if (!functionName.IsGlob()) { return(new MalformedGlobExpressionFailure(I($"Expecting glob/globR function but got '{functionName.GetText()}'."))); } if ((callExpression.Arguments?.Count ?? 0) == 0) { return(new MalformedGlobExpressionFailure("Glob function should take at least one argument but got 0.")); } // Parse the 'root' param var root = AbsolutePath.Invalid; var pathExpressionString = callExpression.Arguments[0].GetText(); if (!TryCreateAbsolutePath( pathTable, basePath, pathExpressionString, out root)) { return(new MalformedGlobExpressionFailure(I($"Malformed path expression '{pathExpressionString}'."))); } // Parse the 'pattern' param. If none is provided, it is defaulted to "*" var pattern = callExpression.Arguments.Count > 1 ? callExpression.Arguments[1].Cast <IStringLiteral>().Text : "*"; // Determine if glob is recursive var recursive = functionName.IsGlobRecursive(); return(new GlobDescriptor(root, pattern, recursive)); }
private bool FixCreateFunction(ICallExpression call, ISymbol symbol, DiagnosticsContext context, string formatFunction, string interfaceName) { if (Matches(context, symbol, "Sdk.Prelude", interfaceName + ".create")) { var arg = call.Arguments.FirstOrDefault(); var fix = ComputeFix(formatFunction, arg); if (Fix) { call.Replace(fix); } else { var existingExpression = call.ToDisplayString(); var fixExpression = fix.ToDisplayString(); Logger.LegacyLiteralFix(LoggingContext, call.LocationForLogging(context.SourceFile), fixExpression, existingExpression); return(false); } } return(true); }
public virtual void VisitCallExpression(ICallExpression e) { }
private static string GetModuleNameFromImportFrom(ICallExpression node) { return(node.Arguments.First().TryCast <ILiteralExpression>()?.Text); }
/// <nodoc/> public Result <SignatureHelp, ResponseError> SignatureHelp(TextDocumentPositionParams positionParams, CancellationToken token) { // TODO: support cancellation if (!TryFindNode(positionParams, out var nodeAtPosition)) { return(Result <SignatureHelp, ResponseError> .Success(new SignatureHelp())); } ICallExpression callExpression = GetContainingCallExpression(nodeAtPosition); if (callExpression == null) { Logger.LanguageServerNonCriticalInternalIssue(LoggingContext, FormattableStringEx.I($"Couldn't find call expression containing {nodeAtPosition.GetFormattedText()}")); return(Result <SignatureHelp, ResponseError> .Success(new SignatureHelp())); } var callSymbol = TypeChecker.GetSymbolAtLocation(callExpression.Expression); // If the user has typed a call expresion to a symbol (function) that doesn't exist (i.e. "foo.bar()") // Then just issue a debug writeline and a success instead of crashing. // There is going to be a red-line squiggle under it anyway. if (callSymbol == null) { Logger.LanguageServerNonCriticalInternalIssue(LoggingContext, FormattableStringEx.I($"Couldn't find symbol for call expression containing {nodeAtPosition.GetFormattedText()}")); return(Result <SignatureHelp, ResponseError> .Success(new SignatureHelp())); } var signature = TypeChecker.GetSignaturesOfType(TypeChecker.GetTypeAtLocation(callExpression.Expression), SignatureKind.Call).FirstOrDefault(); if (signature == null) { Logger.LanguageServerNonCriticalInternalIssue(LoggingContext, FormattableStringEx.I($"Couldn't find call signature for call expression containing {nodeAtPosition.GetFormattedText()}")); return(Result <SignatureHelp, ResponseError> .Success(new SignatureHelp())); } var functionDeclaration = DScriptFunctionSignature.FromSignature(callSymbol.Name, signature); var parameterInformations = functionDeclaration.FormattedParameterNames.Select(formattedParameterName => new ParameterInformation() { Label = formattedParameterName, }); int activeParameterIndex = DScriptFunctionSignature.GetActiveParameterIndex(callExpression, nodeAtPosition); var signatureHelp = new SignatureHelp() { Signatures = new SignatureInformation[] { new SignatureInformation() { Label = functionDeclaration.FormattedFullFunctionSignature, Parameters = parameterInformations.ToArray(), Documentation = DocumentationUtilities.GetDocumentationForSymbolAsString(callSymbol), }, }, ActiveParameter = activeParameterIndex, ActiveSignature = 0, }; return(Result <SignatureHelp, ResponseError> .Success(signatureHelp)); }