~halega/+junk/sharpdevelop

« back to all changes in this revision

Viewing changes to src/AddIns/BackendBindings/Boo/BooBinding/Project/Src/CodeCompletion/InferredReturnType.cs

  • Committer: sk
  • Date: 2011-09-10 05:17:57 UTC
  • Revision ID: halega@halega.com-20110910051757-qfouz1llya9m6boy
4.1.0.7915 Release Candidate 1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
 
2
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
 
3
 
 
4
using System;
 
5
using Boo.Lang.Compiler.Ast;
 
6
using ICSharpCode.SharpDevelop;
 
7
using ICSharpCode.SharpDevelop.Dom;
 
8
 
 
9
namespace Grunwald.BooBinding.CodeCompletion
 
10
{
 
11
        /// <summary>
 
12
        /// Return type that is inferred from an expression.
 
13
        /// </summary>
 
14
        public class BooInferredReturnType : ProxyReturnType
 
15
        {
 
16
                Expression expression;
 
17
                Block block;
 
18
                IReturnType cachedType;
 
19
                IClass context;
 
20
                
 
21
                public BooInferredReturnType(Expression expression, IClass context)
 
22
                {
 
23
                        if (expression == null) throw new ArgumentNullException("expression");
 
24
                        this.context = context;
 
25
                        this.expression = expression;
 
26
                }
 
27
                
 
28
                bool useLastStatementIfNoReturnStatement;
 
29
                
 
30
                public BooInferredReturnType(Block block, IClass context, bool useLastStatementIfNoReturnStatement)
 
31
                {
 
32
                        if (block == null) throw new ArgumentNullException("block");
 
33
                        this.useLastStatementIfNoReturnStatement = useLastStatementIfNoReturnStatement;
 
34
                        this.block = block;
 
35
                        this.context = context;
 
36
                }
 
37
                
 
38
                public override IReturnType BaseType {
 
39
                        get {
 
40
                                // clear up references to method/expression after the type has been resolved
 
41
                                if (block != null) {
 
42
                                        GetReturnTypeVisitor v = new GetReturnTypeVisitor(this);
 
43
                                        Block b = block;
 
44
                                        block = null; // reset block before calling Visit to prevent StackOverflow
 
45
                                        v.Visit(b);
 
46
                                        if (v.noReturnStatement) {
 
47
                                                if (useLastStatementIfNoReturnStatement && v.lastExpressionStatement != null) {
 
48
                                                        cachedType = new BooResolver().GetTypeOfExpression(v.lastExpressionStatement.Expression, context);
 
49
                                                } else {
 
50
                                                        cachedType = ParserService.CurrentProjectContent.SystemTypes.Void;
 
51
                                                }
 
52
                                        } else if (v.result is NullReturnType) {
 
53
                                                cachedType = ConvertVisitor.GetDefaultReturnType(ParserService.CurrentProjectContent);
 
54
                                        } else {
 
55
                                                cachedType = v.result;
 
56
                                        }
 
57
                                } else if (expression != null) {
 
58
                                        Expression expr = expression;
 
59
                                        expression = null;
 
60
                                        cachedType = new BooResolver().GetTypeOfExpression(expr, context);
 
61
                                }
 
62
                                return cachedType;
 
63
                        }
 
64
                }
 
65
                
 
66
                class GetReturnTypeVisitor : DepthFirstVisitor
 
67
                {
 
68
                        IClass context;
 
69
                        BooInferredReturnType parentReturnType;
 
70
                        public GetReturnTypeVisitor(BooInferredReturnType parentReturnType)
 
71
                        {
 
72
                                this.context = parentReturnType.context;
 
73
                                this.parentReturnType = parentReturnType;
 
74
                        }
 
75
                        
 
76
                        public IReturnType result;
 
77
                        public bool noReturnStatement = true;
 
78
                        public ExpressionStatement lastExpressionStatement;
 
79
                        
 
80
                        public override void OnReturnStatement(ReturnStatement node)
 
81
                        {
 
82
                                noReturnStatement = false;
 
83
                                if (node.Expression == null) {
 
84
                                        result = ParserService.CurrentProjectContent.SystemTypes.Void;
 
85
                                } else {
 
86
                                        result = new BooResolver().GetTypeOfExpression(node.Expression, context);
 
87
                                }
 
88
                        }
 
89
                        
 
90
                        public override void OnExpressionStatement(ExpressionStatement node)
 
91
                        {
 
92
                                base.OnExpressionStatement(node);
 
93
                                lastExpressionStatement = node;
 
94
                        }
 
95
                        
 
96
                        public override void OnYieldStatement(YieldStatement node)
 
97
                        {
 
98
                                noReturnStatement = false;
 
99
                                
 
100
                                IProjectContent pc = context != null ? context.ProjectContent : ParserService.CurrentProjectContent;
 
101
                                IReturnType enumerable = new GetClassReturnType(pc, "System.Collections.Generic.IEnumerable", 1);
 
102
                                
 
103
                                // Prevent creating an infinite number of InferredReturnTypes in inferring cycles
 
104
                                parentReturnType.expression = new NullLiteralExpression();
 
105
                                IReturnType returnType;
 
106
                                if (node.Expression == null)
 
107
                                        returnType = ConvertVisitor.GetDefaultReturnType(pc);
 
108
                                else
 
109
                                        returnType = new BooResolver().GetTypeOfExpression(node.Expression, context);
 
110
                                if (returnType != null) {
 
111
                                        returnType.GetUnderlyingClass(); // force to infer type
 
112
                                }
 
113
                                if (parentReturnType.expression == null) {
 
114
                                        // inferrence cycle with parentReturnType
 
115
                                        returnType = new GetClassReturnType(pc, "?", 0);
 
116
                                }
 
117
                                parentReturnType.expression = null;
 
118
                                
 
119
                                result = new ConstructedReturnType(enumerable, new IReturnType[] { returnType });
 
120
                        }
 
121
                        
 
122
                        public override void OnBlockExpression(BlockExpression node)
 
123
                        {
 
124
                                // ignore return statements in callable blocks
 
125
                        }
 
126
                        
 
127
                        public override bool Visit(Node node)
 
128
                        {
 
129
                                if (result != null && !(result is NullReturnType))
 
130
                                        return false;
 
131
                                else
 
132
                                        return base.Visit(node);
 
133
                        }
 
134
                }
 
135
        }
 
136
}