Example #1
0
		DomRegion MakeBraceRegion(AstNode node)
		{
			if (node == null || node.IsNull)
				return DomRegion.Empty;
			else
				return MakeRegion(node.GetChildByRole(AstNode.Roles.LBrace).StartLocation,
				                  node.GetChildByRole(AstNode.Roles.RBrace).EndLocation);
		}
            private void AddIssue(AstNode node, IType baseType, int argumentCount = 0)
            {
                var identifier = node.GetChildByRole(Roles.Identifier);

                this.AddIssue(
                    identifier,
                    string.Format(ctx.TranslateString("CS1729: The type '{0}' does not contain a constructor that takes '{1}' arguments"), baseType.Name, argumentCount));
            }
Example #3
0
		public static ResolveResult Resolve(Lazy<ICompilation> compilation, CSharpUnresolvedFile unresolvedFile, SyntaxTree syntaxTree, TextLocation location, out AstNode node,
		                                    CancellationToken cancellationToken = default(CancellationToken))
		{
			node = syntaxTree.GetNodeAt(location);
			if (node == null || node is ArrayInitializerExpression)
				return null;
			if (CSharpAstResolver.IsUnresolvableNode(node)) {
				if (node is Identifier) {
					node = node.Parent;
				} else if (node.NodeType == NodeType.Token) {
					if (node.Parent is IndexerExpression || node.Parent is ConstructorInitializer) {
						Console.WriteLine (2);
						// There's no other place where one could hover to see the indexer's tooltip,
						// so we need to resolve it when hovering over the '[' or ']'.
						// For constructor initializer, the same applies to the 'base'/'this' token.
						node = node.Parent;
					} else {
						return null;
					}
				} else {
					// don't resolve arbitrary nodes - we don't want to show tooltips for everything
					return null;
				}
			} else {
				// It's a resolvable node.
				// However, we usually don't want to show the tooltip everywhere
				// For example, hovering with the mouse over an empty line between two methods causes
				// node==TypeDeclaration, but we don't want to show any tooltip.
				
				if (!node.GetChildByRole(Roles.Identifier).IsNull) {
					// We'll suppress the tooltip for resolvable nodes if there is an identifier that
					// could be hovered over instead:
					return null;
				}
			}
			if (node == null)
				return null;
			
			if (node.Parent is ObjectCreateExpression && node.Role == Roles.Type) {
				node = node.Parent;
			}
			
			InvocationExpression parentInvocation = null;
			if ((node is IdentifierExpression || node is MemberReferenceExpression || node is PointerReferenceExpression) && node.Role != Roles.Argument) {
				// we also need to resolve the invocation
				parentInvocation = node.Parent as InvocationExpression;
			}
			
			// TODO: I think we should provide an overload so that an existing CSharpAstResolver can be reused
			CSharpAstResolver resolver = new CSharpAstResolver(compilation.Value, syntaxTree, unresolvedFile);
			ResolveResult rr = resolver.Resolve(node, cancellationToken);
			if (rr is MethodGroupResolveResult && parentInvocation != null)
				return resolver.Resolve(parentInvocation);
			else
				return rr;
		}
Example #4
0
        static bool IsAsync(AstNode currentFunction)
        {
            var method = currentFunction as MethodDeclaration;

            if (method != null)
            {
                return(method.HasModifier(Modifiers.Async));
            }
            return(!currentFunction.GetChildByRole(LambdaExpression.AsyncModifierRole).IsNull);
        }
Example #5
0
 static bool HasNoIdentifier(AstNode node)
 {
     return
         (node.GetChildByRole(Roles.Identifier) == Roles.Identifier.NullObject &&
          node.GetChildByRole(Roles.Parameter) == Roles.Parameter.NullObject &&
          node.GetChildByRole(Roles.Argument) == Roles.Argument.NullObject &&
          node.GetChildByRole(Roles.Type) == Roles.Type.NullObject &&
          node.GetChildByRole(Roles.TargetExpression) == Roles.TargetExpression.NullObject &&
          node.GetChildByRole(Roles.TypeParameter) == Roles.TypeParameter.NullObject &&
          node.GetChildByRole(Roles.TypeArgument) == Roles.TypeArgument.NullObject &&
          node.GetChildByRole(Roles.Constraint) == Roles.Constraint.NullObject);
 }
Example #6
0
		public static ResolveResult Resolve(Func<ICompilation> compilation, CSharpParsedFile parsedFile, CompilationUnit cu, TextLocation location, out AstNode node,
		                                    CancellationToken cancellationToken = default(CancellationToken))
		{
			node = cu.GetNodeAt(location);
			if (node == null)
				return null;
			if (CSharpAstResolver.IsUnresolvableNode(node)) {
				if (node is Identifier) {
					node = node.Parent;
				} else if (node.NodeType == NodeType.Token) {
					if (node.Parent is IndexerExpression || node.Parent is ConstructorInitializer) {
						// There's no other place where one could hover to see the indexer's tooltip,
						// so we need to resolve it when hovering over the '[' or ']'.
						// For constructor initializer, the same applies to the 'base'/'this' token.
						node = node.Parent;
					} else {
						return null;
					}
				} else {
					// don't resolve arbitrary nodes - we don't want to show tooltips for everything
					return null;
				}
			} else {
				// It's a resolvable node.
				// However, we usually don't want to show the tooltip everywhere
				// For example, hovering with the mouse over an empty line between two methods causes
				// node==TypeDeclaration, but we don't want to show any tooltip.
				
				if (!node.GetChildByRole(Roles.Identifier).IsNull) {
					// We'll suppress the tooltip for resolvable nodes if there is an identifier that
					// could be hovered over instead:
					return null;
				}
			}
			if (node == null)
				return null;
			
			if (node.Parent is ObjectCreateExpression && node.Role == Roles.Type) {
				node = node.Parent;
			}
			
			InvocationExpression parentInvocation = null;
			if (node is IdentifierExpression || node is MemberReferenceExpression || node is PointerReferenceExpression) {
				// we also need to resolve the invocation
				parentInvocation = node.Parent as InvocationExpression;
			}
			
			CSharpAstResolver resolver = new CSharpAstResolver(compilation(), cu, parsedFile);
			resolver.ApplyNavigator(new NodeListResolveVisitorNavigator(node), cancellationToken);
			ResolveResult rr = resolver.Resolve(node, cancellationToken);
			if (rr is MethodGroupResolveResult && parentInvocation != null)
				return resolver.Resolve(parentInvocation);
			else
				return rr;
		}
