Example #1
0
        private bool TryAddProperty(FunctionDefinition node, IPythonType declaringType)
        {
            // We can't add a property to an unknown type. Fallback to a regular function for now.
            // TOOD: Decouple declaring types from the property.
            if (declaringType.IsUnknown())
            {
                return(false);
            }

            var dec        = node.Decorators?.Decorators;
            var decorators = dec != null?dec.ExcludeDefault().ToArray() : Array.Empty <Expression>();

            foreach (var d in decorators.OfType <NameExpression>())
            {
                switch (d.Name)
                {
                case @"property":
                    AddProperty(node, declaringType, false);
                    return(true);

                case @"abstractproperty":
                    AddProperty(node, declaringType, true);
                    return(true);
                }
            }
            return(false);
        }
 private static bool IsStubBetterType(IPythonType sourceType, IPythonType stubType)
 {
     if (stubType.IsUnknown())
     {
         // Do not use worse types than what is in the module.
         return(false);
     }
     if (sourceType.IsUnknown())
     {
         return(true); // Anything is better than unknowns.
     }
     // If stub says 'Any' but we have better type, keep the current type.
     return(!(stubType.DeclaringModule is TypingModule) || stubType.Name != "Any");
 }
        private void TransferDocumentationAndLocation(IPythonType sourceType, IPythonType stubType)
        {
            if (sourceType.IsUnknown() || sourceType.DeclaringModule.ModuleType == ModuleType.Builtins ||
                stubType.IsUnknown() || stubType.DeclaringModule.ModuleType == ModuleType.Builtins)
            {
                return; // Do not transfer location of unknowns or builtins
            }

            // Stub may be one for multiple modules - when module consists of several
            // submodules, there is typically only one stub for the main module.
            // Types from 'unittest.case' (library) are stubbed in 'unittest' stub.
            if (!IsFromThisModuleOrSubmodules(sourceType))
            {
                return; // Do not change unrelated types.
            }

            // Destination must be from this module stub and not from other modules.
            // Consider that 'email.headregistry' stub has DataHeader declaring 'datetime'
            // property of type 'datetime' from 'datetime' module. We don't want to modify
            // datetime type and change it's location to 'email.headregistry'.
            if (stubType.DeclaringModule.ModuleType != ModuleType.Stub || stubType.DeclaringModule != _eval.Module.Stub)
            {
                return;
            }

            // Documentation and location are always get transferred from module type
            // to the stub type and never the other way around. This makes sure that
            // we show documentation from the original module and goto definition
            // navigates to the module source and not to the stub.
            if (sourceType != stubType && sourceType is PythonType src && stubType is PythonType dst)
            {
                // If type is a class, then doc can either come from class definition node of from __init__.
                // If class has doc from the class definition, don't stomp on it.
                if (src is PythonClassType srcClass && dst is PythonClassType dstClass)
                {
                    // Higher lever source wins
                    if (srcClass.DocumentationSource == PythonClassType.ClassDocumentationSource.Class ||
                        (srcClass.DocumentationSource == PythonClassType.ClassDocumentationSource.Init && dstClass.DocumentationSource == PythonClassType.ClassDocumentationSource.Base))
                    {
                        dstClass.SetDocumentation(srcClass.Documentation);
                    }
                }
 private static void TransferDocumentationAndLocation(IPythonType s, IPythonType d)
 {
     if (s.IsUnknown())
     {
         return; // Do not transfer location of unknowns
     }
     // Documentation and location are always get transferred from module type
     // to the stub type and never the other way around. This makes sure that
     // we show documentation from the original module and goto definition
     // navigates to the module source and not to the stub.
     if (s != d && s is PythonType src && d is PythonType dst)
     {
         var documentation = src.Documentation;
         if (!string.IsNullOrEmpty(documentation))
         {
             dst.SetDocumentation(documentation);
         }
         dst.Location = src.Location;
     }
 }
Example #5
0
        private void HandleTypedVariable(IPythonType variableType, IMember value, Expression expr)
        {
            // Check value type for compatibility
            IMember instance = null;

            if (value != null)
            {
                var valueType = value.GetPythonType();
                if (!variableType.IsUnknown() && !valueType.Equals(variableType))
                {
                    // TODO: warn incompatible value type.
                    // TODO: verify values. Value may be list() while variable type is List[str].
                    // Leave it as variable type.
                }
                else
                {
                    instance = value;
                }
            }
            var args = ArgumentSet.Empty(expr, Eval);

            instance = instance ?? variableType?.CreateInstance(args) ?? Eval.UnknownType.CreateInstance(ArgumentSet.WithoutContext);

            if (expr is NameExpression ne)
            {
                Eval.DeclareVariable(ne.Name, instance, VariableSource.Declaration, ne);
                return;
            }

            if (expr is MemberExpression m)
            {
                // self.x : int = 42
                var self    = Eval.LookupNameInScopes("self", out var scope);
                var argType = self?.GetPythonType();
                if (argType is PythonClassType cls && scope != null)
                {
                    cls.AddMember(m.Name, instance, true);
                }
            }
        }