Esempio n. 1
0
        private FieldSymbol BuildPropertyAsField(PropertyDeclarationNode propertyNode, TypeSymbol typeSymbol)
        {
            AttributeNode intrinsicPropertyAttribute = AttributeNode.FindAttribute(propertyNode.Attributes, "IntrinsicProperty");

            if (intrinsicPropertyAttribute == null)
            {
                return(null);
            }

            TypeSymbol fieldType = typeSymbol.SymbolSet.ResolveType(propertyNode.Type, _symbolTable, typeSymbol);

            Debug.Assert(fieldType != null);

            if (fieldType != null)
            {
                FieldSymbol symbol = new FieldSymbol(propertyNode.Name, typeSymbol, fieldType);
                BuildMemberDetails(symbol, typeSymbol, propertyNode, propertyNode.Attributes);

                string scriptAlias = GetAttributeValue(propertyNode.Attributes, "ScriptAlias");
                if (scriptAlias != null)
                {
                    symbol.SetAlias(scriptAlias);
                }

                return(symbol);
            }

            return(null);
        }
Esempio n. 2
0
        bool IParseNodeValidator.Validate(ParseNode node, CompilerOptions options, IErrorHandler errorHandler)
        {
            CompilationUnitNode compilationUnitNode = (CompilationUnitNode)node;

            foreach (AttributeBlockNode attribBlock in compilationUnitNode.Attributes)
            {
                AttributeNode scriptNamespaceNode = AttributeNode.FindAttribute(attribBlock.Attributes, "ScriptNamespace");
                if (scriptNamespaceNode != null)
                {
                    string scriptNamespace = (string)((LiteralNode)scriptNamespaceNode.Arguments[0]).Value;

                    if (Utility.IsValidScriptNamespace(scriptNamespace) == false)
                    {
                        errorHandler.ReportError("A script namespace must be a valid script identifier.",
                                                 scriptNamespaceNode.Token.Location);
                    }
                }
            }

            foreach (ParseNode childNode in compilationUnitNode.Members)
            {
                if (!(childNode is NamespaceNode))
                {
                    errorHandler.ReportError("Non-namespaced types are not supported.",
                                             childNode.Token.Location);
                    return(false);
                }
            }

            return(true);
        }
Esempio n. 3
0
        bool IParseNodeValidator.Validate(ParseNode node, CompilerOptions options, IErrorHandler errorHandler)
        {
            CompilationUnitNode compilationUnitNode = (CompilationUnitNode)node;

            foreach (AttributeBlockNode attribBlock in compilationUnitNode.Attributes)
            {
                AttributeNode scriptNamespaceNode =
                    AttributeNode.FindAttribute(attribBlock.Attributes, DSharpStringResources.SCRIPT_NAMESPACE_ATTRIBUTE);

                if (scriptNamespaceNode != null)
                {
                    string scriptNamespace = (string)((LiteralNode)scriptNamespaceNode.Arguments[0]).Value;

                    if (Utility.IsValidScriptNamespace(scriptNamespace) == false)
                    {
                        errorHandler.ReportNodeValidationError(DSharpStringResources.SCRIPT_NAMESPACE_VIOLATION, scriptNamespaceNode);
                    }
                }
            }

            foreach (ParseNode childNode in compilationUnitNode.Members)
            {
                if (!(childNode is NamespaceNode))
                {
                    errorHandler.ReportNodeValidationError(DSharpStringResources.SCRIPT_NAMESPACE_TYPE_VIOLATION, childNode);

                    return(false);
                }
            }

            return(true);
        }
Esempio n. 4
0
        internal static string GetAttributeValue(this ParseNodeList parseNodeList, string attributeName)
        {
            AttributeNode node = AttributeNode.FindAttribute(parseNodeList, attributeName);

            if (node != null && node.Arguments.Count != 0 && node.Arguments[0].NodeType == ParseNodeType.Literal)
            {
                Debug.Assert(((LiteralNode)node.Arguments[0]).Value is string);

                return((string)((LiteralNode)node.Arguments[0]).Value);
            }

            return(null);
        }
Esempio n. 5
0
        private string GetAttributeValue(ParseNodeList attributes, string attributeName)
        {
            AttributeNode node = AttributeNode.FindAttribute(attributes, attributeName);

            if (node != null)
            {
                Debug.Assert(node.Arguments[0] is LiteralNode);
                Debug.Assert(((LiteralNode)node.Arguments[0]).Value is string);

                return((string)((LiteralNode)node.Arguments[0]).Value);
            }
            return(null);
        }