Example #7
0
        protected internal override bool DoMatch(AstNode other, Match match)
        {
            IdentifierExpression ident = other as IdentifierExpression;

            if (ident == null || ident.TypeArguments.Any())
            {
                return(false);
            }
            AstNode referenced = match.Get(referencedGroupName).Last();

            return(ident.Identifier == referenced.GetChildByRole(AstNode.Roles.Identifier).Name);
        }
            NullValueAnalysis GetAnalysis(AstNode parentFunction)
            {
                NullValueAnalysis analysis;

                if (cachedNullAnalysis.TryGetValue(parentFunction, out analysis))
                {
                    return(analysis);
                }

                analysis = new NullValueAnalysis(ctx, parentFunction.GetChildByRole(Roles.Body), parentFunction.GetChildrenByRole(Roles.Parameter), ctx.CancellationToken);
                cachedNullAnalysis [parentFunction] = analysis;
                return(analysis);
            }
        void HandleConstructorOrDestructor(AstNode constructorDeclaration)
        {
            Identifier nameToken = constructorDeclaration.GetChildByRole(Roles.Identifier);

            VisitChildrenUntil(constructorDeclaration, nameToken);
            var currentTypeDef = resolver.GetResolverStateBefore(constructorDeclaration).CurrentTypeDefinition;

            if (currentTypeDef != null && nameToken.Name == currentTypeDef.Name)
            {
                TColor color;
                if (TryGetTypeHighlighting(currentTypeDef.Kind, out color))
                {
                    Colorize(nameToken, color);
                }
            }
            VisitChildrenAfter(constructorDeclaration, nameToken);
        }
Example #10
0
        public string ConvertSymbol(ISymbol symbol)
        {
            var stringWriter = new StringWriter();
            var astBuilder   = new TypeSystemAstBuilder();

            astBuilder.AlwaysUseShortTypeNames = true;
            AstNode node   = astBuilder.ConvertSymbol(symbol);
            var     writer = new TextWriterTokenWriter(stringWriter);
            var     rt     = node.GetChildByRole(Roles.Type);

            if (!rt.IsNull)
            {
                rt.AcceptVisitor(new CSharpOutputVisitor(stringWriter, FormattingOptionsFactory.CreateMono()));
            }

            IProperty property = symbol as IProperty;

            if (property != null)
            {
                writer.Space();
                writer.WriteToken(Roles.LBrace, "{");
                writer.Space();
                if (property.CanGet)
                {
                    writer.WriteKeyword(PropertyDeclaration.GetKeywordRole, "get");
                    writer.WriteToken(Roles.Semicolon, ";");
                    writer.Space();
                }
                if (property.CanSet)
                {
                    writer.WriteKeyword(PropertyDeclaration.SetKeywordRole, "set");
                    writer.WriteToken(Roles.Semicolon, ";");
                    writer.Space();
                }
                writer.WriteToken(Roles.RBrace, "}");
            }
            return(stringWriter.ToString());
        }
Example #11
0
        public override void StartNode(AstNode node)
        {
            if (nodeStack.Count == 0)
            {
                if (IsUsingDeclaration(node))
                {
                    firstUsingDeclaration = !IsUsingDeclaration(node.PrevSibling);
                    lastUsingDeclaration  = !IsUsingDeclaration(node.NextSibling);
                }
                else
                {
                    firstUsingDeclaration = false;
                    lastUsingDeclaration  = false;
                }
            }
            nodeStack.Push(node);
            startLocations.Push(output.Location);

            if (node is EntityDeclaration && node.Annotation <MemberReference>() != null && node.GetChildByRole(Roles.Identifier).IsNull)
            {
                output.WriteDefinition("", node.Annotation <MemberReference>(), false);
            }

            if (node.Annotation <MethodDebugSymbols>() != null)
            {
                symbolsStack.Push(node.Annotation <MethodDebugSymbols>());
                symbolsStack.Peek().StartLocation = startLocations.Peek();
            }
        }
Example #12
0
        public void StartNode(AstNode node)
        {
            if (nodeStack.Count == 0)
            {
                if (IsUsingDeclaration(node))
                {
                    firstUsingDeclaration = !IsUsingDeclaration(node.PrevSibling);
                    lastUsingDeclaration  = !IsUsingDeclaration(node.NextSibling);
                }
                else
                {
                    firstUsingDeclaration = false;
                    lastUsingDeclaration  = false;
                }
            }
            nodeStack.Push(node);
            startLocations.Push(output.Location);

            if (node is AttributedNode && node.Annotation <MemberReference>() != null && node.GetChildByRole(AstNode.Roles.Identifier).IsNull)
            {
                output.WriteDefinition("", node.Annotation <MemberReference>(), false);
            }

            MemberMapping mapping = node.Annotation <MemberMapping>();

            if (mapping != null)
            {
                parentMemberMappings.Push(currentMemberMapping);
                currentMemberMapping = mapping;
            }
        }
Example #13
0
		public override void StartNode(AstNode node)
		{
			if (nodeStack.Count == 0) {
				if (IsUsingDeclaration(node)) {
					firstUsingDeclaration = !IsUsingDeclaration(node.PrevSibling);
					lastUsingDeclaration = !IsUsingDeclaration(node.NextSibling);
				} else {
					firstUsingDeclaration = false;
					lastUsingDeclaration = false;
				}
			}
			nodeStack.Push(node);
			startLocations.Push(output.Location);
			
			if (node is EntityDeclaration && node.Annotation<MemberReference>() != null && node.GetChildByRole(Roles.Identifier).IsNull)
				output.WriteDefinition("", node.Annotation<MemberReference>(), false);

			if (node.Annotation<MethodDebugSymbols>() != null) {
				symbolsStack.Push(node.Annotation<MethodDebugSymbols>());
				symbolsStack.Peek().StartLocation = startLocations.Peek();
			}
		}
