/NRefactory/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs

http://github.com/icsharpcode/ILSpy · C# · 4103 lines · 3399 code · 401 blank · 303 comment · 866 complexity · d765836f7b4dab83d4130dae6a772643 MD5 · raw file

Large files are truncated click here to view the full file

  1. // Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy of this
  4. // software and associated documentation files (the "Software"), to deal in the Software
  5. // without restriction, including without limitation the rights to use, copy, modify, merge,
  6. // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
  7. // to whom the Software is furnished to do so, subject to the following conditions:
  8. //
  9. // The above copyright notice and this permission notice shall be included in all copies or
  10. // substantial portions of the Software.
  11. //
  12. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  13. // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  14. // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
  15. // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  16. // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  17. // DEALINGS IN THE SOFTWARE.
  18. using System;
  19. using System.Collections.Generic;
  20. using System.Diagnostics;
  21. using System.Linq;
  22. using System.Text;
  23. using System.Threading;
  24. using ICSharpCode.NRefactory.CSharp.Analysis;
  25. using ICSharpCode.NRefactory.CSharp.TypeSystem;
  26. using ICSharpCode.NRefactory.Semantics;
  27. using ICSharpCode.NRefactory.TypeSystem;
  28. using ICSharpCode.NRefactory.TypeSystem.Implementation;
  29. namespace ICSharpCode.NRefactory.CSharp.Resolver
  30. {
  31. /// <summary>
  32. /// Traverses the DOM and resolves expressions.
  33. /// </summary>
  34. /// <remarks>
  35. /// The ResolveVisitor does two jobs at the same time: it tracks the resolve context (properties on CSharpResolver)
  36. /// and it resolves the expressions visited.
  37. /// To allow using the context tracking without having to resolve every expression in the file (e.g. when you want to resolve
  38. /// only a single node deep within the DOM), you can use the <see cref="IResolveVisitorNavigator"/> interface.
  39. /// The navigator allows you to switch the between scanning mode and resolving mode.
  40. /// In scanning mode, the context is tracked (local variables registered etc.), but nodes are not resolved.
  41. /// While scanning, the navigator will get asked about every node that the resolve visitor is about to enter.
  42. /// This allows the navigator whether to keep scanning, whether switch to resolving mode, or whether to completely skip the
  43. /// subtree rooted at that node.
  44. ///
  45. /// In resolving mode, the context is tracked and nodes will be resolved.
  46. /// The resolve visitor may decide that it needs to resolve other nodes as well in order to resolve the current node.
  47. /// In this case, those nodes will be resolved automatically, without asking the navigator interface.
  48. /// For child nodes that are not essential to resolving, the resolve visitor will switch back to scanning mode (and thus will
  49. /// ask the navigator for further instructions).
  50. ///
  51. /// Moreover, there is the <c>ResolveAll</c> mode - it works similar to resolving mode, but will not switch back to scanning mode.
  52. /// The whole subtree will be resolved without notifying the navigator.
  53. /// </remarks>
  54. sealed class ResolveVisitor : IAstVisitor<ResolveResult>
  55. {
  56. // The ResolveVisitor is also responsible for handling lambda expressions.
  57. static readonly ResolveResult errorResult = ErrorResolveResult.UnknownError;
  58. CSharpResolver resolver;
  59. /// <summary>Resolve result of the current LINQ query.</summary>
  60. /// <remarks>We do not have to put this into the stored state (resolver) because
  61. /// query expressions are always resolved in a single operation.</remarks>
  62. ResolveResult currentQueryResult;
  63. readonly CSharpUnresolvedFile unresolvedFile;
  64. readonly Dictionary<AstNode, ResolveResult> resolveResultCache = new Dictionary<AstNode, ResolveResult>();
  65. readonly Dictionary<AstNode, CSharpResolver> resolverBeforeDict = new Dictionary<AstNode, CSharpResolver>();
  66. readonly Dictionary<AstNode, CSharpResolver> resolverAfterDict = new Dictionary<AstNode, CSharpResolver>();
  67. readonly Dictionary<Expression, ConversionWithTargetType> conversionDict = new Dictionary<Expression, ConversionWithTargetType>();
  68. internal struct ConversionWithTargetType
  69. {
  70. public readonly Conversion Conversion;
  71. public readonly IType TargetType;
  72. public ConversionWithTargetType(Conversion conversion, IType targetType)
  73. {
  74. this.Conversion = conversion;
  75. this.TargetType = targetType;
  76. }
  77. }
  78. IResolveVisitorNavigator navigator;
  79. bool resolverEnabled;
  80. List<LambdaBase> undecidedLambdas;
  81. internal CancellationToken cancellationToken;
  82. #region Constructor
  83. static readonly IResolveVisitorNavigator skipAllNavigator = new ConstantModeResolveVisitorNavigator(ResolveVisitorNavigationMode.Skip, null);
  84. /// <summary>
  85. /// Creates a new ResolveVisitor instance.
  86. /// </summary>
  87. public ResolveVisitor(CSharpResolver resolver, CSharpUnresolvedFile unresolvedFile)
  88. {
  89. if (resolver == null)
  90. throw new ArgumentNullException("resolver");
  91. this.resolver = resolver;
  92. this.unresolvedFile = unresolvedFile;
  93. this.navigator = skipAllNavigator;
  94. }
  95. internal void SetNavigator(IResolveVisitorNavigator navigator)
  96. {
  97. this.navigator = navigator ?? skipAllNavigator;
  98. }
  99. ResolveResult voidResult {
  100. get {
  101. return new ResolveResult(resolver.Compilation.FindType(KnownTypeCode.Void));
  102. }
  103. }
  104. #endregion
  105. #region ResetContext
  106. /// <summary>
  107. /// Resets the visitor to the stored position, runs the action, and then reverts the visitor to the previous position.
  108. /// </summary>
  109. void ResetContext(CSharpResolver storedContext, Action action)
  110. {
  111. var oldResolverEnabled = this.resolverEnabled;
  112. var oldResolver = this.resolver;
  113. var oldQueryResult = this.currentQueryResult;
  114. try {
  115. this.resolverEnabled = false;
  116. this.resolver = storedContext;
  117. this.currentQueryResult = null;
  118. action();
  119. } finally {
  120. this.resolverEnabled = oldResolverEnabled;
  121. this.resolver = oldResolver;
  122. this.currentQueryResult = oldQueryResult;
  123. }
  124. }
  125. #endregion
  126. #region Scan / Resolve
  127. /// <summary>
  128. /// Scans the AST rooted at the given node.
  129. /// </summary>
  130. public void Scan(AstNode node)
  131. {
  132. if (node == null || node.IsNull)
  133. return;
  134. switch (node.NodeType) {
  135. case NodeType.Token:
  136. case NodeType.Whitespace:
  137. return; // skip tokens, identifiers, comments, etc.
  138. }
  139. // don't Scan again if the node was already resolved
  140. if (resolveResultCache.ContainsKey(node)) {
  141. // Restore state change caused by this node:
  142. CSharpResolver newResolver;
  143. if (resolverAfterDict.TryGetValue(node, out newResolver))
  144. resolver = newResolver;
  145. return;
  146. }
  147. var mode = navigator.Scan(node);
  148. switch (mode) {
  149. case ResolveVisitorNavigationMode.Skip:
  150. if (node is VariableDeclarationStatement || node is SwitchSection) {
  151. // Enforce scanning of variable declarations.
  152. goto case ResolveVisitorNavigationMode.Scan;
  153. }
  154. StoreCurrentState(node);
  155. break;
  156. case ResolveVisitorNavigationMode.Scan:
  157. bool oldResolverEnabled = resolverEnabled;
  158. var oldResolver = resolver;
  159. resolverEnabled = false;
  160. StoreCurrentState(node);
  161. ResolveResult result = node.AcceptVisitor(this);
  162. if (result != null) {
  163. // If the node was resolved, store the result even though it wasn't requested.
  164. // This is necessary so that Visit-methods that decide to always resolve are
  165. // guaranteed to get called only once.
  166. // This is used for lambda registration.
  167. StoreResult(node, result);
  168. if (resolver != oldResolver) {
  169. // The node changed the resolver state:
  170. resolverAfterDict.Add(node, resolver);
  171. }
  172. cancellationToken.ThrowIfCancellationRequested();
  173. }
  174. resolverEnabled = oldResolverEnabled;
  175. break;
  176. case ResolveVisitorNavigationMode.Resolve:
  177. Resolve(node);
  178. break;
  179. default:
  180. throw new InvalidOperationException("Invalid value for ResolveVisitorNavigationMode");
  181. }
  182. }
  183. /// <summary>
  184. /// Equivalent to 'Scan', but also resolves the node at the same time.
  185. /// This method should be only used if the CSharpResolver passed to the ResolveVisitor was manually set
  186. /// to the correct state.
  187. /// Otherwise, use <c>resolver.Scan(syntaxTree); var result = resolver.GetResolveResult(node);</c>
  188. /// instead.
  189. /// --
  190. /// This method now is internal, because it is difficult to use correctly.
  191. /// Users of the public API should use Scan()+GetResolveResult() instead.
  192. /// </summary>
  193. internal ResolveResult Resolve(AstNode node)
  194. {
  195. if (node == null || node.IsNull)
  196. return errorResult;
  197. bool oldResolverEnabled = resolverEnabled;
  198. resolverEnabled = true;
  199. ResolveResult result;
  200. if (!resolveResultCache.TryGetValue(node, out result)) {
  201. cancellationToken.ThrowIfCancellationRequested();
  202. StoreCurrentState(node);
  203. var oldResolver = resolver;
  204. result = node.AcceptVisitor(this) ?? errorResult;
  205. StoreResult(node, result);
  206. if (resolver != oldResolver) {
  207. // The node changed the resolver state:
  208. resolverAfterDict.Add(node, resolver);
  209. }
  210. }
  211. resolverEnabled = oldResolverEnabled;
  212. return result;
  213. }
  214. IType ResolveType(AstType type)
  215. {
  216. return Resolve(type).Type;
  217. }
  218. void StoreCurrentState(AstNode node)
  219. {
  220. // It's possible that we re-visit an expression that we scanned over earlier,
  221. // so we might have to overwrite an existing state.
  222. #if DEBUG
  223. CSharpResolver oldResolver;
  224. if (resolverBeforeDict.TryGetValue(node, out oldResolver)) {
  225. Debug.Assert(oldResolver.LocalVariables.SequenceEqual(resolver.LocalVariables));
  226. }
  227. #endif
  228. resolverBeforeDict[node] = resolver;
  229. }
  230. void StoreResult(AstNode node, ResolveResult result)
  231. {
  232. Debug.Assert(result != null);
  233. if (node.IsNull)
  234. return;
  235. Log.WriteLine("Resolved '{0}' to {1}", node, result);
  236. Debug.Assert(!CSharpAstResolver.IsUnresolvableNode(node));
  237. // The state should be stored before the result is.
  238. Debug.Assert(resolverBeforeDict.ContainsKey(node));
  239. // Don't store results twice.
  240. Debug.Assert(!resolveResultCache.ContainsKey(node));
  241. // Don't use ConversionResolveResult as a result, because it can get
  242. // confused with an implicit conversion.
  243. Debug.Assert(!(result is ConversionResolveResult) || result is CastResolveResult);
  244. resolveResultCache[node] = result;
  245. if (navigator != null)
  246. navigator.Resolved(node, result);
  247. }
  248. void ScanChildren(AstNode node)
  249. {
  250. for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) {
  251. Scan(child);
  252. }
  253. }
  254. #endregion
  255. #region Process Conversions
  256. sealed class AnonymousFunctionConversion : Conversion
  257. {
  258. public readonly IType ReturnType;
  259. public readonly ExplicitlyTypedLambda ExplicitlyTypedLambda;
  260. public readonly LambdaTypeHypothesis Hypothesis;
  261. readonly bool isValid;
  262. public AnonymousFunctionConversion(IType returnType, LambdaTypeHypothesis hypothesis, bool isValid)
  263. {
  264. if (returnType == null)
  265. throw new ArgumentNullException("returnType");
  266. this.ReturnType = returnType;
  267. this.Hypothesis = hypothesis;
  268. this.isValid = isValid;
  269. }
  270. public AnonymousFunctionConversion(IType returnType, ExplicitlyTypedLambda explicitlyTypedLambda, bool isValid)
  271. {
  272. if (returnType == null)
  273. throw new ArgumentNullException("returnType");
  274. this.ReturnType = returnType;
  275. this.ExplicitlyTypedLambda = explicitlyTypedLambda;
  276. this.isValid = isValid;
  277. }
  278. public override bool IsValid {
  279. get { return isValid; }
  280. }
  281. public override bool IsImplicit {
  282. get { return true; }
  283. }
  284. public override bool IsAnonymousFunctionConversion {
  285. get { return true; }
  286. }
  287. }
  288. /// <summary>
  289. /// Convert 'rr' to the target type using the specified conversion.
  290. /// </summary>
  291. void ProcessConversion(Expression expr, ResolveResult rr, Conversion conversion, IType targetType)
  292. {
  293. AnonymousFunctionConversion afc = conversion as AnonymousFunctionConversion;
  294. if (afc != null) {
  295. Log.WriteLine("Processing conversion of anonymous function to " + targetType + "...");
  296. Log.Indent();
  297. if (afc.Hypothesis != null)
  298. afc.Hypothesis.MergeInto(this, afc.ReturnType);
  299. if (afc.ExplicitlyTypedLambda != null)
  300. afc.ExplicitlyTypedLambda.ApplyReturnType(this, afc.ReturnType);
  301. Log.Unindent();
  302. }
  303. if (expr != null && !expr.IsNull && conversion != Conversion.IdentityConversion) {
  304. navigator.ProcessConversion(expr, rr, conversion, targetType);
  305. conversionDict[expr] = new ConversionWithTargetType(conversion, targetType);
  306. }
  307. }
  308. void ImportConversions(ResolveVisitor childVisitor)
  309. {
  310. foreach (var pair in childVisitor.conversionDict) {
  311. conversionDict.Add(pair.Key, pair.Value);
  312. navigator.ProcessConversion(pair.Key, resolveResultCache[pair.Key], pair.Value.Conversion, pair.Value.TargetType);
  313. }
  314. }
  315. /// <summary>
  316. /// Convert 'rr' to the target type.
  317. /// </summary>
  318. void ProcessConversion(Expression expr, ResolveResult rr, IType targetType)
  319. {
  320. if (expr == null || expr.IsNull)
  321. return;
  322. ProcessConversion(expr, rr, resolver.conversions.ImplicitConversion(rr, targetType), targetType);
  323. }
  324. /// <summary>
  325. /// Resolves the specified expression and processes the conversion to targetType.
  326. /// </summary>
  327. void ResolveAndProcessConversion(Expression expr, IType targetType)
  328. {
  329. if (targetType.Kind == TypeKind.Unknown) {
  330. // no need to resolve the expression right now
  331. Scan(expr);
  332. } else {
  333. ProcessConversion(expr, Resolve(expr), targetType);
  334. }
  335. }
  336. void ProcessConversionResult(Expression expr, ConversionResolveResult rr)
  337. {
  338. if (rr != null && !(rr is CastResolveResult))
  339. ProcessConversion(expr, rr.Input, rr.Conversion, rr.Type);
  340. }
  341. void ProcessConversionResults(IEnumerable<Expression> expr, IEnumerable<ResolveResult> conversionResolveResults)
  342. {
  343. Debug.Assert(expr.Count() == conversionResolveResults.Count());
  344. using (var e1 = expr.GetEnumerator()) {
  345. using (var e2 = conversionResolveResults.GetEnumerator()) {
  346. while (e1.MoveNext() && e2.MoveNext()) {
  347. ProcessConversionResult(e1.Current, e2.Current as ConversionResolveResult);
  348. }
  349. }
  350. }
  351. }
  352. void MarkUnknownNamedArguments(IEnumerable<Expression> arguments)
  353. {
  354. foreach (var nae in arguments.OfType<NamedArgumentExpression>()) {
  355. StoreCurrentState(nae);
  356. StoreResult(nae, new NamedArgumentResolveResult(nae.Name, resolveResultCache[nae.Expression]));
  357. }
  358. }
  359. void ProcessInvocationResult(Expression target, IEnumerable<Expression> arguments, ResolveResult invocation)
  360. {
  361. if (invocation is CSharpInvocationResolveResult || invocation is DynamicInvocationResolveResult) {
  362. int i = 0;
  363. IList<ResolveResult> argumentsRR;
  364. if (invocation is CSharpInvocationResolveResult) {
  365. var csi = (CSharpInvocationResolveResult)invocation;
  366. if (csi.IsExtensionMethodInvocation) {
  367. Debug.Assert(arguments.Count() + 1 == csi.Arguments.Count);
  368. ProcessConversionResult(target, csi.Arguments[0] as ConversionResolveResult);
  369. i = 1;
  370. } else {
  371. Debug.Assert(arguments.Count() == csi.Arguments.Count);
  372. }
  373. argumentsRR = csi.Arguments;
  374. }
  375. else {
  376. argumentsRR = ((DynamicInvocationResolveResult)invocation).Arguments;
  377. }
  378. foreach (Expression arg in arguments) {
  379. ResolveResult argRR = argumentsRR[i++];
  380. NamedArgumentExpression nae = arg as NamedArgumentExpression;
  381. NamedArgumentResolveResult nrr = argRR as NamedArgumentResolveResult;
  382. Debug.Assert((nae == null) == (nrr == null));
  383. if (nae != null && nrr != null) {
  384. StoreCurrentState(nae);
  385. StoreResult(nae, nrr);
  386. ProcessConversionResult(nae.Expression, nrr.Argument as ConversionResolveResult);
  387. } else {
  388. ProcessConversionResult(arg, argRR as ConversionResolveResult);
  389. }
  390. }
  391. }
  392. else {
  393. MarkUnknownNamedArguments(arguments);
  394. }
  395. }
  396. #endregion
  397. #region GetResolveResult
  398. /// <summary>
  399. /// Gets the resolve result for the specified node.
  400. /// If the node was not resolved by the navigator, this method will resolve it.
  401. /// </summary>
  402. public ResolveResult GetResolveResult(AstNode node)
  403. {
  404. Debug.Assert(!CSharpAstResolver.IsUnresolvableNode(node));
  405. MergeUndecidedLambdas();
  406. ResolveResult result;
  407. if (resolveResultCache.TryGetValue(node, out result))
  408. return result;
  409. AstNode parent;
  410. CSharpResolver storedResolver = GetPreviouslyScannedContext(node, out parent);
  411. ResetContext(
  412. storedResolver,
  413. delegate {
  414. navigator = new NodeListResolveVisitorNavigator(node);
  415. Debug.Assert(!resolverEnabled);
  416. Scan(parent);
  417. navigator = skipAllNavigator;
  418. });
  419. MergeUndecidedLambdas();
  420. return resolveResultCache[node];
  421. }
  422. CSharpResolver GetPreviouslyScannedContext(AstNode node, out AstNode parent)
  423. {
  424. parent = node;
  425. CSharpResolver storedResolver;
  426. while (!resolverBeforeDict.TryGetValue(parent, out storedResolver)) {
  427. AstNode tmp = parent.Parent;
  428. if (tmp == null)
  429. throw new InvalidOperationException("Could not find a resolver state for any parent of the specified node. Are you trying to resolve a node that is not a descendant of the CSharpAstResolver's root node?");
  430. if (tmp.NodeType == NodeType.Whitespace)
  431. return resolver; // special case: resolve expression within preprocessor directive
  432. parent = tmp;
  433. }
  434. return storedResolver;
  435. }
  436. /// <summary>
  437. /// Gets the resolver state in front of the specified node.
  438. /// If the node was not visited by a previous scanning process, the
  439. /// AST will be scanned again to determine the state.
  440. /// </summary>
  441. public CSharpResolver GetResolverStateBefore(AstNode node)
  442. {
  443. MergeUndecidedLambdas();
  444. CSharpResolver r;
  445. if (resolverBeforeDict.TryGetValue(node, out r))
  446. return r;
  447. AstNode parent;
  448. CSharpResolver storedResolver = GetPreviouslyScannedContext(node, out parent);
  449. ResetContext(
  450. storedResolver,
  451. delegate {
  452. navigator = new NodeListResolveVisitorNavigator(new[] { node }, scanOnly: true);
  453. Debug.Assert(!resolverEnabled);
  454. // parent might already be resolved if 'node' is an unresolvable node
  455. Scan(parent);
  456. navigator = skipAllNavigator;
  457. });
  458. MergeUndecidedLambdas();
  459. while (node != null) {
  460. if (resolverBeforeDict.TryGetValue(node, out r))
  461. return r;
  462. node = node.Parent;
  463. }
  464. return null;
  465. }
  466. public CSharpResolver GetResolverStateAfter(AstNode node)
  467. {
  468. // Resolve the node to fill the resolverAfterDict
  469. GetResolveResult(node);
  470. CSharpResolver result;
  471. if (resolverAfterDict.TryGetValue(node, out result))
  472. return result;
  473. else
  474. return GetResolverStateBefore(node);
  475. }
  476. public ConversionWithTargetType GetConversionWithTargetType(Expression expr)
  477. {
  478. GetResolverStateBefore(expr);
  479. ResolveParentForConversion(expr);
  480. ConversionWithTargetType result;
  481. if (conversionDict.TryGetValue(expr, out result)) {
  482. return result;
  483. } else {
  484. ResolveResult rr = GetResolveResult(expr);
  485. return new ConversionWithTargetType(Conversion.IdentityConversion, rr.Type);
  486. }
  487. }
  488. #endregion
  489. #region Track UsingScope
  490. ResolveResult IAstVisitor<ResolveResult>.VisitSyntaxTree(SyntaxTree unit)
  491. {
  492. CSharpResolver previousResolver = resolver;
  493. try {
  494. if (unresolvedFile != null) {
  495. resolver = resolver.WithCurrentUsingScope(unresolvedFile.RootUsingScope.Resolve(resolver.Compilation));
  496. } else {
  497. var cv = new TypeSystemConvertVisitor(unit.FileName ?? string.Empty);
  498. ApplyVisitorToUsings(cv, unit.Children);
  499. PushUsingScope(cv.UnresolvedFile.RootUsingScope);
  500. }
  501. ScanChildren(unit);
  502. return voidResult;
  503. } finally {
  504. resolver = previousResolver;
  505. }
  506. }
  507. void ApplyVisitorToUsings(TypeSystemConvertVisitor visitor, IEnumerable<AstNode> children)
  508. {
  509. foreach (var child in children) {
  510. if (child is ExternAliasDeclaration || child is UsingDeclaration || child is UsingAliasDeclaration) {
  511. child.AcceptVisitor(visitor);
  512. }
  513. }
  514. }
  515. void PushUsingScope(UsingScope usingScope)
  516. {
  517. usingScope.Freeze();
  518. resolver = resolver.WithCurrentUsingScope(new ResolvedUsingScope(resolver.CurrentTypeResolveContext, usingScope));
  519. }
  520. ResolveResult IAstVisitor<ResolveResult>.VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration)
  521. {
  522. CSharpResolver previousResolver = resolver;
  523. try {
  524. var nsName = namespaceDeclaration.NamespaceName;
  525. AstNode child = namespaceDeclaration.FirstChild;
  526. for (; child != null && child.Role != Roles.LBrace; child = child.NextSibling) {
  527. Scan(child);
  528. }
  529. if (unresolvedFile != null) {
  530. resolver = resolver.WithCurrentUsingScope(unresolvedFile.GetUsingScope(namespaceDeclaration.StartLocation).Resolve(resolver.Compilation));
  531. } else {
  532. // string fileName = namespaceDeclaration.GetRegion().FileName ?? string.Empty;
  533. // Fetch parent using scope
  534. // Create root using scope if necessary
  535. if (resolver.CurrentUsingScope == null)
  536. PushUsingScope(new UsingScope());
  537. // Create child using scope
  538. DomRegion region = namespaceDeclaration.GetRegion();
  539. var identifiers = namespaceDeclaration.Identifiers.ToList();
  540. // For all but the last identifier:
  541. UsingScope usingScope;
  542. for (int i = 0; i < identifiers.Count - 1; i++) {
  543. usingScope = new UsingScope(resolver.CurrentUsingScope.UnresolvedUsingScope, identifiers[i]);
  544. usingScope.Region = region;
  545. PushUsingScope(usingScope);
  546. }
  547. // Last using scope:
  548. usingScope = new UsingScope(resolver.CurrentUsingScope.UnresolvedUsingScope, identifiers.Last());
  549. usingScope.Region = region;
  550. var cv = new TypeSystemConvertVisitor(new CSharpUnresolvedFile(), usingScope);
  551. ApplyVisitorToUsings(cv, namespaceDeclaration.Children);
  552. PushUsingScope(usingScope);
  553. }
  554. for (; child != null; child = child.NextSibling) {
  555. Scan(child);
  556. }
  557. // merge undecided lambdas before leaving the using scope so that
  558. // the resolver can make better use of its cache
  559. MergeUndecidedLambdas();
  560. if (resolver.CurrentUsingScope != null && resolver.CurrentUsingScope.Namespace != null)
  561. return new NamespaceResolveResult(resolver.CurrentUsingScope.Namespace);
  562. else
  563. return null;
  564. } finally {
  565. resolver = previousResolver;
  566. }
  567. }
  568. #endregion
  569. #region Track CurrentTypeDefinition
  570. ResolveResult VisitTypeOrDelegate(AstNode typeDeclaration, string name, int typeParameterCount)
  571. {
  572. CSharpResolver previousResolver = resolver;
  573. try {
  574. ITypeDefinition newTypeDefinition = null;
  575. if (resolver.CurrentTypeDefinition != null) {
  576. int totalTypeParameterCount = resolver.CurrentTypeDefinition.TypeParameterCount + typeParameterCount;
  577. foreach (ITypeDefinition nestedType in resolver.CurrentTypeDefinition.NestedTypes) {
  578. if (nestedType.Name == name && nestedType.TypeParameterCount == totalTypeParameterCount) {
  579. newTypeDefinition = nestedType;
  580. break;
  581. }
  582. }
  583. } else if (resolver.CurrentUsingScope != null) {
  584. newTypeDefinition = resolver.CurrentUsingScope.Namespace.GetTypeDefinition(name, typeParameterCount);
  585. }
  586. if (newTypeDefinition != null)
  587. resolver = resolver.WithCurrentTypeDefinition(newTypeDefinition);
  588. ScanChildren(typeDeclaration);
  589. // merge undecided lambdas before leaving the type definition so that
  590. // the resolver can make better use of its cache
  591. MergeUndecidedLambdas();
  592. return newTypeDefinition != null ? new TypeResolveResult(newTypeDefinition) : errorResult;
  593. } finally {
  594. resolver = previousResolver;
  595. }
  596. }
  597. ResolveResult IAstVisitor<ResolveResult>.VisitTypeDeclaration(TypeDeclaration typeDeclaration)
  598. {
  599. return VisitTypeOrDelegate(typeDeclaration, typeDeclaration.Name, typeDeclaration.TypeParameters.Count);
  600. }
  601. ResolveResult IAstVisitor<ResolveResult>.VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration)
  602. {
  603. return VisitTypeOrDelegate(delegateDeclaration, delegateDeclaration.Name, delegateDeclaration.TypeParameters.Count);
  604. }
  605. #endregion
  606. #region Track CurrentMember
  607. ResolveResult IAstVisitor<ResolveResult>.VisitFieldDeclaration(FieldDeclaration fieldDeclaration)
  608. {
  609. return VisitFieldOrEventDeclaration(fieldDeclaration, SymbolKind.Field);
  610. }
  611. ResolveResult IAstVisitor<ResolveResult>.VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration)
  612. {
  613. return VisitFieldOrEventDeclaration(fixedFieldDeclaration, SymbolKind.Field);
  614. }
  615. ResolveResult IAstVisitor<ResolveResult>.VisitEventDeclaration(EventDeclaration eventDeclaration)
  616. {
  617. return VisitFieldOrEventDeclaration(eventDeclaration, SymbolKind.Event);
  618. }
  619. ResolveResult VisitFieldOrEventDeclaration(EntityDeclaration fieldOrEventDeclaration, SymbolKind symbolKind)
  620. {
  621. //int initializerCount = fieldOrEventDeclaration.GetChildrenByRole(Roles.Variable).Count;
  622. CSharpResolver oldResolver = resolver;
  623. for (AstNode node = fieldOrEventDeclaration.FirstChild; node != null; node = node.NextSibling) {
  624. if (node.Role == Roles.Variable || node.Role == FixedFieldDeclaration.VariableRole) {
  625. IMember member;
  626. if (unresolvedFile != null) {
  627. member = GetMemberFromLocation(node);
  628. } else {
  629. string name = ((VariableInitializer)node).Name;
  630. member = AbstractUnresolvedMember.Resolve(resolver.CurrentTypeResolveContext, symbolKind, name);
  631. }
  632. resolver = resolver.WithCurrentMember(member);
  633. Scan(node);
  634. resolver = oldResolver;
  635. } else {
  636. Scan(node);
  637. }
  638. }
  639. return voidResult;
  640. }
  641. IMember GetMemberFromLocation(AstNode node)
  642. {
  643. ITypeDefinition typeDef = resolver.CurrentTypeDefinition;
  644. if (typeDef == null)
  645. return null;
  646. TextLocation location = TypeSystemConvertVisitor.GetStartLocationAfterAttributes(node);
  647. return typeDef.GetMembers(
  648. delegate (IUnresolvedMember m) {
  649. if (m.UnresolvedFile != unresolvedFile)
  650. return false;
  651. DomRegion region = m.Region;
  652. return !region.IsEmpty && region.Begin <= location && region.End > location;
  653. },
  654. GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions
  655. ).FirstOrDefault();
  656. }
  657. ResolveResult IAstVisitor<ResolveResult>.VisitVariableInitializer(VariableInitializer variableInitializer)
  658. {
  659. // Within the variable initializer, the newly declared variable is not yet available:
  660. var resolverWithVariable = resolver;
  661. if (variableInitializer.Parent is VariableDeclarationStatement)
  662. resolver = resolver.PopLastVariable();
  663. ArrayInitializerExpression aie = variableInitializer.Initializer as ArrayInitializerExpression;
  664. if (resolverEnabled || aie != null) {
  665. ResolveResult result = errorResult;
  666. if (variableInitializer.Parent is FieldDeclaration || variableInitializer.Parent is EventDeclaration) {
  667. if (resolver.CurrentMember != null) {
  668. result = new MemberResolveResult(null, resolver.CurrentMember, false);
  669. }
  670. } else {
  671. string identifier = variableInitializer.Name;
  672. foreach (IVariable v in resolverWithVariable.LocalVariables) {
  673. if (v.Name == identifier) {
  674. result = new LocalResolveResult(v);
  675. break;
  676. }
  677. }
  678. }
  679. ArrayType arrayType = result.Type as ArrayType;
  680. if (aie != null && arrayType != null) {
  681. StoreCurrentState(aie);
  682. List<Expression> initializerElements = new List<Expression>();
  683. int[] sizes = new int[arrayType.Dimensions];
  684. UnpackArrayInitializer(initializerElements, sizes, aie, 0, true);
  685. ResolveResult[] initializerElementResults = new ResolveResult[initializerElements.Count];
  686. for (int i = 0; i < initializerElementResults.Length; i++) {
  687. initializerElementResults[i] = Resolve(initializerElements[i]);
  688. }
  689. var arrayCreation = resolver.ResolveArrayCreation(arrayType.ElementType, sizes, initializerElementResults);
  690. StoreResult(aie, arrayCreation);
  691. ProcessConversionResults(initializerElements, arrayCreation.InitializerElements);
  692. } else if (variableInitializer.Parent is FixedStatement) {
  693. var initRR = Resolve(variableInitializer.Initializer);
  694. PointerType pointerType;
  695. if (initRR.Type.Kind == TypeKind.Array) {
  696. pointerType = new PointerType(((ArrayType)initRR.Type).ElementType);
  697. } else if (ReflectionHelper.GetTypeCode(initRR.Type) == TypeCode.String) {
  698. pointerType = new PointerType(resolver.Compilation.FindType(KnownTypeCode.Char));
  699. } else {
  700. pointerType = null;
  701. ProcessConversion(variableInitializer.Initializer, initRR, result.Type);
  702. }
  703. if (pointerType != null) {
  704. var conversion = resolver.conversions.ImplicitConversion(pointerType, result.Type);
  705. if (conversion.IsIdentityConversion)
  706. conversion = Conversion.ImplicitPointerConversion;
  707. ProcessConversion(variableInitializer.Initializer, initRR, conversion, result.Type);
  708. }
  709. } else {
  710. ResolveAndProcessConversion(variableInitializer.Initializer, result.Type);
  711. }
  712. resolver = resolverWithVariable;
  713. return result;
  714. } else {
  715. Scan(variableInitializer.Initializer);
  716. resolver = resolverWithVariable;
  717. return null;
  718. }
  719. }
  720. ResolveResult IAstVisitor<ResolveResult>.VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer)
  721. {
  722. if (resolverEnabled) {
  723. ResolveResult result = errorResult;
  724. if (resolver.CurrentMember != null) {
  725. result = new MemberResolveResult(null, resolver.CurrentMember, false);
  726. }
  727. ResolveAndProcessConversion(fixedVariableInitializer.CountExpression, resolver.Compilation.FindType(KnownTypeCode.Int32));
  728. return result;
  729. } else {
  730. ScanChildren(fixedVariableInitializer);
  731. return null;
  732. }
  733. }
  734. ResolveResult VisitMethodMember(EntityDeclaration memberDeclaration)
  735. {
  736. CSharpResolver oldResolver = resolver;
  737. try {
  738. IMember member = null;
  739. if (unresolvedFile != null) {
  740. member = GetMemberFromLocation(memberDeclaration);
  741. }
  742. if (member == null) {
  743. // Re-discover the method:
  744. SymbolKind symbolKind = memberDeclaration.SymbolKind;
  745. var parameterTypes = TypeSystemConvertVisitor.GetParameterTypes(memberDeclaration.GetChildrenByRole(Roles.Parameter), InterningProvider.Dummy);
  746. if (symbolKind == SymbolKind.Constructor) {
  747. string name = memberDeclaration.HasModifier(Modifiers.Static) ? ".cctor" : ".ctor";
  748. member = AbstractUnresolvedMember.Resolve(
  749. resolver.CurrentTypeResolveContext, symbolKind, name,
  750. parameterTypeReferences: parameterTypes);
  751. } else if (symbolKind == SymbolKind.Destructor) {
  752. member = AbstractUnresolvedMember.Resolve(resolver.CurrentTypeResolveContext, symbolKind, "Finalize");
  753. } else {
  754. string[] typeParameterNames = memberDeclaration.GetChildrenByRole(Roles.TypeParameter).Select(tp => tp.Name).ToArray();
  755. AstType explicitInterfaceAstType = memberDeclaration.GetChildByRole(EntityDeclaration.PrivateImplementationTypeRole);
  756. ITypeReference explicitInterfaceType = null;
  757. if (!explicitInterfaceAstType.IsNull) {
  758. explicitInterfaceType = explicitInterfaceAstType.ToTypeReference();
  759. }
  760. member = AbstractUnresolvedMember.Resolve(
  761. resolver.CurrentTypeResolveContext, symbolKind, memberDeclaration.Name,
  762. explicitInterfaceType, typeParameterNames, parameterTypes);
  763. }
  764. }
  765. resolver = resolver.WithCurrentMember(member);
  766. ScanChildren(memberDeclaration);
  767. if (member != null)
  768. return new MemberResolveResult(null, member, false);
  769. else
  770. return errorResult;
  771. } finally {
  772. resolver = oldResolver;
  773. }
  774. }
  775. ResolveResult IAstVisitor<ResolveResult>.VisitMethodDeclaration(MethodDeclaration methodDeclaration)
  776. {
  777. return VisitMethodMember(methodDeclaration);
  778. }
  779. ResolveResult IAstVisitor<ResolveResult>.VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration)
  780. {
  781. return VisitMethodMember(operatorDeclaration);
  782. }
  783. ResolveResult IAstVisitor<ResolveResult>.VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration)
  784. {
  785. return VisitMethodMember(constructorDeclaration);
  786. }
  787. ResolveResult IAstVisitor<ResolveResult>.VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration)
  788. {
  789. return VisitMethodMember(destructorDeclaration);
  790. }
  791. // handle properties/indexers
  792. ResolveResult VisitPropertyMember(EntityDeclaration propertyOrIndexerDeclaration)
  793. {
  794. CSharpResolver oldResolver = resolver;
  795. try {
  796. IMember member;
  797. if (unresolvedFile != null) {
  798. member = GetMemberFromLocation(propertyOrIndexerDeclaration);
  799. } else {
  800. // Re-discover the property:
  801. string name = propertyOrIndexerDeclaration.Name;
  802. var parameterTypeReferences = TypeSystemConvertVisitor.GetParameterTypes(propertyOrIndexerDeclaration.GetChildrenByRole(Roles.Parameter), InterningProvider.Dummy);
  803. AstType explicitInterfaceAstType = propertyOrIndexerDeclaration.GetChildByRole(EntityDeclaration.PrivateImplementationTypeRole);
  804. ITypeReference explicitInterfaceType = null;
  805. if (!explicitInterfaceAstType.IsNull) {
  806. explicitInterfaceType = explicitInterfaceAstType.ToTypeReference();
  807. }
  808. member = AbstractUnresolvedMember.Resolve(
  809. resolver.CurrentTypeResolveContext, propertyOrIndexerDeclaration.SymbolKind, name,
  810. explicitInterfaceType, parameterTypeReferences: parameterTypeReferences);
  811. }
  812. // We need to use the property as current member so that indexer parameters can be resolved correctly.
  813. resolver = resolver.WithCurrentMember(member);
  814. var resolverWithPropertyAsMember = resolver;
  815. for (AstNode node = propertyOrIndexerDeclaration.FirstChild; node != null; node = node.NextSibling) {
  816. if (node.Role == PropertyDeclaration.GetterRole && member is IProperty) {
  817. resolver = resolver.WithCurrentMember(((IProperty)member).Getter);
  818. Scan(node);
  819. resolver = resolverWithPropertyAsMember;
  820. } else if (node.Role == PropertyDeclaration.SetterRole && member is IProperty) {
  821. resolver = resolver.WithCurrentMember(((IProperty)member).Setter);
  822. Scan(node);
  823. resolver = resolverWithPropertyAsMember;
  824. } else {
  825. Scan(node);
  826. }
  827. }
  828. if (member != null)
  829. return new MemberResolveResult(null, member, false);
  830. else
  831. return errorResult;
  832. } finally {
  833. resolver = oldResolver;
  834. }
  835. }
  836. ResolveResult IAstVisitor<ResolveResult>.VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration)
  837. {
  838. return VisitPropertyMember(propertyDeclaration);
  839. }
  840. ResolveResult IAstVisitor<ResolveResult>.VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration)
  841. {
  842. return VisitPropertyMember(indexerDeclaration);
  843. }
  844. ResolveResult IAstVisitor<ResolveResult>.VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration)
  845. {
  846. CSharpResolver oldResolver = resolver;
  847. try {
  848. IMember member;
  849. if (unresolvedFile != null) {
  850. member = GetMemberFromLocation(eventDeclaration);
  851. } else {
  852. string name = eventDeclaration.Name;
  853. AstType explicitInterfaceAstType = eventDeclaration.PrivateImplementationType;
  854. if (explicitInterfaceAstType.IsNull) {
  855. member = AbstractUnresolvedMember.Resolve(resolver.CurrentTypeResolveContext, SymbolKind.Event, name);
  856. } else {
  857. member = AbstractUnresolvedMember.Resolve(resolver.CurrentTypeResolveContext, SymbolKind.Event, name,
  858. explicitInterfaceAstType.ToTypeReference());
  859. }
  860. }
  861. resolver = resolver.WithCurrentMember(member);
  862. var resolverWithEventAsMember = resolver;
  863. for (AstNode node = eventDeclaration.FirstChild; node != null; node = node.NextSibling) {
  864. if (node.Role == CustomEventDeclaration.AddAccessorRole && member is IEvent) {
  865. resolver = resolver.WithCurrentMember(((IEvent)member).AddAccessor);
  866. Scan(node);
  867. resolver = resolverWithEventAsMember;
  868. } else if (node.Role == CustomEventDeclaration.RemoveAccessorRole && member is IEvent) {
  869. resolver = resolver.WithCurrentMember(((IEvent)member).RemoveAccessor);
  870. Scan(node);
  871. resolver = resolverWithEventAsMember;
  872. } else {
  873. Scan(node);
  874. }
  875. }
  876. if (member != null)
  877. return new MemberResolveResult(null, member, false);
  878. else
  879. return errorResult;
  880. } finally {
  881. resolver = oldResolver;
  882. }
  883. }
  884. ResolveResult IAstVisitor<ResolveResult>.VisitParameterDeclaration(ParameterDeclaration parameterDeclaration)
  885. {
  886. ScanChildren(parameterDeclaration);
  887. if (resolverEnabled) {
  888. string name = parameterDeclaration.Name;
  889. if (parameterDeclaration.Parent is DocumentationReference) {
  890. // create a dummy parameter
  891. IType type = ResolveType(parameterDeclaration.Type);
  892. switch (parameterDeclaration.ParameterModifier) {
  893. case ParameterModifier.Ref:
  894. case ParameterModifier.Out:
  895. type = new ByReferenceType(type);
  896. break;
  897. }
  898. return new LocalResolveResult(new DefaultParameter(
  899. type, name,
  900. isRef: parameterDeclaration.ParameterModifier == ParameterModifier.Ref,
  901. isOut: parameterDeclaration.ParameterModifier == ParameterModifier.Out,
  902. isParams: parameterDeclaration.ParameterModifier == ParameterModifier.Params));
  903. }
  904. // Look in lambda parameters:
  905. foreach (IParameter p in resolver.LocalVariables.OfType<IParameter>()) {
  906. if (p.Name == name)
  907. return new LocalResolveResult(p);
  908. }
  909. IParameterizedMember pm = resolver.CurrentMember as IParameterizedMember;
  910. if (pm == null && resolver.CurrentTypeDefinition != null) {
  911. // Also consider delegate parameters:
  912. pm = resolver.CurrentTypeDefinition.GetDelegateInvokeMethod();
  913. // pm will be null if the current type isn't a delegate
  914. }
  915. if (pm != null) {
  916. foreach (IParameter p in pm.Parameters) {
  917. if (p.Name == name) {
  918. return new LocalResolveResult(p);
  919. }
  920. }
  921. }
  922. return errorResult;
  923. } else {
  924. return null;
  925. }
  926. }
  927. ResolveResult IAstVisitor<ResolveResult>.VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration)
  928. {
  929. ScanChildren(typeParameterDeclaration);
  930. if (resolverEnabled) {
  931. string name = typeParameterDeclaration.Name;
  932. IMethod m = resolver.CurrentMember as IMethod;
  933. if (m != null) {
  934. foreach (var tp in m.TypeParameters) {
  935. if (tp.Name == name)
  936. return new TypeResolveResult(tp);
  937. }
  938. }
  939. if (resolver.CurrentTypeDefinition != null) {
  940. var typeParameters = resolver.CurrentTypeDefinition.TypeParameters;
  941. // look backwards so that TPs in the current type take precedence over those copied from outer types
  942. for (int i = typeParameters.Count - 1; i >= 0; i--) {
  943. if (typeParameters[i].Name == name)
  944. return new TypeResolveResult(typeParameters[i]);
  945. }
  946. }
  947. return errorResult;
  948. } else {
  949. return null;
  950. }
  951. }
  952. ResolveResult IAstVisitor<ResolveResult>.VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration)
  953. {
  954. CSharpResolver oldResolver = resolver;
  955. try {
  956. // Scan enum member attributes before setting resolver.CurrentMember, so that
  957. // enum values used as attribute arguments have the correct type.
  958. // (within an enum member, all other enum members are treated as having their underlying type)
  959. foreach (var attributeSection in enumMemberDeclaration.Attributes)
  960. Scan(attributeSection);
  961. IMember member = null;
  962. if (unresolvedFile != null) {
  963. member = GetMemberFromLocation(enumMemberDeclaration);
  964. } else if (resolver.CurrentTypeDefinition != null) {
  965. string name = enumMemberDeclaration.Name;
  966. member = resolver.CurrentTypeDefinition.GetFields(f => f.Name == name, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault();
  967. }
  968. resolver = resolver.WithCurrentMember(member);
  969. if (resolverEnabled && resolver.CurrentTypeDefinition != null) {
  970. ResolveAndProcessConversion(enumMemberDeclaration.Initializer, resolver.CurrentTypeDefinition.EnumUnderlyingType);
  971. if (resolverEnabled && member != null)
  972. return new MemberResolveResult(null, member, false);
  973. else
  974. return errorResult;
  975. } else {
  976. Scan(enumMemberDeclaration.Initializer);
  977. return null;
  978. }
  979. } finally {
  980. resolver = oldResolver;
  981. }
  982. }
  983. #endregion
  984. #region Track CheckForOverflow
  985. ResolveResult IAstVisitor<ResolveResult>.VisitCheckedExpression(CheckedExpression checkedExpression)
  986. {
  987. CSharpResolver oldResolver = resolver;
  988. try {
  989. resolver = resolver.WithCheckForOverflow(true);
  990. if (resolverEnabled) {
  991. return Resolve(checkedExpression.Expression);
  992. } else {
  993. ScanChildren(checkedExpression);
  994. return null;
  995. }
  996. } finally {
  997. resolver = oldResolver;
  998. }
  999. }
  1000. ResolveResult IAstVisitor<ResolveResult>.VisitUncheckedExpression(UncheckedExpression uncheckedExpression)
  1001. {
  1002. CSharpResolver oldResolver = resolver;
  1003. try {
  1004. resolver = resolver.WithCheckForOverflow(false);
  1005. if (resolverEnabled) {
  1006. return Resolve(uncheckedExpression.Expression);
  1007. } else {
  1008. ScanChildren(uncheckedExpression);
  1009. return null;
  1010. }
  1011. } finally {
  1012. resolver = oldResolver;
  1013. }
  1014. }
  1015. ResolveResult IAstVisitor<ResolveResult>.VisitCheckedStatement(CheckedStatement checkedStatement)
  1016. {
  1017. CSharpResolver oldResolver = resolver;
  1018. try {
  1019. resolver = resolver.WithCheckForOverflow(true);
  1020. ScanChildren(checkedStatement);
  1021. return voidResult;
  1022. } finally {
  1023. resolver = oldResolver;
  1024. }
  1025. }
  1026. ResolveResult IAstVisitor<ResolveResult>.VisitUncheckedStatement(UncheckedStatement uncheckedStatement)
  1027. {
  1028. CSharpResolver oldResolver = resolver;
  1029. try {
  1030. resolver = resolver.WithCheckForOverflow(false);
  1031. ScanChildren(uncheckedStatement);
  1032. return voidResult;
  1033. } finally {
  1034. resolver = oldResolver;
  1035. }
  1036. }
  1037. #endregion
  1038. #region Visit AnonymousTypeCreateExpression
  1039. static string GetAnonymousTypePropertyName(Expression expr, out Expression resolveExpr)
  1040. {
  1041. if (expr is NamedExpression) {
  1042. var namedArgExpr = (NamedExpression)expr;
  1043. resolveExpr = namedArgExpr.Expression;
  1044. return namedArgExpr.Name;
  1045. }
  1046. // no name given, so it's a projection initializer
  1047. if (expr is MemberReferenceExpression) {
  1048. resolveExpr = expr;
  1049. return ((MemberReferenceExpression)expr).MemberName;
  1050. }
  1051. if (expr is IdentifierExpression) {
  1052. resolveExpr = expr;
  1053. return ((IdentifierExpression)expr).Identifier;
  1054. }
  1055. resolveExpr = null;
  1056. return null;
  1057. }
  1058. class AnonymousTypeMember
  1059. {
  1060. public readonly Expression Expression;
  1061. public readonly ResolveResult Initializer;
  1062. public AnonymousTypeMember(Expression expression, ResolveResult initializer)
  1063. {
  1064. this.Expression = expression;
  1065. this.Initializer = initializer;
  1066. }
  1067. }
  1068. ResolveResult IAstVisitor<ResolveResult>.VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression)
  1069. {
  1070. // 7.6.10.6 Anonymous object creation expressions
  1071. List<IUnresolvedProperty> unresolvedProperties = new List<IUnresolvedProperty>();
  1072. List<AnonymousTypeMember> members = new List<AnonymousTypeMember>();
  1073. foreach (var expr in anonymousTypeCreateExpression.Initializers) {
  1074. Expression resolveExpr;
  1075. var name = GetAnonymousTypePropertyName(expr, out resolveExpr);
  1076. if (resolveExpr != null) {
  1077. var initRR = Resolve(resolveExpr);
  1078. var returnTypeRef = initRR.Type.ToTypeReference();
  1079. var property = new DefaultUnresolvedProperty();
  1080. property.Name = name;
  1081. property.Accessibility = Accessibility.Public;
  1082. property.ReturnType = returnTypeRef;
  1083. property.Getter = new DefaultUnresolvedMethod {
  1084. Name = "get_" + name,
  1085. Accessibility = Accessibility.Public,
  1086. ReturnType = returnTypeRef,
  1087. SymbolKind = SymbolKind.Accessor,
  1088. AccessorOwner = property
  1089. };
  1090. unresolvedProperties.Add(property);
  1091. members.Add(new AnonymousTypeMember(expr, initRR));
  1092. } else {
  1093. Scan(expr);
  1094. }
  1095. }
  1096. var anonymousType = new AnonymousType(resolver.Compilation, unresolvedProperties);
  1097. var properties = anonymousType.GetProperties().ToList();
  1098. Debug.Assert(properties.Count == members.Count);
  1099. List<ResolveResult> assignments = new List<ResolveResult>();
  1100. for (int i = 0; i < members.Count; i++) {
  1101. ResolveResult lhs = new MemberResolveResult(new InitializedObjectResolveResult(anonymousType), properties[i]);
  1102. ResolveResult rhs = members[i].Initializer;
  1103. ResolveResult assignment = resolver.ResolveAssignment(AssignmentOperatorType.Assign, lhs, rhs);
  1104. var ne = members[i].Expression as NamedExpression;
  1105. if (ne != null) {
  1106. StoreCurrentState(ne);
  1107. // ne.Expression was already resolved by the first loop
  1108. StoreResult(ne, lhs);
  1109. }
  1110. assignments.Add(assignment);
  1111. }
  1112. var anonymousCtor = DefaultResolvedMethod.GetDummyConstructor(resolver.Compilation, anonymousType);
  1113. return new InvocationResolveResult(null, anonymousCtor, initializerStatements: assignments);
  1114. }
  1115. #endregion
  1116. #region Visit Expressions
  1117. ResolveResult IAstVisitor<ResolveResult>.VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression)
  1118. {
  1119. int dimensions = arrayCreateExpression.Arguments.Count;
  1120. IEnumerable<Expression> sizeArgumentExpressions;
  1121. ResolveResult[] sizeArguments;
  1122. IEnumerable<ArraySpecifier> additionalArraySpecifiers;
  1123. if (dimensions == 0) {
  1124. var firstSpecifier = arrayCreateExpression.AdditionalArraySpecifiers.FirstOrDefault();
  1125. if (firstSpecifier != null) {
  1126. dimensions = firstSpecifier.Dimensions;
  1127. additionalArraySpecifiers = arrayCreateExpression.AdditionalArraySpecifiers.Skip(1);
  1128. } else {
  1129. // No array specifiers (neither with nor without size) - can happen if there are syntax errors.
  1130. // Dimensions must be at least one; otherwise 'new ArrayType' will crash.
  1131. dimensions = 1;
  1132. additionalArraySpecifiers = arrayCreateExpression.AdditionalArraySpecifiers;
  1133. }
  1134. sizeArguments = null;
  1135. sizeArgumentExpressions = null;
  1136. } else {
  1137. sizeArgumentExpressions = arrayCreateExpression.Arguments;
  1138. sizeArguments = new ResolveResult[dimensions];
  1139. int pos = 0;
  1140. foreach (var node in sizeArgumentExpressions)
  1141. sizeArguments[pos++] = Resolve(node);
  1142. additionalArraySpecifiers = arrayCreateExpression.AdditionalArraySpecifiers;
  1143. }
  1144. int[] sizes;
  1145. List<Expression> initializerElements;
  1146. ResolveResult[] initializerElementResults;
  1147. if (arrayCreateExpression.Initializer.IsNull) {
  1148. sizes = null;
  1149. initializerElements = null;
  1150. initializerElementResults = null;
  1151. } else {
  1152. StoreCurrentState(arrayCreateExpression.Initializer);
  1153. initializerElements = new List<Expression>();
  1154. sizes = new int[dimensions];
  1155. UnpackArrayInitializer(initializerElements, sizes, arrayCreateExpression.Initializer, 0, true);
  1156. initializerElementResults = new ResolveResult[initializerElements.Count];
  1157. for (int i = 0; i < initializerElementResults.Length; i++) {
  1158. initializerElementResults[i] = Resolve(initializerElements[i]);
  1159. }
  1160. StoreResult(arrayCreateExpression.Initializer, voidResult);
  1161. }
  1162. IType elementType;
  1163. if (arrayCreateExpression.Type.IsNull) {
  1164. elementType = null;
  1165. } else {
  1166. elementType = ResolveType(arrayCreateExpression.Type);
  1167. foreach (var spec in additionalArraySpecifiers.Reverse()) {
  1168. elementType = new ArrayType(resolver.Compilation, elementType, spec.Dimensions);
  1169. }
  1170. }
  1171. ArrayCreateResolveResult acrr;
  1172. if (sizeArguments != null) {
  1173. acrr = resolver.ResolveArrayCreation(elementType, sizeArguments, initializerElementResults);
  1174. } else if (sizes != null) {
  1175. acrr = resolver.ResolveArrayCreation(elementType, sizes, initializerElementResults);
  1176. } else {
  1177. // neither size arguments nor an initializer exist -> error
  1178. return new ErrorResolveResult(new ArrayType(resolver.Compilation, elementType ?? SpecialType.UnknownType, dimensions));
  1179. }
  1180. if (sizeArgumentExpressions != null)
  1181. ProcessConversionResults(sizeArgumentExpressions, acrr.SizeArguments);
  1182. if (acrr.InitializerElements != null)
  1183. ProcessConversionResults(initializerElements, acrr.InitializerElements);
  1184. return acrr;
  1185. }
  1186. void UnpackArrayInitializer(List<Expression> elementList, int[] sizes, ArrayInitializerExpression initializer, int dimension, bool resolveNestedInitializersToVoid)
  1187. {
  1188. Debug.Assert(dimension < sizes.Length);
  1189. int elementCount = 0;
  1190. if (dimension + 1 < sizes.Length) {
  1191. foreach (var node in initializer.Elements) {
  1192. ArrayInitializerExpression aie = node as ArrayInitializerExpression;
  1193. if (aie != null) {
  1194. if (resolveNestedInitializersToVoid) {
  1195. StoreCurrentState(aie);
  1196. StoreResult(aie, voidResult);
  1197. }
  1198. UnpackArrayInitializer(elementList, sizes, aie, dimension + 1, resolveNestedInitializersToVoid);
  1199. } else {
  1200. elementList.Add(node);
  1201. }
  1202. elementCount++;
  1203. }
  1204. } else {
  1205. foreach (var expr in initializer.Elements) {
  1206. elementList.Add(expr);
  1207. elementCount++;
  1208. }
  1209. }
  1210. if (sizes[dimension] == 0) // 0 = uninitialized
  1211. sizes[dimension] = elementCount;
  1212. else if (sizes[dimension] != elementCount)
  1213. sizes[dimension] = -1; // -1 = error
  1214. }
  1215. ResolveResult IAstVisitor<ResolveResult>.VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression)
  1216. {
  1217. // Array initializers are handled by their parent expression.
  1218. ScanChildren(arrayInitializerExpression);
  1219. return errorResult;
  1220. }
  1221. ResolveResult IAstVisitor<ResolveResult>.VisitAsExpression(AsExpression asExpression)
  1222. {
  1223. if (resolverEnabled) {
  1224. ResolveResult input = Resolve(asExpression.Exp