Esempio n. 6
0
        private IndexerSymbol BuildIndexer(IndexerDeclarationNode indexerNode, TypeSymbol typeSymbol)
        {
            TypeSymbol indexerType = typeSymbol.SymbolSet.ResolveType(indexerNode.Type, _symbolTable, typeSymbol);

            Debug.Assert(indexerType != null);

            if (indexerType != null)
            {
                IndexerSymbol indexer = new IndexerSymbol(typeSymbol, indexerType);
                BuildMemberDetails(indexer, typeSymbol, indexerNode, indexerNode.Attributes);

                if (AttributeNode.FindAttribute(indexerNode.Attributes, "IntrinsicProperty") != null)
                {
                    indexer.SetIntrinsic();
                }

                SymbolImplementationFlags implFlags = SymbolImplementationFlags.Regular;
                if (indexerNode.SetAccessor == null)
                {
                    implFlags |= SymbolImplementationFlags.ReadOnly;
                }
                if ((indexerNode.Modifiers & Modifiers.Abstract) != 0)
                {
                    implFlags |= SymbolImplementationFlags.Abstract;
                }
                else if ((indexerNode.Modifiers & Modifiers.Override) != 0)
                {
                    implFlags |= SymbolImplementationFlags.Override;
                }

                indexer.SetImplementationState(implFlags);

                Debug.Assert(indexerNode.Parameters.Count != 0);
                foreach (ParameterNode parameterNode in indexerNode.Parameters)
                {
                    ParameterSymbol paramSymbol = BuildParameter(parameterNode, indexer);
                    if (paramSymbol != null)
                    {
                        paramSymbol.SetParseContext(parameterNode);
                        indexer.AddParameter(paramSymbol);
                    }
                }

                indexer.AddParameter(new ParameterSymbol("value", indexer, indexerType, ParameterMode.In));

                return(indexer);
            }

            return(null);
        }
Esempio n. 7
0
        bool IParseNodeValidator.Validate(ParseNode node, CompilerOptions options, IErrorHandler errorHandler)
        {
            NamespaceNode namespaceNode = (NamespaceNode)node;

            bool valid = true;

            foreach (ParseNode childNode in namespaceNode.Members)
            {
                if (childNode is NamespaceNode)
                {
                    errorHandler.ReportError("Nested namespaces are not supported.",
                                             childNode.Token.Location);
                    valid = false;
                }
            }

            if (namespaceNode.Name.Equals("System") ||
                namespaceNode.Name.StartsWith("System."))
            {
                // Usage of the System namespace is limited to imported types.

                foreach (ParseNode childNode in namespaceNode.Members)
                {
                    bool allowed = false;

                    if (childNode is UserTypeNode)
                    {
                        ParseNodeList attributes = ((UserTypeNode)childNode).Attributes;
                        if (AttributeNode.FindAttribute(attributes, "ScriptImport") != null ||
                            (AttributeNode.FindAttribute(attributes, "ScriptAllowSystemNamespace") != null))
                        {
                            allowed = true;
                        }
                    }

                    if (allowed == false)
                    {
                        errorHandler.ReportError("Only types marked as Imported are allowed within the System namespace.",
                                                 namespaceNode.Token.Location);
                        valid = false;
                        break;
                    }
                }
            }

            return(valid);
        }
Esempio n. 8
0
        private void BuildMemberDetails(MemberSymbol memberSymbol, TypeSymbol typeSymbol, MemberNode memberNode, ParseNodeList attributes)
        {
            if (memberSymbol.Type != SymbolType.EnumerationField)
            {
                memberSymbol.SetVisibility(GetVisibility(memberNode, typeSymbol));
            }

            bool preserveCase = (AttributeNode.FindAttribute(attributes, "PreserveCase") != null);

            memberSymbol.SetNameCasing(preserveCase);

            string scriptName = GetAttributeValue(attributes, "ScriptName");

            if (scriptName != null)
            {
                memberSymbol.SetTransformedName(scriptName);
            }
            else if (AttributeNode.FindAttribute(attributes, "PreserveName") != null)
            {
                memberSymbol.DisableNameTransformation();
            }
        }
Esempio n. 9
0
        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))
                    {
                        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);
        }