Example #14
0
        public void ConvertSymbol(ISymbol symbol, TokenWriter writer, CSharpFormattingOptions formattingPolicy)
        {
            if (symbol == null)
            {
                throw new ArgumentNullException(nameof(symbol));
            }
            if (writer == null)
            {
                throw new ArgumentNullException(nameof(writer));
            }
            if (formattingPolicy == null)
            {
                throw new ArgumentNullException(nameof(formattingPolicy));
            }

            TypeSystemAstBuilder astBuilder = CreateAstBuilder();
            AstNode node = astBuilder.ConvertSymbol(symbol);

            writer.StartNode(node);
            EntityDeclaration entityDecl = node as EntityDeclaration;

            if (entityDecl != null)
            {
                PrintModifiers(entityDecl.Modifiers, writer);
            }

            if ((ConversionFlags & ConversionFlags.ShowDefinitionKeyword) == ConversionFlags.ShowDefinitionKeyword)
            {
                if (node is TypeDeclaration)
                {
                    switch (((TypeDeclaration)node).ClassType)
                    {
                    case ClassType.Class:
                        writer.WriteKeyword(Roles.ClassKeyword, "class");
                        break;

                    case ClassType.Struct:
                        writer.WriteKeyword(Roles.StructKeyword, "struct");
                        break;

                    case ClassType.Interface:
                        writer.WriteKeyword(Roles.InterfaceKeyword, "interface");
                        break;

                    case ClassType.Enum:
                        writer.WriteKeyword(Roles.EnumKeyword, "enum");
                        break;

                    case ClassType.RecordClass:
                        writer.WriteKeyword(Roles.RecordKeyword, "record");
                        break;

                    default:
                        throw new Exception("Invalid value for ClassType");
                    }
                    writer.Space();
                }
                else if (node is DelegateDeclaration)
                {
                    writer.WriteKeyword(Roles.DelegateKeyword, "delegate");
                    writer.Space();
                }
                else if (node is EventDeclaration)
                {
                    writer.WriteKeyword(EventDeclaration.EventKeywordRole, "event");
                    writer.Space();
                }
                else if (node is NamespaceDeclaration)
                {
                    writer.WriteKeyword(Roles.NamespaceKeyword, "namespace");
                    writer.Space();
                }
            }

            if ((ConversionFlags & ConversionFlags.PlaceReturnTypeAfterParameterList) != ConversionFlags.PlaceReturnTypeAfterParameterList &&
                (ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType)
            {
                var rt = node.GetChildByRole(Roles.Type);
                if (!rt.IsNull)
                {
                    rt.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy));
                    writer.Space();
                }
            }

            if (symbol is ITypeDefinition)
            {
                WriteTypeDeclarationName((ITypeDefinition)symbol, writer, formattingPolicy);
            }
            else if (symbol is IMember)
            {
                WriteMemberDeclarationName((IMember)symbol, writer, formattingPolicy);
            }
            else
            {
                writer.WriteIdentifier(Identifier.Create(symbol.Name));
            }

            if ((ConversionFlags & ConversionFlags.ShowParameterList) == ConversionFlags.ShowParameterList && HasParameters(symbol))
            {
                writer.WriteToken(symbol.SymbolKind == SymbolKind.Indexer ? Roles.LBracket : Roles.LPar, symbol.SymbolKind == SymbolKind.Indexer ? "[" : "(");
                bool first = true;
                foreach (var param in node.GetChildrenByRole(Roles.Parameter))
                {
                    if ((ConversionFlags & ConversionFlags.ShowParameterModifiers) == 0)
                    {
                        param.ParameterModifier = ParameterModifier.None;
                    }
                    if ((ConversionFlags & ConversionFlags.ShowParameterDefaultValues) == 0)
                    {
                        param.DefaultExpression.Detach();
                    }
                    if (first)
                    {
                        first = false;
                    }
                    else
                    {
                        writer.WriteToken(Roles.Comma, ",");
                        writer.Space();
                    }
                    param.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy));
                }
                writer.WriteToken(symbol.SymbolKind == SymbolKind.Indexer ? Roles.RBracket : Roles.RPar, symbol.SymbolKind == SymbolKind.Indexer ? "]" : ")");
            }

            if ((ConversionFlags & ConversionFlags.PlaceReturnTypeAfterParameterList) == ConversionFlags.PlaceReturnTypeAfterParameterList &&
                (ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType)
            {
                var rt = node.GetChildByRole(Roles.Type);
                if (!rt.IsNull)
                {
                    writer.Space();
                    writer.WriteToken(Roles.Colon, ":");
                    writer.Space();
                    if (symbol is IField f && CSharpDecompiler.IsFixedField(f, out var type, out int elementCount))
                    {
                        rt = astBuilder.ConvertType(type);
                        new IndexerExpression(new TypeReferenceExpression(rt), astBuilder.ConvertConstantValue(f.Compilation.FindType(KnownTypeCode.Int32), elementCount))
                        .AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy));
                    }
                    else
                    {
                        rt.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy));
                    }
                }
            }
		public void StartNode(AstNode node)
		{
			if (nodeStack.Count == 0) {
				if (IsUsingDeclaration(node)) {
					firstUsingDeclaration = !IsUsingDeclaration(node.PrevSibling);
					lastUsingDeclaration = !IsUsingDeclaration(node.NextSibling);
				} else {
					firstUsingDeclaration = false;
					lastUsingDeclaration = false;
				}
			}
			nodeStack.Push(node);
			startLocations.Push(output.Location);
			
			if (node is EntityDeclaration && node.Annotation<MemberReference>() != null && node.GetChildByRole(Roles.Identifier).IsNull)
				output.WriteDefinition("", node.Annotation<MemberReference>(), false);
			
			MemberMapping mapping = node.Annotation<MemberMapping>();
			if (mapping != null) {
				parentMemberMappings.Push(currentMemberMapping);
				currentMemberMapping = mapping;
			}
		}
