public ICollection <TypeSymbol> BuildMetadata(ParseNodeList compilationUnits, SymbolSet symbols, CompilerOptions options) { Debug.Assert(compilationUnits != null); Debug.Assert(symbols != null); _symbols = symbols; _symbolTable = symbols; _options = options; string scriptName = GetAssemblyScriptName(compilationUnits); if (String.IsNullOrEmpty(scriptName)) { _errorHandler.ReportError("You must declare a ScriptAssembly attribute.", String.Empty); } else if (Utility.IsValidScriptName(scriptName) == false) { string errorMessage = "The ScriptAssembly attribute referenced an invalid name '{0}'. Script names must only contain letters, numbers, dots or underscores."; _errorHandler.ReportError(String.Format(errorMessage, scriptName), String.Empty); } symbols.ScriptName = scriptName; string scriptPrefix = GetAssemblyScriptPrefix(compilationUnits); if (String.IsNullOrEmpty(scriptPrefix) == false) { if (Utility.IsValidIdentifier(scriptPrefix) == false) { string errorMessage = "The ScriptQualifier attribute referenced an invalid prefix '{0}'. Script prefix must be valid identifiers."; _errorHandler.ReportError(String.Format(errorMessage, scriptPrefix), String.Empty); } } else { scriptPrefix = scriptName.Replace(".", String.Empty); } symbols.ScriptPrefix = scriptPrefix; string assemblyScriptNamespace = GetAssemblyScriptNamespace(compilationUnits); List <TypeSymbol> types = new List <TypeSymbol>(); // Build all the types first. // Types need to be loaded upfront so that they can be used in resolving types associated // with members. foreach (CompilationUnitNode compilationUnit in compilationUnits) { foreach (NamespaceNode namespaceNode in compilationUnit.Members) { string namespaceName = namespaceNode.Name; NamespaceSymbol namespaceSymbol = symbols.GetNamespace(namespaceName); List <string> imports = null; Dictionary <string, string> aliases = null; ParseNodeList usingClauses = namespaceNode.UsingClauses; if ((usingClauses != null) && (usingClauses.Count != 0)) { foreach (ParseNode usingNode in namespaceNode.UsingClauses) { if (usingNode is UsingNamespaceNode) { if (imports == null) { imports = new List <string>(usingClauses.Count); } string referencedNamespace = ((UsingNamespaceNode)usingNode).ReferencedNamespace; if (imports.Contains(referencedNamespace) == false) { imports.Add(referencedNamespace); } } else { Debug.Assert(usingNode is UsingAliasNode); if (aliases == null) { aliases = new Dictionary <string, string>(); } UsingAliasNode aliasNode = (UsingAliasNode)usingNode; aliases[aliasNode.Alias] = aliasNode.TypeName; } } } // Add parent namespaces as imports in reverse order since they // are searched in that fashion. string[] namespaceParts = namespaceName.Split('.'); for (int i = namespaceParts.Length - 2; i >= 0; i--) { string partialNamespace; if (i == 0) { partialNamespace = namespaceParts[0]; } else { partialNamespace = String.Join(".", namespaceParts, 0, i + 1); } if (imports == null) { imports = new List <string>(); } if (imports.Contains(partialNamespace) == false) { imports.Add(partialNamespace); } } // Build type symbols for all user-defined types foreach (TypeNode typeNode in namespaceNode.Members) { UserTypeNode userTypeNode = typeNode as UserTypeNode; if (userTypeNode == null) { continue; } // Check if we have overriding script namespace for this type. string typeScriptNamespace = GetScriptNamespace(userTypeNode.Attributes); if (String.IsNullOrEmpty(typeScriptNamespace)) { typeScriptNamespace = assemblyScriptNamespace; } ClassSymbol partialTypeSymbol = null; bool isPartial = false; if ((userTypeNode.Modifiers & Modifiers.Partial) != 0) { partialTypeSymbol = (ClassSymbol)((ISymbolTable)namespaceSymbol).FindSymbol(userTypeNode.Name, /* context */ null, SymbolFilter.Types); if ((partialTypeSymbol != null) && partialTypeSymbol.IsApplicationType) { // This class will be considered as a partial class isPartial = true; // Merge code model information for the partial class onto the code model node // for the primary partial class. Interesting bits of information include things // such as base class etc. that is yet to be processed. CustomTypeNode partialTypeNode = (CustomTypeNode)partialTypeSymbol.ParseContext; partialTypeNode.MergePartialType((CustomTypeNode)userTypeNode); // Merge interesting bits of information onto the primary type symbol as well // representing this partial class BuildType(partialTypeSymbol, userTypeNode); if (String.IsNullOrEmpty(typeScriptNamespace) == false) { partialTypeSymbol.ScriptNamespace = typeScriptNamespace; } } } TypeSymbol typeSymbol = BuildType(userTypeNode, namespaceSymbol); if (typeSymbol != null) { typeSymbol.SetParseContext(userTypeNode); typeSymbol.SetParentSymbolTable(symbols); if (imports != null) { typeSymbol.SetImports(imports); } if (aliases != null) { typeSymbol.SetAliases(aliases); } if (String.IsNullOrEmpty(typeScriptNamespace) == false) { typeSymbol.ScriptNamespace = typeScriptNamespace; } if (isPartial == false) { namespaceSymbol.AddType(typeSymbol); } else { // Partial types don't get added to the namespace, so we don't have // duplicated named items. However, they still do get instantiated // and processed as usual. // // The members within partial classes refer to the partial type as their parent, // and hence derive context such as the list of imports scoped to the // particular type. // However, the members will get added to the primary partial type's list of // members so they can be found. // Effectively the partial class here gets created just to hold // context of type-symbol level bits of information such as the list of // imports, that are consumed when generating code for the members defined // within a specific partial class. ((ClassSymbol)typeSymbol).SetPrimaryPartialClass(partialTypeSymbol); } types.Add(typeSymbol); } } } } // Build inheritance chains foreach (TypeSymbol typeSymbol in types) { if (typeSymbol.Type == SymbolType.Class) { BuildTypeInheritance((ClassSymbol)typeSymbol); } } // Import members foreach (TypeSymbol typeSymbol in types) { BuildMembers(typeSymbol); } // Associate interface members with interface member symbols foreach (TypeSymbol typeSymbol in types) { if (typeSymbol.Type == SymbolType.Class) { BuildInterfaceAssociations((ClassSymbol)typeSymbol); } } // Load resource values if (_symbols.HasResources) { foreach (TypeSymbol typeSymbol in types) { if (typeSymbol.Type == SymbolType.Resources) { BuildResources((ResourcesSymbol)typeSymbol); } } } // Load documentation if (_options.EnableDocComments) { Stream docCommentsStream = options.DocCommentFile.GetStream(); if (docCommentsStream != null) { try { XmlDocument docComments = new XmlDocument(); docComments.Load(docCommentsStream); symbols.SetComments(docComments); } finally { options.DocCommentFile.CloseStream(docCommentsStream); } } } return(types); }
private void BuildMembers(TypeSymbol typeSymbol) { if (typeSymbol.Type == SymbolType.Delegate) { DelegateTypeNode delegateNode = (DelegateTypeNode)typeSymbol.ParseContext; TypeSymbol returnType = typeSymbol.SymbolSet.ResolveType(delegateNode.ReturnType, _symbolTable, typeSymbol); Debug.Assert(returnType != null); if (returnType != null) { MethodSymbol invokeMethod = new MethodSymbol("Invoke", typeSymbol, returnType, MemberVisibility.Public); invokeMethod.SetTransformedName(String.Empty); // Mark the method as abstract, as there is no actual implementation of the method // to be generated invokeMethod.SetImplementationState(SymbolImplementationFlags.Abstract); typeSymbol.AddMember(invokeMethod); } return; } CustomTypeNode typeNode = (CustomTypeNode)typeSymbol.ParseContext; foreach (MemberNode member in typeNode.Members) { MemberSymbol memberSymbol = null; switch (member.NodeType) { case ParseNodeType.FieldDeclaration: case ParseNodeType.ConstFieldDeclaration: memberSymbol = BuildField((FieldDeclarationNode)member, typeSymbol); break; case ParseNodeType.PropertyDeclaration: memberSymbol = BuildPropertyAsField((PropertyDeclarationNode)member, typeSymbol); if (memberSymbol == null) { memberSymbol = BuildProperty((PropertyDeclarationNode)member, typeSymbol); } break; case ParseNodeType.IndexerDeclaration: memberSymbol = BuildIndexer((IndexerDeclarationNode)member, typeSymbol); break; case ParseNodeType.ConstructorDeclaration: case ParseNodeType.MethodDeclaration: if ((member.Modifiers & Modifiers.Extern) != 0) { // Extern methods are there for defining overload signatures, so // we just skip them as far as metadata goes. The validator has // taken care of the requirements/constraints around use of extern methods. continue; } memberSymbol = BuildMethod((MethodDeclarationNode)member, typeSymbol); break; case ParseNodeType.EventDeclaration: memberSymbol = BuildEvent((EventDeclarationNode)member, typeSymbol); break; case ParseNodeType.EnumerationFieldDeclaration: memberSymbol = BuildEnumField((EnumerationFieldNode)member, typeSymbol); break; } if (memberSymbol != null) { memberSymbol.SetParseContext(member); if ((typeSymbol.IsApplicationType == false) && ((memberSymbol.Type == SymbolType.Constructor) || (typeSymbol.GetMember(memberSymbol.Name) != null))) { // If the type is an imported type, then it is allowed to contain // overloads, and we're simply going to ignore its existence, as long // as one overload has been added to the member table. continue; } typeSymbol.AddMember(memberSymbol); if ((typeSymbol.Type == SymbolType.Class) && (memberSymbol.Type == SymbolType.Event)) { EventSymbol eventSymbol = (EventSymbol)memberSymbol; if (eventSymbol.DefaultImplementation) { // Add a private field that will serve as the backing member // later on in the conversion (eg. in non-event expressions) MemberVisibility visibility = MemberVisibility.PrivateInstance; if ((eventSymbol.Visibility & MemberVisibility.Static) != 0) { visibility |= MemberVisibility.Static; } FieldSymbol fieldSymbol = new FieldSymbol("__" + Utility.CreateCamelCaseName(eventSymbol.Name), typeSymbol, eventSymbol.AssociatedType); fieldSymbol.SetVisibility(visibility); fieldSymbol.SetParseContext(((EventDeclarationNode)eventSymbol.ParseContext).Field); typeSymbol.AddMember(fieldSymbol); } } } } }
bool IParseNodeValidator.Validate(ParseNode node, CompilerOptions options, IErrorHandler errorHandler) { CustomTypeNode typeNode = (CustomTypeNode)node; bool recordRestrictions = false; bool hasCodeMembers = false; ParseNode codeMemberNode = null; AttributeNode importedTypeAttribute = AttributeNode.FindAttribute(typeNode.Attributes, DSharpStringResources.SCRIPT_IMPORT_ATTRIBUTE); if (importedTypeAttribute != null) { // This is an imported type definition... we'll assume its valid, since // the set of restrictions for such types is fewer, and different, so // for now that translates into skipping the members. return(false); } if ((typeNode.Modifiers & Modifiers.New) != 0) { errorHandler.ReportNodeValidationError(DSharpStringResources.NEW_KEYWORD_ON_TYPE_UNSUPPORTED, typeNode); return(false); } if ((typeNode.Modifiers & (Modifiers.Private | Modifiers.Protected)) != 0) { errorHandler.ReportNodeValidationError(DSharpStringResources.ACCESS_MODIFIER_ON_TYPE_UNSUPPORTED, typeNode); return(false); } if ((typeNode.Modifiers & Modifiers.Partial) != 0 && typeNode.Type != TokenType.Class) { errorHandler.ReportNodeValidationError(DSharpStringResources.UNSUPPORTED_PARTIAL_TYPE, typeNode); return(false); } if (typeNode.Type == TokenType.Class) { AttributeNode objectAttribute = AttributeNode.FindAttribute(typeNode.Attributes, DSharpStringResources.SCRIPT_OBJECT_ATTRIBUTE); if (objectAttribute != null) { if ((typeNode.Modifiers & Modifiers.Sealed) == 0) { errorHandler.ReportNodeValidationError(DSharpStringResources.SCRIPT_OBJECT_ATTRIBUTE_ERROR, typeNode); } if (typeNode.BaseTypes.Count != 0) { errorHandler.ReportNodeValidationError(DSharpStringResources.SCRIPT_OBJECT_CLASS_INHERITENCE_ERROR, typeNode); } recordRestrictions = true; } } if (typeNode.Members != null && typeNode.Members.Count != 0) { Dictionary <string, object> memberNames = new Dictionary <string, object>(); bool hasCtor = false; foreach (ParseNode genericMemberNode in typeNode.Members) { if (!(genericMemberNode is MemberNode)) { continue; } MemberNode memberNode = (MemberNode)genericMemberNode; if ((memberNode.Modifiers & Modifiers.Extern) != 0) { // Extern methods are placeholders for creating overload signatures continue; } if (recordRestrictions && ((memberNode.Modifiers & Modifiers.Static) != 0 || memberNode.NodeType != ParseNodeType.ConstructorDeclaration && memberNode.NodeType != ParseNodeType.FieldDeclaration)) { errorHandler.ReportNodeValidationError(DSharpStringResources.SCRIPT_OBJECT_MEMBER_VIOLATION_ERROR, memberNode); } if (memberNode.NodeType == ParseNodeType.ConstructorDeclaration) { if ((memberNode.Modifiers & Modifiers.Static) == 0) { if (hasCtor) { errorHandler.ReportNodeValidationError(DSharpStringResources.UNSUPPORTED_CONSTRUCTOR_OVERLOAD, memberNode); } hasCtor = true; } continue; } if (memberNode is MethodDeclarationNode methodDeclaration) { if (methodDeclaration.IsExensionMethod && (!methodDeclaration.Modifiers.HasFlag(Modifiers.Static) || !typeNode.Modifiers.HasFlag(Modifiers.Static))) { errorHandler.ReportNodeValidationError(DSharpStringResources.EXTENSION_TYPE_AND_METHOD_SHOULD_BE_STATIC, methodDeclaration); } } if (memberNode.NodeType == ParseNodeType.OperatorDeclaration) { // Operators don't have a name continue; } string name = memberNode.Name; AttributeNode ignoreAttribute = AttributeNode.FindAttribute(memberNode.Attributes, DSharpStringResources.SCRIPT_IGNORE_ATTRIBUTE); if (ignoreAttribute == null && memberNames.ContainsKey(name) && typeNode.Type != TokenType.Interface) { errorHandler.ReportNodeValidationError(DSharpStringResources.UNSUPPORTED_METHOD_OVERLOAD, memberNode); } // remember the method overload only if it wasn't ignored if (ignoreAttribute == null) { memberNames[name] = null; } string nameToValidate = name; bool preserveCase = false; AttributeNode nameAttribute = AttributeNode.FindAttribute(memberNode.Attributes, DSharpStringResources.SCRIPT_NAME_ATTRIBUTE); if (nameAttribute != null && nameAttribute.Arguments.Count != 0) { foreach (ParseNode argNode in nameAttribute.Arguments) { if (argNode.NodeType == ParseNodeType.Literal) { nameToValidate = (string)((LiteralNode)argNode).Value; } else if (argNode.NodeType == ParseNodeType.BinaryExpression) { if (string.CompareOrdinal(((NameNode)((BinaryExpressionNode)argNode).LeftChild).Name, "PreserveCase") == 0) { preserveCase = (bool)((LiteralNode)((BinaryExpressionNode)argNode).RightChild) .Value; } } } } if (Utility.IsKeyword(nameToValidate, /* testCamelCase */ preserveCase == false)) { errorHandler.ReportNodeValidationError(DSharpStringResources.RESERVED_KEYWORD_ON_MEMBER_ERROR, memberNode); } if (hasCodeMembers == false) { hasCodeMembers = memberNode.NodeType == ParseNodeType.PropertyDeclaration || memberNode.NodeType == ParseNodeType.MethodDeclaration || memberNode.NodeType == ParseNodeType.EventDeclaration || memberNode.NodeType == ParseNodeType.IndexerDeclaration; codeMemberNode = memberNode; } } } return(true); }
bool IParseNodeValidator.Validate(ParseNode node, CompilerOptions options, IErrorHandler errorHandler) { MethodDeclarationNode methodNode = (MethodDeclarationNode)node; if (((methodNode.Modifiers & Modifiers.Static) == 0) && ((methodNode.Modifiers & Modifiers.New) != 0)) { errorHandler.ReportError("The new modifier is not supported on instance members.", methodNode.Token.Location); return(false); } if ((methodNode.Modifiers & Modifiers.Extern) != 0) { AttributeNode altSigAttribute = AttributeNode.FindAttribute(methodNode.Attributes, "AlternateSignature"); if (altSigAttribute == null) { errorHandler.ReportError("Extern methods should only be used to declare alternate signatures and marked with [AlternateSignature].", methodNode.Token.Location); return(false); } CustomTypeNode typeNode = (CustomTypeNode)methodNode.Parent; MethodDeclarationNode implMethodNode = null; if (methodNode.NodeType == ParseNodeType.MethodDeclaration) { foreach (MemberNode memberNode in typeNode.Members) { if ((memberNode.NodeType == ParseNodeType.MethodDeclaration) && ((memberNode.Modifiers & Modifiers.Extern) == 0) && memberNode.Name.Equals(methodNode.Name, StringComparison.Ordinal)) { implMethodNode = (MethodDeclarationNode)memberNode; break; } } } else if (methodNode.NodeType == ParseNodeType.ConstructorDeclaration) { foreach (MemberNode memberNode in typeNode.Members) { if ((memberNode.NodeType == ParseNodeType.ConstructorDeclaration) && ((memberNode.Modifiers & Modifiers.Extern) == 0)) { implMethodNode = (MethodDeclarationNode)memberNode; break; } } } if (implMethodNode == null) { errorHandler.ReportError("Extern methods used to declare alternate signatures should have a corresponding non-extern implementation as well.", methodNode.Token.Location); return(false); } if ((methodNode.Modifiers & (Modifiers.Static | Modifiers.AccessMask)) != (implMethodNode.Modifiers & (Modifiers.Static | Modifiers.AccessMask))) { errorHandler.ReportError("The implemenation method and associated alternate signature methods should have the same access type.", methodNode.Token.Location); } } return(true); }
bool IParseNodeValidator.Validate(ParseNode node, CompilerOptions options, IErrorHandler errorHandler) { CustomTypeNode typeNode = (CustomTypeNode)node; bool extensionRestrictions = false; bool moduleRestrictions = false; bool recordRestrictions = false; bool hasCodeMembers = false; ParseNode codeMemberNode = null; AttributeNode importedTypeAttribute = AttributeNode.FindAttribute(typeNode.Attributes, "ScriptImport"); if (importedTypeAttribute != null) { // This is an imported type definition... we'll assume its valid, since // the set of restrictions for such types is fewer, and different, so // for now that translates into skipping the members. return(false); } if (((typeNode.Modifiers & Modifiers.Partial) != 0) && (typeNode.Type != TokenType.Class)) { errorHandler.ReportError("Partial types can only be classes, not enumerations or interfaces.", typeNode.Token.Location); return(false); } if (typeNode.Type == TokenType.Class) { if (typeNode.BaseTypes.Count != 0) { NameNode baseTypeNameNode = typeNode.BaseTypes[0] as NameNode; if (baseTypeNameNode != null) { if (String.CompareOrdinal(baseTypeNameNode.Name, "TestClass") == 0) { if ((typeNode.Modifiers & Modifiers.Internal) == 0) { errorHandler.ReportError("Classes derived from TestClass must be marked as internal.", typeNode.Token.Location); } if ((typeNode.Modifiers & Modifiers.Static) != 0) { errorHandler.ReportError("Classes derived from TestClass must not be marked as static.", typeNode.Token.Location); } if ((typeNode.Modifiers & Modifiers.Sealed) == 0) { errorHandler.ReportError("Classes derived from TestClass must be marked as sealed.", typeNode.Token.Location); } if (typeNode.BaseTypes.Count != 1) { errorHandler.ReportError("Classes derived from TestClass cannot implement interfaces.", typeNode.Token.Location); } } } } AttributeNode objectAttribute = AttributeNode.FindAttribute(typeNode.Attributes, "ScriptObject"); if (objectAttribute != null) { if ((typeNode.Modifiers & Modifiers.Sealed) == 0) { errorHandler.ReportError("ScriptObject attribute can only be set on sealed classes.", typeNode.Token.Location); } if (typeNode.BaseTypes.Count != 0) { errorHandler.ReportError("Classes marked with ScriptObject must not derive from another class or implement interfaces.", typeNode.Token.Location); } recordRestrictions = true; } AttributeNode extensionAttribute = AttributeNode.FindAttribute(typeNode.Attributes, "ScriptExtension"); if (extensionAttribute != null) { extensionRestrictions = true; if ((typeNode.Modifiers & Modifiers.Static) == 0) { errorHandler.ReportError("ScriptExtension attribute can only be set on static classes.", typeNode.Token.Location); } if ((extensionAttribute.Arguments.Count != 1) || !(extensionAttribute.Arguments[0] is LiteralNode) || !(((LiteralNode)extensionAttribute.Arguments[0]).Value is string) || String.IsNullOrEmpty((string)((LiteralNode)extensionAttribute.Arguments[0]).Value)) { errorHandler.ReportError("ScriptExtension attribute declaration must specify the object being extended.", typeNode.Token.Location); } } AttributeNode moduleAttribute = AttributeNode.FindAttribute(typeNode.Attributes, "ScriptModule"); if (moduleAttribute != null) { moduleRestrictions = true; if (((typeNode.Modifiers & Modifiers.Static) == 0) || ((typeNode.Modifiers & Modifiers.Internal) == 0)) { errorHandler.ReportError("ScriptModule attribute can only be set on internal static classes.", typeNode.Token.Location); } } } if ((typeNode.Members != null) && (typeNode.Members.Count != 0)) { Dictionary <string, object> memberNames = new Dictionary <string, object>(); bool hasCtor = false; foreach (ParseNode genericMemberNode in typeNode.Members) { if (!(genericMemberNode is MemberNode)) { errorHandler.ReportError("Only members are allowed inside types. Nested types are not supported.", node.Token.Location); continue; } MemberNode memberNode = (MemberNode)genericMemberNode; if ((memberNode.Modifiers & Modifiers.Extern) != 0) { // Extern methods are placeholders for creating overload signatures continue; } if (extensionRestrictions && (memberNode.NodeType != ParseNodeType.MethodDeclaration)) { errorHandler.ReportError("Classes marked with ScriptExtension attribute should only have methods.", memberNode.Token.Location); } if (moduleRestrictions && (memberNode.NodeType != ParseNodeType.ConstructorDeclaration)) { errorHandler.ReportError("Classes marked with ScriptModule attribute should only have a static constructor.", memberNode.Token.Location); } if (recordRestrictions && (((memberNode.Modifiers & Modifiers.Static) != 0) || ((memberNode.NodeType != ParseNodeType.ConstructorDeclaration) && (memberNode.NodeType != ParseNodeType.FieldDeclaration)))) { errorHandler.ReportError("Classes marked with ScriptObject attribute should only have a constructor and field members.", memberNode.Token.Location); } if (memberNode.NodeType == ParseNodeType.ConstructorDeclaration) { if ((memberNode.Modifiers & Modifiers.Static) == 0) { if (hasCtor) { errorHandler.ReportError("Constructor overloads are not supported.", memberNode.Token.Location); } hasCtor = true; } continue; } if (memberNode.NodeType == ParseNodeType.OperatorDeclaration) { // Operators don't have a name continue; } string name = memberNode.Name; if (memberNames.ContainsKey(name)) { errorHandler.ReportError("Duplicate-named member. Method overloads are not supported.", memberNode.Token.Location); } memberNames[name] = null; string nameToValidate = name; bool preserveCase = false; AttributeNode nameAttribute = AttributeNode.FindAttribute(memberNode.Attributes, "ScriptName"); if ((nameAttribute != null) && (nameAttribute.Arguments.Count != 0)) { foreach (ParseNode argNode in nameAttribute.Arguments) { if (argNode.NodeType == ParseNodeType.Literal) { nameToValidate = (string)((LiteralNode)argNode).Value; } else if (argNode.NodeType == ParseNodeType.BinaryExpression) { if (String.CompareOrdinal(((NameNode)((BinaryExpressionNode)argNode).LeftChild).Name, "PreserveCase") == 0) { preserveCase = (bool)((LiteralNode)((BinaryExpressionNode)argNode).RightChild).Value; } } } } if (Utility.IsKeyword(nameToValidate, /* testCamelCase */ (preserveCase == false))) { errorHandler.ReportError("Invalid member name. Member names should not use keywords.", memberNode.Token.Location); } if (hasCodeMembers == false) { hasCodeMembers = ((memberNode.NodeType == ParseNodeType.PropertyDeclaration) || (memberNode.NodeType == ParseNodeType.MethodDeclaration) || (memberNode.NodeType == ParseNodeType.EventDeclaration) || (memberNode.NodeType == ParseNodeType.IndexerDeclaration)); codeMemberNode = memberNode; } } } return(true); }
private TypeSymbol BuildType(UserTypeNode typeNode, NamespaceSymbol namespaceSymbol) { Debug.Assert(typeNode != null); Debug.Assert(namespaceSymbol != null); TypeSymbol typeSymbol = null; ParseNodeList attributes = typeNode.Attributes; if (typeNode.Type == TokenType.Class) { CustomTypeNode customTypeNode = (CustomTypeNode)typeNode; Debug.Assert(customTypeNode != null); NameNode baseTypeNameNode = null; if (customTypeNode.BaseTypes.Count != 0) { baseTypeNameNode = customTypeNode.BaseTypes[0] as NameNode; } if ((baseTypeNameNode != null) && (String.CompareOrdinal(baseTypeNameNode.Name, "Record") == 0)) { typeSymbol = new RecordSymbol(typeNode.Name, namespaceSymbol); } else { AttributeNode resourcesAttribute = AttributeNode.FindAttribute(attributes, "Resources"); if (resourcesAttribute != null) { typeSymbol = new ResourcesSymbol(typeNode.Name, namespaceSymbol); } else { typeSymbol = new ClassSymbol(typeNode.Name, namespaceSymbol); if ((baseTypeNameNode != null) && (String.CompareOrdinal(baseTypeNameNode.Name, "TestClass") == 0)) { ((ClassSymbol)typeSymbol).SetTestClass(); } } } } else if (typeNode.Type == TokenType.Interface) { typeSymbol = new InterfaceSymbol(typeNode.Name, namespaceSymbol); } else if (typeNode.Type == TokenType.Enum) { bool flags = false; AttributeNode flagsAttribute = AttributeNode.FindAttribute(typeNode.Attributes, "Flags"); if (flagsAttribute != null) { flags = true; } typeSymbol = new EnumerationSymbol(typeNode.Name, namespaceSymbol, flags); } else if (typeNode.Type == TokenType.Delegate) { typeSymbol = new DelegateSymbol(typeNode.Name, namespaceSymbol); typeSymbol.SetTransformedName("Function"); typeSymbol.SetIgnoreNamespace(); } Debug.Assert(typeSymbol != null, "Unexpected type node " + typeNode.Type); if (typeSymbol != null) { if ((typeNode.Modifiers & Modifiers.Public) != 0) { typeSymbol.SetPublic(); } BuildType(typeSymbol, typeNode); if (namespaceSymbol.Name.EndsWith(_options.TestsSubnamespace, StringComparison.Ordinal)) { typeSymbol.SetTestType(); } } return(typeSymbol); }