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