private static SymbolDeclaration GetNodeDeclaration(ParseTree.Node node, string fileName = null) { if (node.declaration == null) { var declarationSemantics = node.semantics & SemanticFlags.SymbolDeclarationsMask; var enclosingScopeNode = EnclosingSemanticNode(node.parent, SemanticFlags.ScopesMask); var enclosingScope = GetNodeScope(enclosingScopeNode, fileName); if (enclosingScope == null) return null; ParseTree.BaseNode modifiersNode = null; ParseTree.BaseNode partialNode = null; ParseTree.Node typeParamsNode = null; switch (declarationSemantics) { case SemanticFlags.NamespaceDeclaration: node.declaration = new NamespaceDeclaration { parseTreeNode = node, kind = SymbolKind.Namespace }; break; case SemanticFlags.UsingNamespace: node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.ImportedNamespace }; break; //var namespaceToImport = node.Print(); //(enclosingScope as NamespaceScope).declaration.importedNamespaces[namespaceToImport] = new SymbolReference(node.ChildAt(0)); //return null; case SemanticFlags.UsingAlias: node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.TypeAlias }; break; //var name = node.ChildAt(0).Print(); //((NamespaceScope) enclosingScope).declaration.typeAliases[name] = new SymbolReference(node.ChildAt(2)); //return null; case SemanticFlags.ExternAlias: break; case SemanticFlags.ClassDeclaration: modifiersNode = node.parent.FindChildByName("modifiers"); partialNode = node.parent.FindChildByName("PARTIAL"); node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Class }; typeParamsNode = node.FindChildByName("typeParameterList") as ParseTree.Node; // Debug.Log(node.declaration + " mods: " + node.declaration.modifiers); break; case SemanticFlags.TypeParameterDeclaration: node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.TypeParameter }; break; case SemanticFlags.BaseListDeclaration: node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.BaseTypesList }; break; case SemanticFlags.ConstantDeclarator: modifiersNode = node.parent.parent.parent.FindChildByName("modifiers"); node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = node.parent.parent.RuleName == "constantDeclaration" ? SymbolKind.ConstantField : SymbolKind.LocalConstant }; break; case SemanticFlags.ConstructorDeclarator: modifiersNode = node.parent.FindChildByName("modifiers"); node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Constructor }; break; case SemanticFlags.DestructorDeclarator: node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Destructor }; break; case SemanticFlags.OperatorDeclarator: case SemanticFlags.ConversionOperatorDeclarator: modifiersNode = node.parent.parent.FindChildByName("modifiers"); node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Operator }; break; case SemanticFlags.MethodDeclarator: modifiersNode = node.parent.FindChildByName("modifiers"); typeParamsNode = node.NodeAt(0); if (typeParamsNode != null) typeParamsNode = typeParamsNode.NodeAt(0); if (typeParamsNode != null) typeParamsNode = typeParamsNode.NodeAt(0); if (typeParamsNode != null) typeParamsNode = typeParamsNode.NodeAt(-1); if (typeParamsNode != null) typeParamsNode = typeParamsNode.FindChildByName("typeParameterList") as ParseTree.Node; node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Method }; break; case SemanticFlags.LocalVariableDeclarator: node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Variable }; break; case SemanticFlags.ForEachVariableDeclaration: node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.ForEachVariable }; break; case SemanticFlags.FromClauseVariableDeclaration: node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.FromClauseVariable }; break; case SemanticFlags.LabeledStatement: node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Label }; break; case SemanticFlags.CatchExceptionParameterDeclaration: node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.CatchParameter }; break; case SemanticFlags.FixedParameterDeclaration: modifiersNode = node.FindChildByName("parameterModifier"); node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Parameter }; // Debug.Log("Adding parameter declaration to " + enclosingScope); break; case SemanticFlags.ParameterArrayDeclaration: node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Parameter, modifiers = Modifiers.Params }; break; case SemanticFlags.ImplicitParameterDeclaration: node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Parameter }; break; case SemanticFlags.ExplicitParameterDeclaration: modifiersNode = node.FindChildByName("anonymousFunctionParameterModifier"); node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Parameter }; break; case SemanticFlags.PropertyDeclaration: modifiersNode = node.parent.FindChildByName("modifiers"); node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Property }; break; case SemanticFlags.IndexerDeclaration: modifiersNode = node.parent.FindChildByName("modifiers"); node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Indexer }; break; case SemanticFlags.GetAccessorDeclaration: case SemanticFlags.SetAccessorDeclaration: modifiersNode = node.parent.FindChildByName("accessorModifiers"); node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Accessor }; break; case SemanticFlags.InterfaceGetAccessorDeclaration: case SemanticFlags.InterfaceSetAccessorDeclaration: case SemanticFlags.AddAccessorDeclaration: case SemanticFlags.RemoveAccessorDeclaration: node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Accessor }; break; case SemanticFlags.EventDeclarator: modifiersNode = node.parent.parent.parent.FindChildByName("modifiers"); node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Event }; break; case SemanticFlags.EventWithAccessorsDeclaration: modifiersNode = node.parent.parent.FindChildByName("modifiers"); node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Event }; break; case SemanticFlags.VariableDeclarator: modifiersNode = node.parent.parent.parent.FindChildByName("modifiers"); node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Field }; break; case SemanticFlags.StructDeclaration: modifiersNode = node.parent.FindChildByName("modifiers"); partialNode = node.parent.FindChildByName("PARTIAL"); node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Struct }; break; case SemanticFlags.InterfaceDeclaration: modifiersNode = node.parent.FindChildByName("modifiers"); partialNode = node.parent.FindChildByName("PARTIAL"); node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Interface }; break; case SemanticFlags.InterfaceIndexerDeclaration: modifiersNode = node.parent.FindChildByName("modifiers"); node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Property }; break; case SemanticFlags.InterfacePropertyDeclaration: modifiersNode = node.parent.FindChildByName("modifiers"); node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Property }; break; case SemanticFlags.InterfaceMethodDeclaration: modifiersNode = node.parent.FindChildByName("modifiers"); node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Method }; break; case SemanticFlags.InterfaceEventDeclaration: break; case SemanticFlags.EnumDeclaration: modifiersNode = node.parent.FindChildByName("modifiers"); node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Enum }; break; case SemanticFlags.EnumMemberDeclaration: node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.EnumMember, modifiers = Modifiers.ReadOnly | Modifiers.Public | Modifiers.Static }; break; case SemanticFlags.DelegateDeclaration: modifiersNode = node.parent.FindChildByName("modifiers"); typeParamsNode = node.FindChildByName("typeParameterList") as ParseTree.Node; node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.Delegate }; break; case SemanticFlags.AnonymousObjectCreation: break; case SemanticFlags.MemberDeclarator: break; case SemanticFlags.LambdaExpressionDeclaration: case SemanticFlags.AnonymousMethodDeclaration: enclosingScopeNode = EnclosingScopeNode(node.parent, SemanticFlags.CodeBlockScope, SemanticFlags.MethodBodyScope, SemanticFlags.TypeDeclarationScope); enclosingScope = GetNodeScope(enclosingScopeNode, fileName); node.declaration = new SymbolDeclaration { parseTreeNode = node, kind = SymbolKind.LambdaExpression }; break; case SemanticFlags.None: Debug.LogWarning("declarationSemantics is None on " + node); break; default: throw new ArgumentOutOfRangeException("Unhandled case " + declarationSemantics + " for node " + node); } if (node.declaration != null) { if (modifiersNode != null) node.declaration.modifiers = ParseModifiers(modifiersNode); if (partialNode != null) node.declaration.modifiers |= Modifiers.Partial; if (typeParamsNode != null) node.declaration.numTypeParameters = CountTypeParameters(typeParamsNode); if (enclosingScope == null) Debug.LogWarning("Symbol declaration " + declarationSemantics + " outside of declaration space!\nenclosingScopeNode: " + (enclosingScopeNode != null ? enclosingScopeNode.RuleName : "null") + "\nnode: " + node); else { var saved = SymbolReference.dontResolveNow; SymbolReference.dontResolveNow = true; try { //var symbol = enclosingScope.AddDeclaration(node.declaration); //if (symbol != null) // Debug.Log("Added declaration " + symbol.ReflectionName); //else // Debug.Log("Adding declaration for " + node.declaration.Name + " failed!"); } catch (Exception e) { Debug.LogException(e); } finally { SymbolReference.dontResolveNow = saved; } ++ParseTree.resolverVersion; if (ParseTree.resolverVersion == 0) ++ParseTree.resolverVersion; } } } return node.declaration; }