Example #16
0
        public void ConvertSymbol(ISymbol symbol, TokenWriter writer, CSharpFormattingOptions formattingPolicy)
        {
            if (symbol == null)
            {
                throw new ArgumentNullException("symbol");
            }
            if (writer == null)
            {
                throw new ArgumentNullException("writer");
            }
            if (formattingPolicy == null)
            {
                throw new ArgumentNullException("formattingPolicy");
            }

            TypeSystemAstBuilder astBuilder = CreateAstBuilder();
            AstNode           node          = astBuilder.ConvertSymbol(symbol);
            EntityDeclaration entityDecl    = node as EntityDeclaration;

            if (entityDecl != null)
            {
                PrintModifiers(entityDecl.Modifiers, writer);
            }

            if ((ConversionFlags & ConversionFlags.ShowDefinitionKeyword) == ConversionFlags.ShowDefinitionKeyword)
            {
                if (node is TypeDeclaration)
                {
                    switch (((TypeDeclaration)node).ClassType)
                    {
                    case ClassType.Class:
                        writer.WriteKeyword(Roles.ClassKeyword, "class");
                        break;

                    case ClassType.Struct:
                        writer.WriteKeyword(Roles.StructKeyword, "struct");
                        break;

                    case ClassType.Interface:
                        writer.WriteKeyword(Roles.InterfaceKeyword, "interface");
                        break;

                    case ClassType.Enum:
                        writer.WriteKeyword(Roles.EnumKeyword, "enum");
                        break;

                    default:
                        throw new Exception("Invalid value for ClassType");
                    }
                    writer.Space();
                }
                else if (node is DelegateDeclaration)
                {
                    writer.WriteKeyword(Roles.DelegateKeyword, "delegate");
                    writer.Space();
                }
                else if (node is EventDeclaration)
                {
                    writer.WriteKeyword(EventDeclaration.EventKeywordRole, "event");
                    writer.Space();
                }
                else if (node is NamespaceDeclaration)
                {
                    writer.WriteKeyword(Roles.NamespaceKeyword, "namespace");
                    writer.Space();
                }
            }

            if ((ConversionFlags & ConversionFlags.PlaceReturnTypeAfterParameterList) != ConversionFlags.PlaceReturnTypeAfterParameterList &&
                (ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType)
            {
                var rt = node.GetChildByRole(Roles.Type);
                if (!rt.IsNull)
                {
                    rt.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy));
                    writer.Space();
                }
            }

            if (symbol is ITypeDefinition)
            {
                WriteTypeDeclarationName((ITypeDefinition)symbol, writer, formattingPolicy);
            }
            else if (symbol is IMember)
            {
                WriteMemberDeclarationName((IMember)symbol, writer, formattingPolicy);
            }
            else
            {
                writer.WriteIdentifier(Identifier.Create(symbol.Name));
            }

            if ((ConversionFlags & ConversionFlags.ShowParameterList) == ConversionFlags.ShowParameterList && HasParameters(symbol))
            {
                writer.WriteToken(symbol.SymbolKind == SymbolKind.Indexer ? Roles.LBracket : Roles.LPar, symbol.SymbolKind == SymbolKind.Indexer ? "[" : "(");
                bool first = true;
                foreach (var param in node.GetChildrenByRole(Roles.Parameter))
                {
                    if (first)
                    {
                        first = false;
                    }
                    else
                    {
                        writer.WriteToken(Roles.Comma, ",");
                        writer.Space();
                    }
                    param.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy));
                }
                writer.WriteToken(symbol.SymbolKind == SymbolKind.Indexer ? Roles.RBracket : Roles.RPar, symbol.SymbolKind == SymbolKind.Indexer ? "]" : ")");
            }

            if ((ConversionFlags & ConversionFlags.PlaceReturnTypeAfterParameterList) == ConversionFlags.PlaceReturnTypeAfterParameterList &&
                (ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType)
            {
                var rt = node.GetChildByRole(Roles.Type);
                if (!rt.IsNull)
                {
                    writer.Space();
                    writer.WriteToken(Roles.Colon, ":");
                    writer.Space();
                    rt.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy));
                }
            }

            if ((ConversionFlags & ConversionFlags.ShowBody) == ConversionFlags.ShowBody && !(node is TypeDeclaration))
            {
                IProperty property = symbol as IProperty;
                if (property != null)
                {
                    writer.Space();
                    writer.WriteToken(Roles.LBrace, "{");
                    writer.Space();
                    if (property.CanGet)
                    {
                        writer.WriteKeyword(PropertyDeclaration.GetKeywordRole, "get");
                        writer.WriteToken(Roles.Semicolon, ";");
                        writer.Space();
                    }
                    if (property.CanSet)
                    {
                        writer.WriteKeyword(PropertyDeclaration.SetKeywordRole, "set");
                        writer.WriteToken(Roles.Semicolon, ";");
                        writer.Space();
                    }
                    writer.WriteToken(Roles.RBrace, "}");
                }
                else
                {
                    writer.WriteToken(Roles.Semicolon, ";");
                }
            }
        }
		static bool HasNoIdentifier(AstNode node)
		{
			return 
				node.GetChildByRole(Roles.Identifier) == Roles.Identifier.NullObject &&
				node.GetChildByRole(Roles.Parameter) == Roles.Parameter.NullObject &&
				node.GetChildByRole(Roles.Argument) == Roles.Argument.NullObject &&
				node.GetChildByRole(Roles.Type) == Roles.Type.NullObject &&
				node.GetChildByRole(Roles.TargetExpression) == Roles.TargetExpression.NullObject &&
				node.GetChildByRole(Roles.TypeParameter) == Roles.TypeParameter.NullObject &&
				node.GetChildByRole(Roles.TypeArgument) == Roles.TypeArgument.NullObject &&
				node.GetChildByRole(Roles.Constraint) == Roles.Constraint.NullObject;
		}
