1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
|
#region license
// Copyright (c) 2004-2005, Daniel Grunwald (daniel@danielgrunwald.de)
// Copyright (c) 2005, Peter Johanson (latexer@gentoo.org)
// All rights reserved.
//
// The BooBinding.Parser code is originally that of Daniel Grunwald
// (daniel@danielgrunwald.de) from the SharpDevelop BooBinding. The code has
// been imported here, and modified, including, but not limited to, changes
// to function with MonoDevelop, additions, refactorings, etc.
//
// BooBinding is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// BooBinding is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with BooBinding; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#endregion
/*
namespace BooBinding.Parser
import System
import System.Collections
import MonoDevelop.Projects.Dom
import MonoDevelop.Projects.Dom.Parser
import Boo.Lang.Compiler.Ast
class ExpressionTypeVisitor(DepthFirstVisitor):
protected override def OnError(node as Node, error as Exception):
Error (error.ToString ())
super(node, error)
private def Log (message):
BooParser.Log (self.GetType (), message)
private def Error (message):
BooParser.Error (self.GetType (), message)
[Property(ReturnType)]
_returnType as IReturnType
[Property(ReturnClass)]
_returnClass as IClass
[Property(Resolver)]
_resolver as Resolver
private def CreateReturnType(fullClassName as string):
_returnClass = null
if fullClassName == null:
_returnType = null
else:
_returnType = BooBinding.Parser.ReturnType(fullClassName)
private def CreateReturnType(reference as TypeReference):
_returnClass = null
if reference == null:
_returnType = null
else:
_returnType = BooBinding.Parser.ReturnType(reference)
private def CreateReturnType(c as IClass):
_returnClass = c
if c == null:
_returnType = null
else:
_returnType = BooBinding.Parser.ReturnType(c)
private def SetReturnType(r as IReturnType):
_returnClass = null
_returnType = r
private def Debug(node):
if node == null:
Log ("-- null --")
else:
Log ("${node.ToString()} - ${node.GetType().FullName}")
override def OnBlockExpression(node as BlockExpression):
Debug(node)
CreateReturnType("System.Delegate")
override def OnMethodInvocationExpression(node as MethodInvocationExpression):
Debug(node)
Debug(node.Target)
if node.Target isa MemberReferenceExpression:
// call a method on another object
mre as MemberReferenceExpression = node.Target
Visit(mre.Target)
if _returnClass == null and _returnType != null:
_returnClass = _resolver.SearchType(_returnType.FullyQualifiedName, true)
return if ProcessMethod(node, mre.Name, _returnClass)
// try if the MemberReferenceExpression is a fully qualified class name (constructor call)
ProcessMemberReferenceExpression(mre.Name)
CreateReturnType(_returnClass)
elif node.Target isa ReferenceExpression:
re as ReferenceExpression = node.Target
// try if it is a method on the current object
return if ProcessMethod(node, re.Name, _resolver.CallingClass)
// try if it is a builtin method
return if ProcessMethod(node, re.Name, _resolver.BuiltinClass)
// try if it is a class name -> constructor
CreateReturnType(_resolver.SearchType(re.Name, true))
else:
SetReturnType(null)
private def ProcessMethod(node as MethodInvocationExpression, name as string, c as IClass) as bool:
return false if c == null
possibleOverloads = FindMethods(c, name, node.Arguments.Count)
Log ("found ${possibleOverloads.Count} overloads (multiple overloads not supported yet)")
if possibleOverloads.Count >= 1:
SetReturnType(cast(IMethod, possibleOverloads[0]).ReturnType)
return true
return false
private def FindMethods(c as IClass, name as string, arguments as int):
possibleOverloads = ArrayList()
//for cl as IClass in c.ClassInheritanceTree:
for cl as IClass in _resolver.ParserContext.GetClassInheritanceTree(c):
for m as IMethod in cl.Methods:
if m.Parameters.Count == arguments and name == m.Name:
possibleOverloads.Add(m)
return possibleOverloads
override def OnSlicingExpression(node as SlicingExpression):
Debug(node)
Visit(node.Target)
slice as Slice = node.Indices[0]
if (slice.End != null):
// Boo slice, returns a part of the source -> same type as source
return
if _returnType != null and _returnType.ArrayDimensions != null and _returnType.ArrayDimensions.Length > 0:
SetReturnType(BooBinding.Parser.ReturnType(_returnType.FullyQualifiedName, _returnType.ArrayDimensions[0 : _returnType.ArrayDimensions.Length - 1], 0))
return
if _returnClass == null and _returnType != null:
_returnClass = _resolver.SearchType(_returnType.FullyQualifiedName)
if _returnClass != null:
indexers = FindIndexer(_returnClass, 1)
if indexers.Count > 0:
SetReturnType(cast(IIndexer, indexers[0]).ReturnType)
return
SetReturnType(null)
private def FindIndexer(c as IClass, arguments as int):
possibleOverloads = ArrayList()
//for cl as IClass in c.ClassInheritanceTree:
for cl as IClass in _resolver.ParserContext.GetClassInheritanceTree(c):
for m as IIndexer in cl.Indexer:
if m.Parameters.Count == arguments:
possibleOverloads.Add(m)
return possibleOverloads
override def OnBinaryExpression(node as BinaryExpression):
Debug(node)
CombineTypes(node.Left, node.Right)
override def OnConditionalExpression(node as ConditionalExpression):
Debug(node)
CombineTypes(node.TrueValue, node.FalseValue)
private def CombineTypes(a as Expression, b as Expression):
Visit(a)
override def OnReferenceExpression(node as ReferenceExpression):
// Resolve reference (to a variable, field, parameter or type)
rt = _resolver.GetTypeFromLocal(node.Name)
if rt != null:
SetReturnType(rt)
return
return if ProcessMember(node.Name, _resolver.CallingClass)
if _resolver.IsNamespace(node.Name):
SetReturnType(NamespaceReturnType(node.Name))
else:
CreateReturnType(_resolver.SearchType(node.Name))
override def OnMemberReferenceExpression(node as MemberReferenceExpression):
Debug(node)
Visit(node.Target)
ProcessMemberReferenceExpression(node.Name)
private def ProcessMemberReferenceExpression(name as string):
"""Gets the return type of the MemberReferenceExpression with the specified name
on the current return type."""
if _returnType isa NamespaceReturnType:
name = _returnType.FullyQualifiedName + '.' + name
if _resolver.IsNamespace(name):
SetReturnType(NamespaceReturnType(name))
else:
CreateReturnType(_resolver.SearchType(name))
return
if _returnClass == null and _returnType != null:
_returnClass = _resolver.SearchType(_returnType.FullyQualifiedName)
return if ProcessMember(name, _returnClass)
SetReturnType(null)
private def ProcessMember(name as string, parentClass as IClass):
return false if parentClass == null
for cl as IClass in _resolver.ParserContext.GetClassInheritanceTree(parentClass):
for c as IClass in cl.InnerClasses:
if c.Name == name:
CreateReturnType(c)
return true
for f as IField in cl.Fields:
if f.Name == name:
SetReturnType(f.ReturnType)
return true
for p as IProperty in cl.Properties:
if p.Name == name:
SetReturnType(p.ReturnType)
return true
for m as IMethod in cl.Methods:
if m.Name == name:
CreateReturnType("System.Delegate")
return true
return false
override def OnTimeSpanLiteralExpression(node as TimeSpanLiteralExpression):
CreateReturnType("System.TimeSpan")
override def OnIntegerLiteralExpression(node as IntegerLiteralExpression):
CreateReturnType("System.Int32")
override def OnDoubleLiteralExpression(node as DoubleLiteralExpression):
CreateReturnType("System.Double")
override def OnNullLiteralExpression(node as NullLiteralExpression):
CreateReturnType("System.Object")
override def OnStringLiteralExpression(node as StringLiteralExpression):
CreateReturnType("System.String")
override def OnSelfLiteralExpression(node as SelfLiteralExpression):
CreateReturnType(_resolver.CallingClass)
override def OnSuperLiteralExpression(node as SuperLiteralExpression):
CreateReturnType(_resolver.ParentClass)
override def OnBoolLiteralExpression(node as BoolLiteralExpression):
CreateReturnType("System.Boolean")
override def OnRELiteralExpression(node as RELiteralExpression):
CreateReturnType("System.Text.RegularExpressions.Regex")
override def OnHashLiteralExpression(node as HashLiteralExpression):
CreateReturnType("System.Collections.Hashtable")
override def OnListLiteralExpression(node as ListLiteralExpression):
CreateReturnType("System.Collections.ArrayList")
override def OnArrayLiteralExpression(node as ArrayLiteralExpression):
CreateReturnType("System.Array")
override def OnTryCastExpression(node as TryCastExpression):
CreateReturnType(node.Type)
override def OnCastExpression(node as CastExpression):
CreateReturnType(node.Type)
override def OnTypeofExpression(node as TypeofExpression):
CreateReturnType("System.Type")
*/
|