Esempio n. 10
0
        bool IParseNodeValidator.Validate(ParseNode node, CompilerOptions options, IErrorHandler errorHandler)
        {
            CustomTypeNode typeNode = (CustomTypeNode)node;

            bool      restrictToMethodMembers = false;
            bool      hasCodeMembers          = false;
            ParseNode codeMemberNode          = null;

            AttributeNode importedTypeAttribute = AttributeNode.FindAttribute(typeNode.Attributes, "Imported");

            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);
            }

            AttributeNode scriptNamespaceNode = AttributeNode.FindAttribute(typeNode.Attributes, "ScriptNamespace");

            if (scriptNamespaceNode != null)
            {
                string scriptNamespace = (string)((LiteralNode)scriptNamespaceNode.Arguments[0]).Value;

                if (Utility.IsValidScriptNamespace(scriptNamespace) == false)
                {
                    errorHandler.ReportError("A script namespace must be a valid script identifier.",
                                             scriptNamespaceNode.Token.Location);
                }
            }

            if (typeNode.Type == TokenType.Struct)
            {
                errorHandler.ReportError("Struct types are not supported. Use classes annotated with the Record metadata attribute.",
                                         typeNode.Token.Location);
                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.Interface) &&
                (typeNode.BaseTypes.Count != 0))
            {
                errorHandler.ReportError("Derived interface types are not supported.",
                                         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, "Record") == 0)
                        {
                            if ((typeNode.Modifiers & Modifiers.Sealed) == 0)
                            {
                                errorHandler.ReportError("Classes derived from the Record base class must be marked as sealed.",
                                                         typeNode.Token.Location);
                            }

                            if (typeNode.BaseTypes.Count != 1)
                            {
                                errorHandler.ReportError("Classes derived from the Record base class cannot implement interfaces.",
                                                         typeNode.Token.Location);
                            }
                        }
                        else 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 globalMethodsAttribute = AttributeNode.FindAttribute(typeNode.Attributes, "GlobalMethods");
                if (globalMethodsAttribute != null)
                {
                    restrictToMethodMembers = true;

                    if ((typeNode.Modifiers & Modifiers.Static) == 0)
                    {
                        errorHandler.ReportError("GlobalMethods attribute can only be set on static classes.",
                                                 typeNode.Token.Location);
                    }
                }

                AttributeNode mixinAttribute = AttributeNode.FindAttribute(typeNode.Attributes, "Mixin");
                if (mixinAttribute != null)
                {
                    restrictToMethodMembers = true;

                    if ((typeNode.Modifiers & Modifiers.Static) == 0)
                    {
                        errorHandler.ReportError("Mixin attribute can only be set on 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 (restrictToMethodMembers &&
                        (memberNode.NodeType != ParseNodeType.MethodDeclaration) &&
                        (memberNode.NodeType != ParseNodeType.ConstructorDeclaration))
                    {
                        errorHandler.ReportError("Classes marked with GlobalMethods or Mixin attribute should only have methods.",
                                                 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;

                    bool preserveCase = (AttributeNode.FindAttribute(memberNode.Attributes, "PreserveCase") != null);
                    if (Utility.IsKeyword(name, /* 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;
                    }
                }
            }

            if ((typeNode.Type == TokenType.Struct) && hasCodeMembers)
            {
                errorHandler.ReportError("A struct type is limited to field and constructor members.",
                                         codeMemberNode.Token.Location);
            }

            return(true);
        }
Esempio n. 11
0
        private void BuildType(TypeSymbol typeSymbol, UserTypeNode typeNode)
        {
            Debug.Assert(typeSymbol != null);
            Debug.Assert(typeNode != null);

            ParseNodeList attributes = typeNode.Attributes;

            if (AttributeNode.FindAttribute(attributes, "Imported") != null)
            {
                typeSymbol.SetImported(/* dependencyName */ null);
            }

            if (AttributeNode.FindAttribute(attributes, "IgnoreNamespace") != null)
            {
                typeSymbol.SetIgnoreNamespace();
            }

            if (AttributeNode.FindAttribute(attributes, "PreserveName") != null)
            {
                typeSymbol.DisableNameTransformation();
            }

            string scriptName = GetAttributeValue(attributes, "ScriptName");

            if (scriptName != null)
            {
                typeSymbol.SetTransformedName(scriptName);
            }

            if (typeNode.Type == TokenType.Class)
            {
                bool   globalizeMembers = false;
                string mixinRoot        = null;

                AttributeNode globalMethodsAttribute = AttributeNode.FindAttribute(attributes, "GlobalMethods");
                if (globalMethodsAttribute != null)
                {
                    globalizeMembers = true;
                }
                else
                {
                    AttributeNode mixinAttribute = AttributeNode.FindAttribute(attributes, "Mixin");
                    if (mixinAttribute != null)
                    {
                        Debug.Assert(mixinAttribute.Arguments[0] is LiteralNode);
                        Debug.Assert(((LiteralNode)mixinAttribute.Arguments[0]).Value is string);

                        mixinRoot        = (string)((LiteralNode)mixinAttribute.Arguments[0]).Value;
                        globalizeMembers = true;
                    }
                }

                if (globalizeMembers)
                {
                    ((ClassSymbol)typeSymbol).SetGlobalMethods(mixinRoot);
                }
            }

            if (typeNode.Type == TokenType.Enum)
            {
                if (AttributeNode.FindAttribute(attributes, "NamedValues") != null)
                {
                    ((EnumerationSymbol)typeSymbol).SetNamedValues();
                }
                else if (AttributeNode.FindAttribute(attributes, "NumericValues") != null)
                {
                    ((EnumerationSymbol)typeSymbol).SetNumericValues();
                }
            }
        }
Esempio n. 12
0
        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);
        }
Esempio n. 13
0
        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);
        }
Esempio n. 14
0
        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);
        }