Example #1
0
        /// <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);
        }
Example #2
0
        private void AnalyzeVariableStatement(INode node, DiagnosticContext context)
        {
            var variableStatement = node.Cast <IVariableStatement>();

            // Don't need to check whether a statement was declared at the namespace level,
            // because we'll skip non-exported variable declarations.
            // And export keyword is applicable only for top level variables!

            // We only care about exported statements
            if ((variableStatement.Flags & NodeFlags.Export) == 0)
            {
                return;
            }

            var declarations = variableStatement.DeclarationList.Declarations;

            foreach (var declaration in declarations)
            {
                // 'any' is not allowed for top level variables
                if (declaration.Type?.Kind == TypeScript.Net.Types.SyntaxKind.AnyKeyword ||
                    NodeWalker.ForEachChildRecursively <Bool>(declaration.Type, n => n?.Kind == TypeScript.Net.Types.SyntaxKind.AnyKeyword))
                {
                    context.Logger.ReportNotAllowedTypeAnyOnTopLevelDeclaration(
                        context.LoggingContext,
                        declaration.LocationForLogging(context.SourceFile),
                        declaration.Name.GetFormattedText(),
                        Name);
                }

                // If the variable has an initializer (there is another lint rule that enforces variable initialization,
                // but that can't be assumed here) that is an object literal, then there should be a non-any type annotation
                if (declaration.Initializer?.Kind == TypeScript.Net.Types.SyntaxKind.ObjectLiteralExpression)
                {
                    if (declaration.Type == null)
                    {
                        context.Logger.ReportMissingTypeAnnotationOnTopLevelDeclaration(
                            context.LoggingContext,
                            declaration.LocationForLogging(context.SourceFile),
                            declaration.Name.GetFormattedText(),
                            Name);
                    }
                    else if (declaration.Type.Kind == TypeScript.Net.Types.SyntaxKind.AnyKeyword)
                    {
                        context.Logger.ReportNotAllowedTypeAnyOnTopLevelDeclaration(
                            context.LoggingContext,
                            declaration.LocationForLogging(context.SourceFile),
                            declaration.Name.GetFormattedText(),
                            Name);
                    }
                }
            }
        }
Example #3
0
        private static INode GetReference(ISourceFile spec, string identifierName)
        {
            var firstIdentifier = NodeWalker.ForEachChildRecursively(
                spec,
                node =>
            {
                var identifier = node.As <IIdentifier>();
                if (identifier?.Text == identifierName)
                {
                    return(identifier);
                }
                return(null);
            });

            return(firstIdentifier);
        }
Example #4
0
        /// <summary>
        /// Assumes declaration names are unique (full names are not used)
        /// </summary>
        private static Dictionary <string, int> CollectAllDeclarationsWithPositions(ISourceFile sourceFile)
        {
            var identifersToPositions = new Dictionary <string, int>();

            NodeWalker.ForEachChildRecursively <INode>(sourceFile,
                                                       node =>
            {
                var declarationStatement = node.As <IDeclarationStatement>();
                if (declarationStatement?.Name != null)
                {
                    identifersToPositions.Add(declarationStatement.Name.Text + declarationStatement.Kind, declarationStatement.Pos);
                }

                var variableStatement = node.As <IVariableStatement>();
                if (variableStatement != null)
                {
                    foreach (var declaration in variableStatement.DeclarationList.Declarations)
                    {
                        identifersToPositions.Add(declaration.Name.Cast <IIdentifier>().Text + declaration.Kind, declaration.Pos);
                    }
                }

                var enumMember = node.As <IEnumMember>();
                if (enumMember != null)
                {
                    identifersToPositions.Add(enumMember.Name.Text + enumMember.Kind, enumMember.Pos);
                }

                var exportSpecifier = node.As <IExportSpecifier>();
                if (exportSpecifier != null)
                {
                    identifersToPositions.Add(exportSpecifier.Name.Text + exportSpecifier.Kind, exportSpecifier.Pos);
                }

                return(null);
            });

            return(identifersToPositions);
        }
Example #5
0
        /// <summary>
        /// Create a list of Code Lens annotations a source file to represent the current qualifier
        /// </summary>
        private IEnumerable <CodeLens> GetQualifierTypeForModulesAndTopLevelDeclarations(ISourceFile file)
        {
            // We want to display CodeLens for at the top of the file, and for namespaces at any depth of the source file
            // Also, note that namespaces can be on the same line (e.g. namespace Microsoft.Sdk {...} is actually namespace Sdk inside of namespace Microsoft)
            // In this case we want to display the qualifier for namespace Sdk, since that's what the user cares about
            // So we will use a line-number key'ed dictionary to make sure that for any line in the file, we only add a single qualifier
            var result            = new List <CodeLens>();
            var perLineCodeLenses = new Dictionary <int, CodeLens>();

            if (file.Statements.Count > 0)
            {
                var firstNode = file.Statements[0];
                var firstLine = firstNode.GetStartPosition().ToLineAndColumn().Line;

                if (GetQualifierAsCodeLens(firstNode, out var codeLens))
                {
                    perLineCodeLenses[firstLine] = codeLens;
                }
            }

            NodeWalker.ForEachChildRecursively(file, (node) =>
            {
                if (node.Kind == SyntaxKind.ModuleDeclaration)
                {
                    var lineAndColumn = node.GetStartPosition().ToLineAndColumn();
                    if (GetQualifierAsCodeLens(node, out var codeLens))
                    {
                        perLineCodeLenses[lineAndColumn.Line] = codeLens;
                    }
                }

                return((object)null);
            });

            result.AddRange(perLineCodeLenses.Values.Where(v => v != null));

            return(result);
        }
Example #6
0
 /// <summary>
 /// Invokes <paramref name="func"/>  callback for each recursive child of the given node.
 /// Travesal stops when <paramref name="func"/>  returns a 'truthy' value which is then returned from the function.
 /// </summary>
 public static T ForEachChildRecursively <T>(this INode node, Func <INode, T> func, bool recurseThroughIdentifiers = false)
     where T : class
 {
     return(NodeWalker.ForEachChildRecursively(node, func, recurseThroughIdentifiers));
 }