Example #18
0
 static AstNode GetFunctionToken(AstNode currentFunction)
 {
     return((AstNode)currentFunction.GetChildByRole(Roles.Identifier) ??
            currentFunction.GetChildByRole(LambdaExpression.ArrowRole) ??
            currentFunction.GetChildByRole(AnonymousMethodExpression.DelegateKeywordRole));
 }
        public static ResolveResult Resolve(ICompilation compilation, CppParsedFile parsedFile, CompilationUnit cu, TextLocation location, out AstNode node,
                                            CancellationToken cancellationToken = default(CancellationToken))
        {
            node = cu.GetNodeAt(location);
            if (node == null)
            {
                return(null);
            }
            if (CppAstResolver.IsUnresolvableNode(node))
            {
                if (node is Identifier)
                {
                    node = node.Parent;
                }
                else if (node.NodeType == NodeType.Token)
                {
                    if (node.Parent is IndexerExpression || node.Parent is ConstructorInitializer)
                    {
                        // There's no other place where one could hover to see the indexer's tooltip,
                        // so we need to resolve it when hovering over the '[' or ']'.
                        // For constructor initializer, the same applies to the 'base'/'this' token.
                        node = node.Parent;
                    }
                    else
                    {
                        return(null);
                    }
                }
                else
                {
                    // don't resolve arbitrary nodes - we don't want to show tooltips for everything
                    return(null);
                }
            }
            else
            {
                // It's a resolvable node.
                // However, we usually don't want to show the tooltip everywhere
                // For example, hovering with the mouse over an empty line between two methods causes
                // node==TypeDeclaration, but we don't want to show any tooltip.

                if (!node.GetChildByRole(AstNode.Roles.Identifier).IsNull)
                {
                    // We'll suppress the tooltip for resolvable nodes if there is an identifier that
                    // could be hovered over instead:
                    return(null);
                }
            }
            if (node == null)
            {
                return(null);
            }

            if (node.Parent is ObjectCreateExpression && node.Role == ObjectCreateExpression.Roles.Type)
            {
                node = node.Parent;
            }

            InvocationExpression parentInvocation = null;

            if (node is IdentifierExpression || node is MemberReferenceExpression || node is PointerReferenceExpression)
            {
                // we also need to resolve the invocation
                parentInvocation = node.Parent as InvocationExpression;
            }

            CppAstResolver resolver = new CppAstResolver(compilation, cu, parsedFile);
            ResolveResult  rr       = resolver.Resolve(node, cancellationToken);

            if (rr is MethodGroupResolveResult && parentInvocation != null)
            {
                return(resolver.Resolve(parentInvocation));
            }
            else
            {
                return(rr);
            }
        }
Example #20
0
		public static ResolveResult Resolve(Lazy<ICompilation> compilation, CSharpUnresolvedFile unresolvedFile, SyntaxTree syntaxTree, TextLocation location, out AstNode node,
		                                    CancellationToken cancellationToken = default(CancellationToken))
		{
			node = syntaxTree.GetNodeAt(location);
			if (node == null || node is ArrayInitializerExpression)
				return null;
			if (node.Parent is UsingAliasDeclaration && node.Role == UsingAliasDeclaration.AliasRole) {
				var r = new CSharpAstResolver(compilation.Value, syntaxTree, unresolvedFile);
				return r.Resolve(((UsingAliasDeclaration)node.Parent).Import, cancellationToken);
			}
			if (CSharpAstResolver.IsUnresolvableNode(node)) {
				if (node is Identifier) {
					node = node.Parent;
				} else if (node.NodeType == NodeType.Token) {
					if (node.Parent is IndexerExpression || node.Parent is ConstructorInitializer || node.Role == IndexerDeclaration.ThisKeywordRole) {
						// There's no other place where one could hover to see the indexer's tooltip,
						// so we need to resolve it when hovering over the '[' or ']'.
						// For constructor initializer, the same applies to the 'base'/'this' token.
						node = node.Parent;
					} else if (node.Parent is BinaryOperatorExpression || node.Parent is UnaryOperatorExpression) {
						// Resolve user-defined operator
						node = node.Parent;
					} else {
						return null;
					}
				} else {
					// don't resolve arbitrary nodes - we don't want to show tooltips for everything
					return null;
				}
			} else {
				// It's a resolvable node.
				// However, we usually don't want to show the tooltip everywhere
				// For example, hovering with the mouse over an empty line between two methods causes
				// node==TypeDeclaration, but we don't want to show any tooltip.
				
				if (!node.GetChildByRole(Roles.Identifier).IsNull) {
					// We'll suppress the tooltip for resolvable nodes if there is an identifier that
					// could be hovered over instead:
					return null;
				}
			}

			if (node == null)
				return null;
			if (node.Parent is ObjectCreateExpression && node.Role == Roles.Type) {
				node = node.Parent;
			} else if (node is ThisReferenceExpression && node.Parent is IndexerExpression) {
				node = node.Parent;
			}

			InvocationExpression parentInvocation = null;
			if ((node is IdentifierExpression || node is MemberReferenceExpression || node is PointerReferenceExpression) && node.Role != Roles.Argument) {
				// we also need to resolve the invocation
				parentInvocation = node.Parent as InvocationExpression;
			}
			
			// TODO: I think we should provide an overload so that an existing CSharpAstResolver can be reused
			CSharpAstResolver resolver = new CSharpAstResolver(compilation.Value, syntaxTree, unresolvedFile);
			ResolveResult rr = resolver.Resolve(node, cancellationToken);
			MethodGroupResolveResult mgrr = rr as MethodGroupResolveResult;
			if (mgrr != null) {
				// For method groups, resolve the parent invocation instead.
				if (parentInvocation != null)
					return resolver.Resolve(parentInvocation);
				if (node is Expression) {
					// If it's not an invocation, try if it's a conversion to a delegate type:
					Conversion c = resolver.GetConversion((Expression)node, cancellationToken);
					if (c.IsMethodGroupConversion)
						return new MemberResolveResult(mgrr.TargetResult, c.Method);
				}
			}
			return rr;
		}
