Example #1
0
        public DefinedMethod(ParseInfo parseInfo, Scope objectScope, Scope staticScope, DeltinScriptParser.Define_methodContext context, CodeType containingType)
            : base(parseInfo, context.name.Text, new Location(parseInfo.Script.Uri, DocRange.GetRange(context.name)))
        {
            this.context = context;

            Attributes.ContainingType = containingType;

            DocRange nameRange = DocRange.GetRange(context.name);

            // Get the attributes.
            MethodAttributeAppender attributeResult = new MethodAttributeAppender(Attributes);
            MethodAttributesGetter  attributeGetter = new MethodAttributesGetter(context, attributeResult);

            attributeGetter.GetAttributes(parseInfo.Script.Diagnostics);

            // Copy attribute results
            Static         = attributeResult.Static;
            IsSubroutine   = attributeResult.IsSubroutine;
            SubroutineName = attributeResult.SubroutineName;
            AccessLevel    = attributeResult.AccessLevel;

            // Setup scope.
            SetupScope(Static ? staticScope : objectScope);
            methodScope.MethodContainer = true;
            BlockScope = methodScope.Child();

            // Get the type.
            if (context.VOID() == null)
            {
                DoesReturnValue = true;
                ReturnType      = CodeType.GetCodeTypeFromContext(parseInfo, context.code_type());
            }

            // Setup the parameters and parse the block.
            if (!IsSubroutine)
            {
                SetupParameters(context.setParameters(), false);
            }
            else
            {
                subroutineDefaultGlobal = context.PLAYER() == null;
                Attributes.Parallelable = true;
                parseInfo.TranslateInfo.AddSubroutine(this);

                // Subroutines should not have parameters.
                SetupParameters(context.setParameters(), true);
            }

            // Override attribute.
            if (Attributes.Override)
            {
                IMethod overriding = objectScope.GetMethodOverload(this);

                // No method with the name and parameters found.
                if (overriding == null)
                {
                    parseInfo.Script.Diagnostics.Error("Could not find a method to override.", nameRange);
                }
                else if (!overriding.Attributes.IsOverrideable)
                {
                    parseInfo.Script.Diagnostics.Error("The specified method is not marked as virtual.", nameRange);
                }
                else
                {
                    overriding.Attributes.AddOverride(this);
                }

                if (overriding != null && overriding.DefinedAt != null)
                {
                    // Make the override keyword go to the base method.
                    parseInfo.Script.AddDefinitionLink(
                        attributeGetter.ObtainedAttributes.First(at => at.Type == MethodAttributeType.Override).Range,
                        overriding.DefinedAt
                        );

                    if (!Attributes.Recursive)
                    {
                        Attributes.Recursive = overriding.Attributes.Recursive;
                    }
                }
            }

            if (Attributes.IsOverrideable && AccessLevel == AccessLevel.Private)
            {
                parseInfo.Script.Diagnostics.Error("A method marked as virtual or abstract must have the protection level 'public' or 'protected'.", nameRange);
            }

            // Syntax error if the block is missing.
            if (context.block() == null)
            {
                parseInfo.Script.Diagnostics.Error("Expected block.", nameRange);
            }

            // Add to the scope. Check for conflicts if the method is not overriding.
            containingScope.AddMethod(this, parseInfo.Script.Diagnostics, nameRange, !Attributes.Override);

            // Add the hover info.
            parseInfo.Script.AddHover(DocRange.GetRange(context.name), GetLabel(true));

            if (Attributes.IsOverrideable)
            {
                parseInfo.Script.AddCodeLensRange(new ImplementsCodeLensRange(this, parseInfo.Script, CodeLensSourceType.Function, nameRange));
            }

            parseInfo.TranslateInfo.ApplyBlock(this);
        }