public void GetContent()
        {
            var parseInfo = _parseInfo
                            .SetReturnType(ReturnType)
                            .SetThisType(ContainingType)
                            .SetCallInfo(CallInfo);

            if (Context.Block != null)
            {
                var returnTracker = new ReturnTracker();
                Block = new BlockAction(parseInfo.SetReturnTracker(returnTracker), _methodScope, Context.Block);

                MultiplePaths = returnTracker.IsMultiplePaths;

                // If there is only one return statement, set SingleReturnValue.
                if (returnTracker.Returns.Count == 1)
                {
                    SingleReturnValue = returnTracker.Returns[0].ReturningValue;
                }
            }
            else if (Context.MacroValue != null)
            {
                MacroValue = SingleReturnValue = parseInfo.SetExpectType(ReturnType).GetExpression(_methodScope, Context.MacroValue);

                SemanticsHelper.ExpectValueType(parseInfo, MacroValue, ReturnType, Context.MacroValue.Range);
            }

            ContentReady.Set();
        }
        /// <summary>Gets a variable or type from a VariableContext.</summary>
        /// <param name="scope">The scope the variable was called in.</param>
        /// <param name="getter">The getter scope.</param>
        /// <param name="variableContext">The context of the variable.</param>
        /// <param name="selfContained">Whether the variable was not called in an expression tree.</param>
        /// <returns>An IExpression created from the context.</returns>
        public IExpression GetVariable(Scope scope, Scope getter, Identifier variableContext)
        {
            if (!variableContext.Token)
            {
                return(new MissingElementAction(TranslateInfo));
            }

            var name  = variableContext.Token.Text;
            var range = variableContext.Token.Range;

            // Get the variable.
            var variable = scope.GetAllVariables(name, ResolveInvokeInfo != null).FirstOrDefault();

            // Variable does not exist.
            if (variable == null)
            {
                Script.Diagnostics.Error(string.Format("The variable {0} does not exist in the {1}.", name, scope.ErrorName), range);
                variable = new MissingVariable(TranslateInfo, name);
            }

            // Check the access level.
            if (!SemanticsHelper.AccessLevelMatches(variable.AccessLevel, variable.Attributes.ContainingType, ThisType))
            {
                Script.Diagnostics.Error(string.Format("'{0}' is inaccessable due to its access level.", name), range);
            }

            var apply = new VariableApply(this, scope, getter, variable, variableContext);

            apply.Accept();
            return(apply.VariableCall);
        }
        protected virtual void TypeCheck()
        {
            if (_nameRange == null)
            {
                return;
            }

            // If the type of the variable is a constant workshop value and there is no initial value, throw a syntax error.
            if (_varInfo.Type != null && _varInfo.Type.IsConstant() && _varInfo.InitialValueContext == null)
            {
                _diagnostics.Error("Variables with constant workshop types must have an initial value", _nameRange);
            }

            if (ComponentCollection.IsAttribute(AttributeType.Static) && SemanticsHelper.RecursivelyGetGenerics(_varInfo.Type).Any(type => type is AnonymousType))
            {
                _diagnostics.Error("Static variables cannot use anonymous types", _nameRange);
            }
        }
        public void TrySet(ParseInfo parseInfo, IExpression value, DocRange expressionRange)
        {
            var type = CodeType.GetCodeType(parseInfo.TranslateInfo);

            // Check if the hook was already set.
            if (WasSet)
            {
                parseInfo.Script.Diagnostics.Error("Hooks cannot be set twice.", expressionRange);
            }
            // Check if the given value implements the expected value.
            else if (SemanticsHelper.ExpectValueType(parseInfo, value, type, expressionRange))
            {
                // Set the hook.
                HookValue = value;
                SetHook?.Invoke(value);
            }

            WasSet = true;
        }
 public void CheckConflict(ParseInfo parseInfo, CheckConflict identifier, DocRange range) => SemanticsHelper.ErrorIfConflicts(
     parseInfo: parseInfo,
     identifier: identifier,
     nameConflictMessage: Parse.CheckConflict.CreateNameConflictMessage(Name, identifier.Name),
     overloadConflictMessage: Parse.CheckConflict.CreateOverloadConflictMessage(Name, identifier.Name),
     range: range,
     _objectScope, _staticScope);
        private DefinedMethodProvider(ParseInfo parseInfo, IScopeHandler scopeProvider, FunctionContext context, IDefinedTypeInitializer containingType)
        {
            _parseInfo     = parseInfo;
            Context        = context;
            ContainingType = containingType;
            CallInfo       = new CallInfo(new RecursiveCallHandler(this, context.Subroutine || context.Attributes.Recursive), parseInfo.Script, ContentReady);

            DocRange nameRange = context.Identifier.Range;

            // Get the attributes.
            var attributes = new GenericAttributeAppender(AttributeType.Ref, AttributeType.In, AttributeType.GlobalVar, AttributeType.PlayerVar);

            AttributesGetter.GetAttributes(parseInfo.Script.Diagnostics, context.Attributes, attributes);

            // Set the attributes.
            Static      = attributes.IsStatic;
            Recursive   = attributes.IsRecursive;
            Virtual     = attributes.IsVirtual;
            AccessLevel = attributes.Accessor;
            Recursive   = attributes.IsRecursive;

            // Get subroutine info.
            if (context.Subroutine)
            {
                IsSubroutine            = true;
                SubroutineName          = context.Subroutine.Text.RemoveQuotes();
                SubroutineDefaultGlobal = !context.PlayerVar;
            }

            // Setup the scope.
            var containingScope = scopeProvider.GetScope(Static);

            containingScope.MethodContainer = true;
            _methodScope = containingScope.Child(true);

            // Get the generics.
            GenericTypes = AnonymousType.GetGenerics(parseInfo, context.TypeArguments, this);
            foreach (var type in GenericTypes)
            {
                _methodScope.AddType(new GenericCodeTypeInitializer(type));
            }

            // Get the type.
            if (!context.Type.IsVoid)
            {
                ReturnType = TypeFromContext.GetCodeTypeFromContext(parseInfo, _methodScope, context.Type);
            }

            // Setup the parameters.
            ParameterProviders = ParameterProvider.GetParameterProviders(parseInfo, _methodScope, context.Parameters, IsSubroutine);
            ParameterTypes     = ParameterProviders.Select(p => p.Type).ToArray();

            // Override
            if (attributes.IsOverride)
            {
                OverridingFunction = (DefinedMethodInstance)scopeProvider.GetOverridenFunction(parseInfo.TranslateInfo, new FunctionOverrideInfo(Name, ParameterTypes));
                if (OverridingFunction == null)
                {
                    SemanticsHelper.CouldNotOverride(parseInfo, nameRange, "method");
                }
            }

            // Check conflicts and add to scope.
            scopeProvider.CheckConflict(parseInfo, new(Name, ParameterTypes), nameRange);
            scopeProvider.Add(GetDefaultInstance(scopeProvider.DefinedIn()), Static);

            // Add LSP elements
            // Hover
            parseInfo.Script.AddHover(nameRange, GetLabel(parseInfo.TranslateInfo, LabelInfo.Hover));
            // 'references' code lens
            parseInfo.Script.AddCodeLensRange(new ReferenceCodeLensRange(this, parseInfo, CodeLensSourceType.Function, DefinedAt.range));
            // Rename & go-to-definition
            parseInfo.Script.Elements.AddDeclarationCall(this, new DeclarationCall(nameRange, true));
            // todo: 'override' code lens
            // if (Attributes.IsOverrideable)
            //     parseInfo.Script.AddCodeLensRange(new ImplementsCodeLensRange(this, parseInfo.Script, CodeLensSourceType.Function, nameRange));

            // Add the CallInfo to the recursion check.
            parseInfo.TranslateInfo.GetComponent <RecursionCheckComponent>().AddCheck(CallInfo);

            // Queue content for staged initiation.
            parseInfo.TranslateInfo.StagedInitiation.On(this);
        }
        private void GetInitialValue()
        {
            // Get the initial value.
            if (_initialValueContext != null)
            {
                ParseInfo parseInfo = this._parseInfo;

                // Store the initial value's restricted calls.
                RestrictedCallList restrictedCalls = null;
                if (_handleRestrictedCalls)
                {
                    restrictedCalls = new RestrictedCallList();
                    parseInfo       = parseInfo.SetRestrictedCallHandler(restrictedCalls);
                }

                ParseInfo initialValueParseInfo = parseInfo.SetExpectType(CodeType);
                if (parseInfo.CurrentCallInfo == null)
                {
                    CallInfo callInfo = new CallInfo(parseInfo.Script);
                    initialValueParseInfo = initialValueParseInfo.SetCallInfo(callInfo);
                }

                // Parse the initial value.
                InitialValue = initialValueParseInfo.GetExpression(_operationalScope, _initialValueContext);

                // Get the inferred type.
                if (_inferType)
                {
                    CodeType = InitialValue.Type();
                    _variableTypeHandler.SetType(CodeType);
                    AddScriptData();
                }

                // If the initial value's type is constant, make sure the constant type's implements the variable's type.
                if (InitialValue?.Type() != null && InitialValue.Type().IsConstant() && !InitialValue.Type().Implements(CodeType))
                {
                    parseInfo.Script.Diagnostics.Error($"The type '{InitialValue.Type().Name}' cannot be stored.", _initialValueContext.Range);
                }

                // If the variable's type is constant, make sure the value's type matches.
                else
                {
                    SemanticsHelper.ExpectValueType(parseInfo, InitialValue, CodeType, _initialValueContext.Range);
                }

                // Check restricted calls.
                if (_handleRestrictedCalls)
                {
                    foreach (RestrictedCall call in restrictedCalls)
                    {
                        // If the variable type is global, or the variable type is player and the restricted call type is not player...
                        if (VariableType == VariableType.Global ||
                            (VariableType == VariableType.Player && call.CallType != RestrictedCallType.EventPlayer))
                        {
                            // ... then add the error.
                            call.AddDiagnostic(parseInfo.Script.Diagnostics);
                        }
                    }
                }
            }

            ValueReady.Set();
        }