Example #21
0
        public static ResolveResult Resolve(Lazy <ICompilation> compilation, CSharpUnresolvedFile unresolvedFile, SyntaxTree syntaxTree, TextLocation location, out AstNode node,
                                            CancellationToken cancellationToken = default(CancellationToken))
        {
            node = syntaxTree.GetNodeAt(location);
            if (node == null || node is ArrayInitializerExpression)
            {
                return(null);
            }
            if (node.Parent is UsingAliasDeclaration && node.Role == UsingAliasDeclaration.AliasRole)
            {
                var r = new CSharpAstResolver(compilation.Value, syntaxTree, unresolvedFile);
                return(r.Resolve(((UsingAliasDeclaration)node.Parent).Import, cancellationToken));
            }
            if (CSharpAstResolver.IsUnresolvableNode(node))
            {
                if (node is Identifier)
                {
                    node = node.Parent;
                }
                else if (node.NodeType == NodeType.Token)
                {
                    if (node.Parent is IndexerExpression || node.Parent is ConstructorInitializer || node.Role == IndexerDeclaration.ThisKeywordRole)
                    {
                        // There's no other place where one could hover to see the indexer's tooltip,
                        // so we need to resolve it when hovering over the '[' or ']'.
                        // For constructor initializer, the same applies to the 'base'/'this' token.
                        node = node.Parent;
                    }
                    else if (node.Parent is BinaryOperatorExpression || node.Parent is UnaryOperatorExpression)
                    {
                        // Resolve user-defined operator
                        node = node.Parent;
                    }
                    else
                    {
                        return(null);
                    }
                }
                else
                {
                    // don't resolve arbitrary nodes - we don't want to show tooltips for everything
                    return(null);
                }
            }
            else
            {
                // It's a resolvable node.
                // However, we usually don't want to show the tooltip everywhere
                // For example, hovering with the mouse over an empty line between two methods causes
                // node==TypeDeclaration, but we don't want to show any tooltip.

                if (!node.GetChildByRole(Roles.Identifier).IsNull)
                {
                    // We'll suppress the tooltip for resolvable nodes if there is an identifier that
                    // could be hovered over instead:
                    return(null);
                }
            }

            if (node == null)
            {
                return(null);
            }
            if (node.Parent is ObjectCreateExpression && node.Role == Roles.Type)
            {
                node = node.Parent;
            }

            InvocationExpression parentInvocation = null;

            if ((node is IdentifierExpression || node is MemberReferenceExpression || node is PointerReferenceExpression) && node.Role != Roles.Argument)
            {
                // we also need to resolve the invocation
                parentInvocation = node.Parent as InvocationExpression;
            }

            // TODO: I think we should provide an overload so that an existing CSharpAstResolver can be reused
            CSharpAstResolver        resolver = new CSharpAstResolver(compilation.Value, syntaxTree, unresolvedFile);
            ResolveResult            rr       = resolver.Resolve(node, cancellationToken);
            MethodGroupResolveResult mgrr     = rr as MethodGroupResolveResult;

            if (mgrr != null)
            {
                // For method groups, resolve the parent invocation instead.
                if (parentInvocation != null)
                {
                    return(resolver.Resolve(parentInvocation));
                }
                if (node is Expression)
                {
                    // If it's not an invocation, try if it's a conversion to a delegate type:
                    Conversion c = resolver.GetConversion((Expression)node, cancellationToken);
                    if (c.IsMethodGroupConversion)
                    {
                        return(new MemberResolveResult(mgrr.TargetResult, c.Method));
                    }
                }
            }
            return(rr);
        }
Example #22
0
            void AddIssueFor(AstNode currentFunction)
            {
                if (IsAsync(currentFunction))
                {
                    return;
                }

                //Only suggest modifying functions that return void, Task or Task<T>.
                IType returnType = GetReturnType(ctx, currentFunction);

                if (returnType == null)
                {
                    return;
                }

                bool  isVoid     = false;
                IType resultType = null;

                switch (returnType.FullName)
                {
                case "System.Void":
                    isVoid = true;
                    break;

                case "System.Threading.Tasks.Task":
                    resultType = returnType.IsParameterized ? returnType.TypeArguments.FirstOrDefault() : null;
                    break;

                default:
                    return;
                }

                var functionBody     = currentFunction.GetChildByRole(Roles.Body);
                var statements       = GetStatements(functionBody).ToList();
                var returnStatements = statements.OfType <ReturnStatement>().ToList();

                var invocations = new List <InvocationExpression>();
                var nextInChain = new Dictionary <InvocationExpression, InvocationExpression>();

                foreach (var invocation in currentFunction.Descendants.OfType <InvocationExpression>())
                {
                    if (invocation.Arguments.Count != 1)
                    {
                        continue;
                    }

                    var       lambdaOrDelegate = invocation.Arguments.Single();
                    Statement lambdaBody;
                    if (lambdaOrDelegate is LambdaExpression)
                    {
                        lambdaBody = lambdaOrDelegate.GetChildByRole(LambdaExpression.BodyRole) as BlockStatement;
                        if (lambdaBody == null)
                        {
                            continue;
                        }
                    }
                    else if (lambdaOrDelegate is AnonymousMethodExpression)
                    {
                        lambdaBody = lambdaOrDelegate.GetChildByRole(Roles.Body);
                    }
                    else
                    {
                        continue;
                    }

                    var resolveResult = ctx.Resolve(invocation) as MemberResolveResult;
                    if (resolveResult == null)
                    {
                        continue;
                    }
                    if (resolveResult.Member.FullName != "System.Threading.Tasks.Task.ContinueWith")
                    {
                        continue;
                    }

                    var parentExpression = invocation.Parent as Expression;
                    if (parentExpression != null)
                    {
                        var mreParent = parentExpression as MemberReferenceExpression;
                        if (mreParent == null || mreParent.MemberName != "ContinueWith")
                        {
                            continue;
                        }

                        var parentInvocation = mreParent.Parent as InvocationExpression;
                        if (parentInvocation == null || parentInvocation.Arguments.Count != 1)
                        {
                            continue;
                        }

                        nextInChain[invocation] = parentInvocation;
                    }

                    invocations.Add(invocation);
                }

                if (isVoid && invocations.Count == 0)
                {
                    //Prevent functions like void Foo() {} from being accepted
                    return;
                }

                string taskCompletionSourceIdentifier     = null;
                InvocationExpression returnedContinuation = null;

                if (isVoid)
                {
                    if (returnStatements.Any())
                    {
                        return;
                    }
                }
                else if (!isVoid)
                {
                    if (returnStatements.Count() != 1)
                    {
                        return;
                    }

                    var returnStatement = returnStatements.Single();
                    if (functionBody.Statements.Last() != returnStatement)
                    {
                        return;
                    }

                    var match = ReturnTaskCompletionSourcePattern.Match(returnStatement);
                    if (match.Success)
                    {
                        var taskCompletionSource = match.Get <IdentifierExpression>("target").Single();
                        var taskCompletionSourceResolveResult = ctx.Resolve(taskCompletionSource);

                        //Make sure the TaskCompletionSource is a local variable
                        if (!(taskCompletionSourceResolveResult is LocalResolveResult) ||
                            taskCompletionSourceResolveResult.Type.FullName != "System.Threading.Tasks.TaskCompletionSource")
                        {
                            return;
                        }
                        taskCompletionSourceIdentifier = taskCompletionSource.Identifier;

                        var cfgBuilder = new ControlFlowGraphBuilder();
                        var cachedControlFlowGraphs = new Dictionary <BlockStatement, IList <ControlFlowNode> >();

                        //Make sure there are no unsupported uses of the task completion source
                        foreach (var identifier in functionBody.Descendants.OfType <Identifier>())
                        {
                            if (identifier.Name != taskCompletionSourceIdentifier)
                            {
                                continue;
                            }

                            var statement         = identifier.GetParent <Statement>();
                            var variableStatement = statement as VariableDeclarationStatement;
                            if (variableStatement != null)
                            {
                                if (functionBody.Statements.First() != variableStatement || variableStatement.Variables.Count != 1)
                                {
                                    //This may actually be valid, but it would add even more complexity to this action
                                    return;
                                }
                                var initializer = variableStatement.Variables.First().Initializer as ObjectCreateExpression;
                                if (initializer == null || initializer.Arguments.Count != 0 || !initializer.Initializer.IsNull)
                                {
                                    return;
                                }

                                var constructedType = ctx.ResolveType(initializer.Type);
                                if (constructedType.FullName != "System.Threading.Tasks.TaskCompletionSource")
                                {
                                    return;
                                }

                                continue;
                            }

                            if (statement == returnStatement)
                            {
                                continue;
                            }

                            if (identifier.Parent is MemberReferenceExpression)
                            {
                                //Right side of the member.
                                //We don't care about this case since it's not a reference to the variable.
                                continue;
                            }

                            //The method's taskCompletionSource can only be used on the left side of a member
                            //reference expression (specifically tcs.SetResult).
                            var identifierExpressionParent = identifier.Parent as IdentifierExpression;
                            if (identifierExpressionParent == null)
                            {
                                return;
                            }
                            var memberReferenceExpression = identifierExpressionParent.Parent as MemberReferenceExpression;
                            if (memberReferenceExpression == null)
                            {
                                return;
                            }

                            if (memberReferenceExpression.MemberName != "SetResult")
                            {
                                //Aside from the final return statement, the only member of task completion source
                                //that can be used is SetResult.
                                //Perhaps future versions could also include SetException and SetCancelled.
                                return;
                            }

                            //We found a SetResult -- we will now find out if it is in a proper context
                            AstNode node = memberReferenceExpression;
                            for (;;)
                            {
                                node = node.Parent;

                                if (node == null)
                                {
                                    //Abort since this is unexpected (it should never happen)
                                    return;
                                }

                                if (node is MethodDeclaration)
                                {
                                    //Ok -- tcs.SetResult is in method declaration
                                    break;
                                }

                                if (node is LambdaExpression || node is AnonymousMethodExpression)
                                {
                                    //It's time to verify if the lambda is supported
                                    var lambdaParent = node.Parent as InvocationExpression;
                                    if (lambdaParent == null || !invocations.Contains(lambdaParent))
                                    {
                                        return;
                                    }
                                    break;
                                }
                            }

                            var containingContinueWith = node.Parent as InvocationExpression;
                            if (containingContinueWith != null)
                            {
                                if (nextInChain.ContainsKey(containingContinueWith))
                                {
                                    //Unsupported: ContinueWith has a SetResult
                                    //but it's not the last in the chain
                                    return;
                                }
                            }

                            var containingFunctionBlock = node is LambdaExpression ? (BlockStatement)node.GetChildByRole(LambdaExpression.BodyRole) : node.GetChildByRole(Roles.Body);

                            //Finally, tcs.SetResult must be at the end of its method
                            IList <ControlFlowNode> nodes;
                            if (!cachedControlFlowGraphs.TryGetValue(containingFunctionBlock, out nodes))
                            {
                                nodes = cfgBuilder.BuildControlFlowGraph(containingFunctionBlock, ctx.CancellationToken);
                                cachedControlFlowGraphs[containingFunctionBlock] = nodes;
                            }

                            var setResultNode = nodes.FirstOrDefault(candidateNode => candidateNode.PreviousStatement == statement);
                            if (setResultNode != null && HasReachableNonReturnNodes(setResultNode))
                            {
                                //The only allowed outgoing nodes are return statements
                                return;
                            }
                        }
                    }
                    else
                    {
                        //Not TaskCompletionSource-based
                        //Perhaps it is return Task.ContinueWith(foo);

                        if (!invocations.Any())
                        {
                            return;
                        }

                        var outerMostInvocations = new List <InvocationExpression>();
                        InvocationExpression currentInvocation = invocations.First();
                        do
                        {
                            outerMostInvocations.Add(currentInvocation);
                        } while (nextInChain.TryGetValue(currentInvocation, out currentInvocation));

                        var lastInvocation = outerMostInvocations.Last();
                        if (returnStatement.Expression != lastInvocation)
                        {
                            return;
                        }

                        //Found return <1>.ContinueWith(<2>);
                        returnedContinuation = lastInvocation;
                    }
                }

                //We do not support "return expr" in continuations
                //The only exception is when the outer method returns that continuation.
                invocations.RemoveAll(invocation => invocation != returnedContinuation &&
                                      invocation.Arguments.First().Children.OfType <Statement>().First().DescendantNodesAndSelf(node => node is Statement).OfType <ReturnStatement>().Any(returnStatement => !returnStatement.Expression.IsNull));

                AddIssue(new CodeIssue(GetFunctionToken(currentFunction),
                                       ctx.TranslateString("Function can be converted to C# 5-style async function"),
                                       ctx.TranslateString("Convert to C# 5-style async function"),
                                       script => {
                    AddOriginalNodeAnnotations(currentFunction);
                    var newFunction = currentFunction.Clone();
                    RemoveOriginalNodeAnnotations(currentFunction);

                    //Set async
                    var lambda = newFunction as LambdaExpression;
                    if (lambda != null)
                    {
                        lambda.IsAsync = true;
                    }
                    var anonymousMethod = newFunction as AnonymousMethodExpression;
                    if (anonymousMethod != null)
                    {
                        anonymousMethod.IsAsync = true;
                    }
                    var methodDeclaration = newFunction as MethodDeclaration;
                    if (methodDeclaration != null)
                    {
                        methodDeclaration.Modifiers |= Modifiers.Async;
                    }

                    TransformBody(invocations, isVoid, resultType != null, returnedContinuation, taskCompletionSourceIdentifier, newFunction.GetChildByRole(Roles.Body));

                    script.Replace(currentFunction, newFunction);
                }));
            }
        public void FindIfElseInWebMethod(AstNode invocation, CSharpFile file)
        {
            if (invocation.GetType().Name == "IfElseStatement" &&
                FindWebMethod(invocation.GetParent <MethodDeclaration>()))
            {
                Expression childOfTypeRoleCondition = invocation.GetChildByRole(Roles.Condition);
                if (childOfTypeRoleCondition.GetType().Name == "UnaryOperatorExpression")
                {
                    string strToCheck = "Valid" + invocation.GetParent <MethodDeclaration>().Name;

                    if (allPatterns.IfElseValidMethodUnary(strToCheck).Match(childOfTypeRoleCondition).Success)
                    {
                        file.IndexOfIfElStmt.Add((IfElseStatement)invocation);
                    }
                    else if (allPatterns.IfElseValidMethodUnaryOld().Match(childOfTypeRoleCondition).Success)
                    {
                        string strToCheckforAlreadyDeclared = childOfTypeRoleCondition.Descendants.OfType <IdentifierExpression>().First().GetText();
                        if (strToCheckforAlreadyDeclared.IndexOf(("valid"), StringComparison.OrdinalIgnoreCase) > 0)
                        {
                            file.IndexOfIfElStmtValidation.Add((IfElseStatement)invocation);
                        }
                    }
                    else if (allPatterns.IfElseValidMethodUnaryMemberRef().Match(childOfTypeRoleCondition).Success)
                    {
                        string strToCheckAlreadyDecare = childOfTypeRoleCondition.Descendants.OfType <MemberReferenceExpression>().First().LastChild.GetText();
                        if (strToCheckAlreadyDecare.IndexOf(("valid"), StringComparison.OrdinalIgnoreCase) > 0)
                        {
                            file.IndexOfIfElStmtValidation.Add((IfElseStatement)invocation);
                        }
                    }
                }
                else if (childOfTypeRoleCondition.GetType().Name == "BinaryOperatorExpression")
                {
                    if (allPatterns.IfElseValidMethodBinary().Match(childOfTypeRoleCondition).Success)
                    {
                        string strToCheck = childOfTypeRoleCondition.Descendants.OfType <IdentifierExpression>().First().GetText();
                        if (strToCheck.IndexOf("Valid", StringComparison.OrdinalIgnoreCase) > 0)
                        {
                            file.IndexOfIfElStmtValidation.Add((IfElseStatement)invocation);
                        }
                    }
                    else if (allPatterns.IfElseValidMethodBinaryMemberRef().Match(childOfTypeRoleCondition).Success)
                    {
                        string strToCheck = childOfTypeRoleCondition.Descendants.OfType <IdentifierExpression>().First().NextSibling.GetText();
                        if (strToCheck.IndexOf("Valid", StringComparison.OrdinalIgnoreCase) > 0)
                        {
                            file.IndexOfIfElStmtValidation.Add((IfElseStatement)invocation);
                        }
                    }
                }
                //else if ()
                //   if(childRole == "UnaryOperatorExpression" || childRole == "BinaryOperatorExpression")
                //     file.IndexOfIfElStmt.Add((IfElseStatement)invocation);

                /*                file.IndexOfIfElStmt.Add((IfElseStatement)invocation);
                 *              string strToCheck = null;
                 *              try{
                 *                  //strToCheck = invocation.FirstChild.NextSibling.NextSibling.FirstChild.NextSibling.FirstChild.GetText();
                 *                  strToCheck = invocation.GetChildByRole(Roles.Condition).DescendantsAndSelf.OfType<InvocationExpression>().First().Children.OfType<IdentifierExpression>().First().GetText();
                 *              }
                 *              catch(Exception) {}
                 *              if (strToCheck != null)
                 *              {
                 *                  if (strToCheck.IndexOf("Valid", StringComparison.OrdinalIgnoreCase) >= 0  &&
                 *                      FoundWebMethodAttribute(invocation.GetParent<MethodDeclaration>()))
                 *                  {
                 *                      if (strToCheck == "Valid" + invocation.GetParent<MethodDeclaration>().Name)
                 *                      {
                 *                          file.IndexOfIfElStmt.Add((IfElseStatement)invocation);
                 *                      }
                 *                      else
                 *                      {
                 *                          invocation.Descendants.OfType<InvocationExpression>().First().GetNodeAt(invocation.StartLocation, null);
                 *                          //foreach(var expr)
                 *                      }
                 * //                        else if()
                 *                  }
                 *              }
                 */
            }
        }