Beispiel #1
0
        /// <summary>
        /// Opens the find symbols dialog with a list of results.  This is done by requesting
        /// that VS does a search against our library GUID.  Our library then responds to
        /// that request by extracting the prvoided symbol list out and using that for the
        /// search results.
        /// </summary>
        private static void ShowFindSymbolsDialog(ExpressionAnalysis provider, IVsNavInfo symbols)
        {
            // ensure our library is loaded so find all references will go to our library
            //VSGeneroPackage.GetGlobalService(typeof(IGeneroLibraryManager));
            // For some reason, using the GetGlobalService call was calling resulting in a call to an external package function, if it existed.
            // We want to keep the call to within this package.
            VSGeneroPackage.Instance.LoadLibraryManager();

            if (provider != null && provider.Expression != "")
            {
                var findSym = (IVsFindSymbol)VSGeneroPackage.GetGlobalService(typeof(SVsObjectSearch));
                VSOBSEARCHCRITERIA2 searchCriteria = new VSOBSEARCHCRITERIA2();
                searchCriteria.eSrchType   = VSOBSEARCHTYPE.SO_ENTIREWORD;
                searchCriteria.pIVsNavInfo = symbols;
                searchCriteria.grfOptions  = (uint)_VSOBSEARCHOPTIONS2.VSOBSO_LISTREFERENCES;
                searchCriteria.szName      = provider.Expression;

                Guid guid = Guid.Empty;
                //  new Guid("{a5a527ea-cf0a-4abf-b501-eafe6b3ba5c6}")
                int hResult = findSym.DoSearch(new Guid(CommonConstants.LibraryGuid), new VSOBSEARCHCRITERIA2[] { searchCriteria });
                ErrorHandler.ThrowOnFailure(hResult);
            }
            else
            {
                var statusBar = (IVsStatusbar)VSGeneroPackage.GetGlobalService(typeof(SVsStatusbar));
                statusBar.SetText("The caret must be on valid expression to find all references.");
            }
        }
Beispiel #2
0
        public override IVsSimpleObjectList2 DoSearch(VSOBSEARCHCRITERIA2 criteria)
        {
            var node = _hierarchy as PythonFileNode;

            if (node != null)
            {
                var analysis = node.GetProjectEntry() as IPythonProjectEntry;

                if (analysis != null)
                {
                    var exprAnalysis = new ExpressionAnalysis(
                        ((PythonProjectNode)node.ProjectMgr).GetAnalyzer(),
                        criteria.szName.Substring(criteria.szName.LastIndexOf(':') + 1),
                        analysis.Analysis,
                        0,
                        null,
                        null
                        );

                    return(EditFilter.GetFindRefLocations(_hierarchy.ProjectMgr.Site, exprAnalysis));
                }
            }

            return(null);
        }
Beispiel #3
0
        private static void GetDefsRefsAndValues(ExpressionAnalysis provider, out Dictionary <LocationInfo, SimpleLocationInfo> definitions, out Dictionary <LocationInfo, SimpleLocationInfo> references, out Dictionary <LocationInfo, SimpleLocationInfo> values)
        {
            references  = new Dictionary <LocationInfo, SimpleLocationInfo>();
            definitions = new Dictionary <LocationInfo, SimpleLocationInfo>();
            values      = new Dictionary <LocationInfo, SimpleLocationInfo>();

            foreach (var v in provider.Variables)
            {
                if (v.Location.FilePath == null)
                {
                    // ignore references in the REPL
                    continue;
                }

                switch (v.Type)
                {
                case VariableType.Definition:
                    values.Remove(v.Location);
                    definitions[v.Location] = new SimpleLocationInfo(provider.Expression, v.Location, StandardGlyphGroup.GlyphGroupField);
                    break;

                case VariableType.Reference:
                    references[v.Location] = new SimpleLocationInfo(provider.Expression, v.Location, StandardGlyphGroup.GlyphGroupField);
                    break;

                case VariableType.Value:
                    if (!definitions.ContainsKey(v.Location))
                    {
                        values[v.Location] = new SimpleLocationInfo(provider.Expression, v.Location, StandardGlyphGroup.GlyphGroupField);
                    }
                    break;
                }
            }
        }
Beispiel #4
0
        public void Handle()
        {
            string jsonSql = string.Empty;

            jsonSql = @"{'rules':[{'field':'AppNameTarget','op':'like','value':'GetUsrFc','type':'string'}],'groups':[{'rules':[{'field':'Uname','op':'like','value':'GetUsrFc','type':'string'}],'op':'or'},{'rules':[{'field':'Askchannel','op':'like','value':'GetUsrFc','type':'string'}],'op':'or'},{'rules':[{'field':'Askrouter','op':'like','value':'GetUsrFc','type':'string'}],'op':'or'},{'rules':[{'field':'Askmethod','op':'like','value':'GetUsrFc','type':'string'}],'op':'or'},{'rules':[{'field':'Ip','op':'like','value':'GetUsrFc','type':'string'}],'op':'or'}],'op':'or'}";
            var group = Newtonsoft.Json.JsonConvert.DeserializeObject <Group>(jsonSql);
            var sql   = ExpressionAnalysis.TransmitFilter(group, "__table__");

            Console.WriteLine(sql);
        }
Beispiel #5
0
        private static void GetDefsRefsAndValues(ExpressionAnalysis provider, out Dictionary <LocationInfo, SimpleLocationInfo> definitions, out Dictionary <LocationInfo, SimpleLocationInfo> references, out Dictionary <LocationInfo, SimpleLocationInfo> values)
        {
            references  = new Dictionary <LocationInfo, SimpleLocationInfo>();
            definitions = new Dictionary <LocationInfo, SimpleLocationInfo>();
            values      = new Dictionary <LocationInfo, SimpleLocationInfo>();

            var priorityVariables = new Dictionary <string, IAnalysisVariable>(StringComparer.OrdinalIgnoreCase);

            foreach (var v in provider.Variables)
            {
                if (v.Location.FilePath == null)
                {
                    // ignore references in the REPL
                    continue;
                }

                switch (v.Type)
                {
                case VariableType.Definition:
                    values.Remove(v.Location);

                    if (!string.IsNullOrWhiteSpace(v.Name) && v.Priority != 0)
                    {
                        IAnalysisVariable existing;
                        if (priorityVariables.TryGetValue(v.Name, out existing))
                        {
                            if (existing.Priority <= v.Priority)
                            {
                                break;
                            }
                            else
                            {
                                priorityVariables.Remove(v.Name);
                            }
                        }
                        priorityVariables.Add(v.Name, v);
                    }

                    definitions[v.Location] = new SimpleLocationInfo(provider.Expression, v.Location, StandardGlyphGroup.GlyphGroupField);
                    break;

                case VariableType.Reference:
                    references[v.Location] = new SimpleLocationInfo(provider.Expression, v.Location, StandardGlyphGroup.GlyphGroupField);
                    break;

                case VariableType.Value:
                    if (!definitions.ContainsKey(v.Location))
                    {
                        values[v.Location] = new SimpleLocationInfo(provider.Expression, v.Location, StandardGlyphGroup.GlyphGroupField);
                    }
                    break;
                }
            }
        }
Beispiel #6
0
        internal static LocationCategory GetFindRefLocations(ExpressionAnalysis analysis) {
            Dictionary<LocationInfo, SimpleLocationInfo> references, definitions, values;
            GetDefsRefsAndValues(analysis, out definitions, out references, out values);

            var locations = new LocationCategory("Find All References",
                    new SymbolList("Definitions", StandardGlyphGroup.GlyphLibrary, definitions.Values),
                    new SymbolList("Values", StandardGlyphGroup.GlyphForwardType, values.Values),
                    new SymbolList("References", StandardGlyphGroup.GlyphReference, references.Values)
                );
            return locations;
        }
Beispiel #7
0
        /// <summary>
        /// Creates an instance of <see cref="CFGAnalysis"/> that can analyse a block.
        /// </summary>
        /// <param name="worklist">The worklist to be used to enqueue next blocks.</param>
        /// <returns>New instance of the flow analyzer.</returns>
        internal static CFGAnalysis Create(Worklist <BoundBlock> worklist, ExpressionAnalysis opvisitor)
        {
            Contract.ThrowIfNull(worklist);

            var analysis = new CFGAnalysis(worklist, opvisitor);

            opvisitor.SetAnalysis(analysis);

            //
            return(analysis);
        }
Beispiel #8
0
 public PreviewChangesEngine(IServiceProvider serviceProvider, IRenameVariableInput input, ExpressionAnalysis analysis, RenameVariableRequest request, string originalName, string privatePrefix, VsProjectAnalyzer analyzer, IEnumerable <IAnalysisVariable> variables)
 {
     _serviceProvider = serviceProvider;
     _analysis        = analysis;
     _analyzer        = analyzer;
     _renameReq       = request;
     _originalName    = originalName;
     _privatePrefix   = privatePrefix;
     _variables       = variables;
     _input           = input;
     _list            = new PreviewList(CreatePreviewItems().ToArray());
 }
 /// <summary>
 /// 获取查询条件
 /// </summary>
 /// <param name="dic"></param>
 /// <returns></returns>
 private Tuple <string, List <SqlParameter> > GetWhere <T>(Expression <Func <T, bool> > exp) where T : BaseModel
 {
     if (exp != null)
     {
         string where = ExpressionAnalysis.GetSql(exp);
         if (!String.IsNullOrWhiteSpace(where))
         {
             where = string.Format(" where 1=1 and {0}", where);
         }
         return(new Tuple <string, List <SqlParameter> >(where, ExpressionAnalysis.GetListParameter()));
     }
     return(new Tuple <string, List <SqlParameter> >("", null));
 }
Beispiel #10
0
        /// <summary>
        /// Opens the find symbols dialog with a list of results.  This is done by requesting
        /// that VS does a search against our library GUID.  Our library then responds to
        /// that request by extracting the prvoided symbol list out and using that for the
        /// search results.
        /// </summary>
        private static void ShowFindSymbolsDialog(ExpressionAnalysis provider, SymbolList symbols)
        {
            // ensure our library is loaded so find all references will go to our library
            Package.GetGlobalService(typeof(IRubyLibraryManager));

            var findSym = (IVsFindSymbol)IronRubyToolsPackage.GetGlobalService(typeof(SVsObjectSearch));
            VSOBSEARCHCRITERIA2 searchCriteria = new VSOBSEARCHCRITERIA2();

            searchCriteria.eSrchType   = VSOBSEARCHTYPE.SO_ENTIREWORD;
            searchCriteria.pIVsNavInfo = symbols;
            searchCriteria.grfOptions  = (uint)_VSOBSEARCHOPTIONS2.VSOBSO_LISTREFERENCES;
            searchCriteria.szName      = provider.Expression;

            Guid guid = Guid.Empty;

            ErrorHandler.ThrowOnFailure(findSym.DoSearch(new Guid(CommonConstants.LibraryGuid), new VSOBSEARCHCRITERIA2[] { searchCriteria }));
        }
Beispiel #11
0
        /// <summary>
        /// Opens the find symbols dialog with a list of results.  This is done by requesting
        /// that VS does a search against our library GUID.  Our library then responds to
        /// that request by extracting the prvoided symbol list out and using that for the
        /// search results.
        /// </summary>
        private void ShowFindSymbolsDialog(ExpressionAnalysis provider, IVsNavInfo symbols) {
            // ensure our library is loaded so find all references will go to our library
            _serviceProvider.GetService(typeof(IPythonLibraryManager));

            if (!string.IsNullOrEmpty(provider.Expression)) {
                var findSym = (IVsFindSymbol)_serviceProvider.GetService(typeof(SVsObjectSearch));
                VSOBSEARCHCRITERIA2 searchCriteria = new VSOBSEARCHCRITERIA2();
                searchCriteria.eSrchType = VSOBSEARCHTYPE.SO_ENTIREWORD;
                searchCriteria.pIVsNavInfo = symbols;
                searchCriteria.grfOptions = (uint)_VSOBSEARCHOPTIONS2.VSOBSO_LISTREFERENCES;
                searchCriteria.szName = provider.Expression;

                Guid guid = Guid.Empty;
                //  new Guid("{a5a527ea-cf0a-4abf-b501-eafe6b3ba5c6}")
                ErrorHandler.ThrowOnFailure(findSym.DoSearch(new Guid(CommonConstants.LibraryGuid), new VSOBSEARCHCRITERIA2[] { searchCriteria }));
            } else {
                var statusBar = (IVsStatusbar)_serviceProvider.GetService(typeof(SVsStatusbar));
                statusBar.SetText("The caret must be on valid expression to find all references.");
            }
        }
        /// <summary>
        /// 修改
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <param name="dic">修改条件(key='字段名',value='字段值')</param>
        /// <returns></returns>
        public int Upd <T>(Expression <Func <T, T> > expCloumn, Expression <Func <T, bool> > expWhere) where T : BaseModel
        {
            if (expCloumn == null || expCloumn.Body == null)
            {
                throw new Exception("未传入修改字段");
            }
            string cloumn = ExpressionAnalysis.GetSql(expCloumn);

            SqlParameter[] list = ExpressionAnalysis.GetListParameter().ToArray();
            if (String.IsNullOrWhiteSpace(cloumn))
            {
                throw new Exception("未传入修改字段");
            }
            string sql = string.Format("update {0} set {1} ", typeof(T).GetTableName(), cloumn);
            Tuple <string, List <SqlParameter> > tu = GetWhere(expWhere);

            sql += tu.Item1;
            List <SqlParameter> list2 = list.Union(tu.Item2.ToArray()).ToList();

            return(helpers.ExexuteSql(sql, list2));
        }
Beispiel #13
0
        private static List <LocationInfo> GetDefinitions(ExpressionAnalysis provider, out StandardGlyphGroup type)
        {
            var vars = provider.Variables;

            ObjectType?finalType = null;

            List <LocationInfo> locations = new List <LocationInfo>();

            foreach (VariableResult result in vars)
            {
                if (finalType == null)
                {
                    finalType = result.Type;
                }
                else if (finalType != result.Type)
                {
                    finalType = ObjectType.Multiple;
                }

                if (result.Location != null)
                {
                    locations.Add(result.Location);
                }
            }

            if (finalType != null)
            {
                type = finalType.Value.ToGlyphGroup();
            }
            else
            {
                type = StandardGlyphGroup.GlyphGroupClass;
            }

            return(locations);
        }
Beispiel #14
0
        /// <summary>
        /// Opens the find symbols dialog with a list of results.  This is done by requesting
        /// that VS does a search against our library GUID.  Our library then responds to
        /// that request by extracting the prvoided symbol list out and using that for the
        /// search results.
        /// </summary>
        private static void ShowFindSymbolsDialog(ExpressionAnalysis provider, params SymbolList[] symbols)
        {
            // ensure our library is loaded so find all references will go to our library
            Package.GetGlobalService(typeof(IPythonLibraryManager));

            if (provider.Expression != "")
            {
                var findSym = (IVsFindSymbol)IronPythonToolsPackage.GetGlobalService(typeof(SVsObjectSearch));
                VSOBSEARCHCRITERIA2 searchCriteria = new VSOBSEARCHCRITERIA2();
                searchCriteria.eSrchType   = VSOBSEARCHTYPE.SO_ENTIREWORD;
                searchCriteria.pIVsNavInfo = symbols.Length == 1 ? (IVsNavInfo)symbols[0] : (IVsNavInfo) new LocationCategory("Test", symbols);
                searchCriteria.grfOptions  = (uint)_VSOBSEARCHOPTIONS2.VSOBSO_LISTREFERENCES;
                searchCriteria.szName      = provider.Expression;

                Guid guid = Guid.Empty;
                //  new Guid("{a5a527ea-cf0a-4abf-b501-eafe6b3ba5c6}")
                ErrorHandler.ThrowOnFailure(findSym.DoSearch(new Guid(CommonConstants.LibraryGuid), new VSOBSEARCHCRITERIA2[] { searchCriteria }));
            }
            else
            {
                var statusBar = (IVsStatusbar)CommonPackage.GetGlobalService(typeof(SVsStatusbar));
                statusBar.SetText("The caret must be on valid expression to find all references.");
            }
        }
Beispiel #15
0
        /// <summary>
        /// Resolves value of the function call in compile time if possible and updates the variable type if necessary
        /// </summary>
        public static void HandleFunctionCall(BoundGlobalFunctionCall call, ExpressionAnalysis analysis, ConditionBranch branch)
        {
            // Only direct function names
            if (!HasSimpleName(call, out string name))
            {
                return;
            }

            // Type checking functions
            if (branch != ConditionBranch.AnyResult && CanBeTypeCheckingFunction(call, name, out var arg))
            {
                if (HandleTypeCheckingFunctions(call, name, arg, analysis, branch))
                {
                    return;
                }
            }

            // Functions with all arguments resolved
            if (call.ArgumentsInSourceOrder.All(a => a.Value.ConstantValue.HasValue))
            {
                // Clear out the constant value result from the previous run of this method (if it was valid, it will be reassigned below)
                call.ConstantValue = default(Optional <object>);

                var args = call.ArgumentsInSourceOrder;
                switch (name)
                {
                // bool function_exists ( string $function_name )
                case "function_exists":
                    if (args.Length == 1)
                    {
                        // TRUE <=> function is defined unconditionally in a reference library (PE assembly)
                        var function_name = args[0].Value.ConstantValue.Value as string;
                        if (function_name != null)
                        {
                            var tmp = analysis.Model.ResolveFunction(NameUtils.MakeQualifiedName(function_name, true));
                            if (tmp is PEMethodSymbol || (tmp is AmbiguousMethodSymbol && ((AmbiguousMethodSymbol)tmp).Ambiguities.All(f => f is PEMethodSymbol)))      // TODO: unconditional declaration ?
                            {
                                call.ConstantValue = ConstantValueExtensions.AsOptional(true);
                                return;
                            }
                        }
                    }
                    break;

                // bool class_exists ( string $class_name [, bool $autoload = true ] )
                case "class_exists":
                    if (args.Length >= 1)
                    {
                        // TRUE <=> class is defined unconditionally in a reference library (PE assembly)
                        var class_name = args[0].Value.ConstantValue.Value as string;
                        if (class_name != null)
                        {
                            var tmp = analysis.Model.GetType(NameUtils.MakeQualifiedName(class_name, true));
                            if (tmp is PENamedTypeSymbol)       // TODO: unconditional declaration ?
                            {
                                call.ConstantValue = ConstantValueExtensions.AsOptional(true);
                                return;
                            }
                        }
                    }
                    break;

                // bool method_exists ( string $class_name , string $method_name )
                case "method_exists":
                    if (args.Length == 2)
                    {
                        var class_name    = args[0].Value.ConstantValue.Value as string;
                        var function_name = args[1].Value.ConstantValue.Value as string;
                        if (class_name != null && function_name != null)
                        {
                            var tmp = (NamedTypeSymbol)analysis.Model.GetType(NameUtils.MakeQualifiedName(class_name, true));
                            if (tmp is PENamedTypeSymbol)
                            {
                                if (tmp.LookupMethods(function_name).Any())
                                {
                                    call.ConstantValue = ConstantValueExtensions.AsOptional(true);
                                    return;
                                }
                            }
                        }
                    }
                    break;
                }
            }
        }
Beispiel #16
0
            public void RunHeapAndExpressionAnalyses(DFAController controller)
            {
                if (optimisticHeapAnalysis != null)
                {
                    return;
                }

                optimisticHeapAnalysis = new OptimisticHeapAnalyzer <Local, Parameter, Method, Field, Property, Event, Type, Attribute, Assembly>(this.StackLayer, this.Options.TraceEGraph);
                optimisticHeapAnalysis.TurnArgumentExceptionThrowsIntoAssertFalse = this.Options.TurnArgumentExceptionThrowsIntoAssertFalse;
                optimisticHeapAnalysis.IgnoreExplicitAssumptions = this.Options.IgnoreExplicitAssumptions;
                optimisticHeapAnalysis.TraceAssumptions          = this.Options.TraceAssumptions;
                var heapsolver = this.StackLayer.CreateForward(optimisticHeapAnalysis,
                                                               new DFAOptions {
                    Trace = this.Options.TraceHeapAnalysis
                }, controller);

                heapsolver(optimisticHeapAnalysis.InitialValue());

                this.ValueLayer = CodeLayerFactory.Create(optimisticHeapAnalysis.GetDecoder(this.StackLayer.Decoder),
                                                          this.StackLayer.MetaDataDecoder,
                                                          this.StackLayer.ContractDecoder,
                                                          delegate(SymbolicValue source) { return(source.ToString()); },
                                                          delegate(SymbolicValue dest) { return(dest.ToString()); },
                                                          (v1, v2) => v1.symbol.GlobalId > v2.symbol.GlobalId
                                                          );

                if (this.PrintIL)
                {
                    Console.WriteLine("-----------------Value based CFG---------------------");
                    this.ValueLayer.Decoder.Context.MethodContext.CFG.Print(Console.Out, this.ValueLayer.Printer, optimisticHeapAnalysis.GetEdgePrinter(),
                                                                            (block) => optimisticHeapAnalysis.GetContexts(block),
                                                                            null);
                }
                var exprAnalysis = new ExpressionAnalysis <Local, Parameter, Method, Field, Property, Event, Type, Attribute, Assembly, SymbolicValue, IValueContext <Local, Parameter, Method, Field, Type, SymbolicValue>, EdgeData>(
                    this.ValueLayer,
                    this.Options,
                    optimisticHeapAnalysis.IsUnreachable
                    );
                var exprsolver = this.ValueLayer.CreateForward(exprAnalysis.CreateExpressionAnalyzer(),
                                                               new DFAOptions {
                    Trace = this.Options.TraceExpressionAnalysis
                }, controller);

                exprsolver(exprAnalysis.InitialValue(SymbolicValue.GetUniqueKey));

                var exprDecoder = exprAnalysis.GetDecoder(this.ValueLayer.Decoder);

                expr2String = ExprPrinter.Printer(exprDecoder.Context, this);

                this.ExpressionLayer = CodeLayerFactory.Create(
                    exprDecoder,
                    this.ValueLayer.MetaDataDecoder,
                    this.ValueLayer.ContractDecoder,
                    expr2String,
                    this.ValueLayer.VariableToString,
                    (v1, v2) => v1.symbol.GlobalId > v2.symbol.GlobalId
                    );


                if (this.PrintIL)
                {
                    Console.WriteLine("-----------------Expression based CFG---------------------");
                    this.ExpressionLayer.Decoder.Context.MethodContext.CFG.Print(Console.Out, this.ExpressionLayer.Printer, exprAnalysis.GetBlockPrinter(expr2String),
                                                                                 (block) => exprAnalysis.GetContexts(block),
                                                                                 null);
                }

                this.HybridLayer = CodeLayerFactory.Create(
                    this.ValueLayer.Decoder,
                    this.ValueLayer.MetaDataDecoder,
                    this.ValueLayer.ContractDecoder,
                    this.ValueLayer.ExpressionToString,
                    this.ValueLayer.VariableToString,
                    this.ExpressionLayer.Printer,
                    this.ExpressionLayer.NewerThan
                    );

                if (Options.TraceAssumptions)
                {
                    #region Produce trace output to extract implicit assumptions. Please don't remove this code!

                    Console.WriteLine("<assumptions>");
                    Console.WriteLine(@"<subroutine id=""{0}"" methodName=""{1}"">", HybridLayer.Decoder.Context.MethodContext.CFG.Subroutine.Id, HybridLayer.Decoder.Context.MethodContext.CFG.Subroutine.Name);

                    foreach (var b in HybridLayer.Decoder.Context.MethodContext.CFG.Subroutine.Blocks)
                    {
                        Console.WriteLine(@"<block index=""{0}"">", b.Index);

                        foreach (var apc in b.APCs())
                        {
                            Console.WriteLine(@"<apc name=""{0}"" index=""{1}"" ilOffset=""{2}"" primarySourceContext=""{3}"" sourceContext=""{4}"">",
                                              apc.ToString(), apc.Index, apc.ILOffset, apc.PrimarySourceContext(), HybridLayer.Decoder.Context.MethodContext.SourceContext(apc));

                            Console.WriteLine("<code>");
                            HybridLayer.Printer(apc, "", Console.Out);
                            Console.WriteLine("</code>");

                            optimisticHeapAnalysis.Dump(apc);

                            Console.WriteLine("</apc>");
                        }

                        Console.WriteLine("</block>");
                    }

                    Console.WriteLine("</subroutine>");
                    Console.WriteLine("</assumptions>");

                    #endregion
                }
                ModifiedAtCall = optimisticHeapAnalysis.ModifiedAtCall;
            }
Beispiel #17
0
        /// <summary>
        /// Resolves value of the function call in compile time if possible and updates the variable type if necessary
        /// </summary>
        public static void HandleSpecialFunctionCall(BoundGlobalFunctionCall call, ExpressionAnalysis analysis, ConditionBranch branch)
        {
            // Only direct function names
            if (!HasSimpleName(call, out string name))
            {
                return;
            }

            // Type checking functions
            if (branch != ConditionBranch.AnyResult && CanBeTypeCheckingFunction(call, name, out var arg))
            {
                if (HandleTypeCheckingFunctions(call, name, arg, analysis, branch))
                {
                    return;
                }
            }

            // Functions with all arguments resolved
            if (call.ArgumentsInSourceOrder.All(a => a.Value.ConstantValue.HasValue))
            {
                // Clear out the constant value result from the previous run of this method (if it was valid, it will be reassigned below)
                call.ConstantValue = default(Optional <object>);

                string str;

                var args = call.ArgumentsInSourceOrder;
                switch (name)
                {
                case "is_callable":         // bool is_callable( string $function_name )
                case "function_exists":     // bool function_exists ( string $function_name )
                    if (args.Length == 1 && args[0].Value.ConstantValue.TryConvertToString(out str))
                    {
                        // TRUE <=> function is defined unconditionally in a reference library (PE assembly)
                        var tmp = analysis.Model.ResolveFunction(NameUtils.MakeQualifiedName(str, true));
                        if (tmp is PEMethodSymbol || (tmp is AmbiguousMethodSymbol && ((AmbiguousMethodSymbol)tmp).Ambiguities.All(f => f is PEMethodSymbol)))      // TODO: unconditional declaration ?
                        {
                            call.ConstantValue = ConstantValueExtensions.AsOptional(true);
                            return;
                        }
                    }
                    break;

                // bool class_exists ( string $class_name [, bool $autoload = true ] )
                case "class_exists":
                    if (args.Length >= 1)
                    {
                        // TRUE <=> class is defined unconditionally in a reference library (PE assembly)
                        var class_name = args[0].Value.ConstantValue.Value as string;
                        if (class_name != null)
                        {
                            var tmp = analysis.Model.ResolveType(NameUtils.MakeQualifiedName(class_name, true));
                            if (tmp is PENamedTypeSymbol)       // TODO: unconditional declaration ?
                            {
                                call.ConstantValue = ConstantValueExtensions.AsOptional(true);
                                return;
                            }
                        }
                    }
                    break;

                // bool method_exists ( string $class_name , string $method_name )
                case "method_exists":
                    if (args.Length == 2)
                    {
                        var class_name = args[0].Value.ConstantValue.Value as string;
                        if (class_name != null && args[1].Value.ConstantValue.TryConvertToString(out str))
                        {
                            var tmp = (NamedTypeSymbol)analysis.Model.ResolveType(NameUtils.MakeQualifiedName(class_name, true));
                            if (tmp is PENamedTypeSymbol)
                            {
                                if (tmp.LookupMethods(str).Any())
                                {
                                    call.ConstantValue = ConstantValueExtensions.AsOptional(true);
                                    return;
                                }
                            }
                        }
                    }
                    break;

                case "extension_loaded":        // bool extension_loaded(name)
                    if (args.Length == 1 && args[0].Value.ConstantValue.TryConvertToString(out str))
                    {
                        if (analysis.Model.Extensions.Contains(str, StringComparer.OrdinalIgnoreCase))
                        {
                            call.ConstantValue = ConstantValueExtensions.AsOptional(true);
                            return;
                        }
                    }
                    break;

                case "defined":
                case "constant":
                    if (args.Length == 1 && args[0].Value.ConstantValue.TryConvertToString(out str))
                    {
                        // TODO: const_name in form of "{CLASS}::{NAME}"
                        var tmp = analysis.Model.ResolveConstant(str);
                        if (tmp is PEFieldSymbol symbol)        // TODO: also user constants defined in the same scope
                        {
                            if (name == "defined")
                            {
                                call.ConstantValue = ConstantValueExtensions.AsOptional(true);
                            }
                            else     // name == "constant"
                            {
                                var cvalue = symbol.GetConstantValue(false);
                                call.ConstantValue = (cvalue != null) ? new Optional <object>(cvalue.Value) : null;
                                call.TypeRefMask   = TypeRefFactory.CreateMask(analysis.TypeCtx, symbol.Type);
                            }

                            return;
                        }
                    }
                    break;

                case "strlen":
                    if (args.Length == 1 && args[0].Value.ConstantValue.TryConvertToString(out string value))
                    {
                        call.ConstantValue = new Optional <object>(value.Length);
                    }
                    return;
                }
            }
        }
Beispiel #18
0
        /// <summary>
        /// Processes functions such as is_int, is_bool etc. Returns whether the function was one of these.
        /// </summary>
        private static bool HandleTypeCheckingFunctions(
            BoundGlobalFunctionCall call,
            string name,
            BoundVariableRef arg,
            ExpressionAnalysis analysis,
            ConditionBranch branch)
        {
            var typeCtx   = analysis.TypeCtx;
            var flowState = analysis.State;

            switch (name)
            {
            case "is_int":
            case "is_integer":
            case "is_long":
                HandleTypeCheckingExpression(arg, typeCtx.GetLongTypeMask(), branch, flowState, checkExpr: call);
                return(true);

            case "is_bool":
                HandleTypeCheckingExpression(arg, typeCtx.GetBooleanTypeMask(), branch, flowState, checkExpr: call);
                return(true);

            case "is_float":
            case "is_double":
            case "is_real":
                HandleTypeCheckingExpression(arg, typeCtx.GetDoubleTypeMask(), branch, flowState, checkExpr: call);
                return(true);

            case "is_string":
                var stringMask = typeCtx.GetStringTypeMask() | typeCtx.GetWritableStringTypeMask();
                HandleTypeCheckingExpression(arg, stringMask, branch, flowState, checkExpr: call);
                return(true);

            case "is_resource":
                HandleTypeCheckingExpression(arg, typeCtx.GetResourceTypeMask(), branch, flowState, checkExpr: call);
                return(true);

            case "is_null":
                HandleTypeCheckingExpression(arg, typeCtx.GetNullTypeMask(), branch, flowState, checkExpr: call);
                return(true);

            case "is_array":
                HandleTypeCheckingExpression(
                    arg,
                    currentType => typeCtx.GetArraysFromMask(currentType),
                    branch,
                    flowState,
                    skipPositiveIfAnyType: true,
                    checkExpr: call);
                return(true);

            case "is_object":
                // Keep IncludesSubclasses flag in the true branch and clear it in the false branch
                HandleTypeCheckingExpression(
                    arg,
                    currentType => typeCtx.GetObjectsFromMask(currentType).WithIncludesSubclasses,
                    branch,
                    flowState,
                    skipPositiveIfAnyType: true,
                    checkExpr: call);
                return(true);

            // TODO
            //case "is_scalar":
            //    return;

            case "is_numeric":
                HandleTypeCheckingExpression(
                    arg,
                    currentType =>
                {
                    // Specify numeric types if they are present
                    var targetType = typeCtx.IsLong(currentType) ? typeCtx.GetLongTypeMask() : 0;
                    targetType    |= typeCtx.IsDouble(currentType) ? typeCtx.GetDoubleTypeMask() : 0;

                    if (branch == ConditionBranch.ToTrue)
                    {
                        // Also string types can make is_numeric return true, but not anything else
                        targetType |= typeCtx.IsReadonlyString(currentType) ? typeCtx.GetStringTypeMask() : 0;
                        targetType |= typeCtx.IsWritableString(currentType) ? typeCtx.GetWritableStringTypeMask() : 0;

                        return(targetType);
                    }
                    else
                    {
                        // For number, is_numeric always returns true -> remove numeric types from false branch
                        return(targetType);
                    }
                },
                    branch,
                    flowState,
                    skipPositiveIfAnyType: true,
                    checkExpr: call);
                return(true);

            case "is_callable":
                HandleTypeCheckingExpression(
                    arg,
                    currentType =>
                {
                    // Closure is specified in both branches
                    TypeRefMask targetType = 0;
                    AddTypeIfInContext(typeCtx, type => type.IsLambda, false, ref targetType);

                    if (branch == ConditionBranch.ToTrue)
                    {
                        // Also string types, arrays and objects can make is_callable return true, but not anything else
                        targetType |= typeCtx.IsReadonlyString(currentType) ? typeCtx.GetStringTypeMask() : 0;
                        targetType |= typeCtx.IsWritableString(currentType) ? typeCtx.GetWritableStringTypeMask() : 0;
                        targetType |= typeCtx.GetArraysFromMask(currentType);
                        targetType |= typeCtx.GetObjectsFromMask(currentType);

                        return(targetType);
                    }
                    else
                    {
                        // For closure, is_callable always returns true -> remove the closure type from false branch,
                        // don't remove IncludeSubclasses flag
                        return(targetType);
                    }
                },
                    branch,
                    flowState,
                    skipPositiveIfAnyType: true,
                    checkExpr: call);
                return(true);

            // TODO
            //case "is_iterable":
            //    return;

            default:
                return(false);
            }
        }
Beispiel #19
0
        /// <summary>
        /// Resolves value of the function call in compile time if possible and updates the variable type if necessary
        /// </summary>
        public static void HandleSpecialFunctionCall <T>(BoundGlobalFunctionCall call, ExpressionAnalysis <T> analysis, ConditionBranch branch)
        {
            // Only direct function names
            if (!HasSimpleName(call, out string name))
            {
                return;
            }

            // Type checking functions
            if (branch != ConditionBranch.AnyResult && CanBeTypeCheckingFunction(call, name, out var arg))
            {
                if (HandleTypeCheckingFunctions(call, name, arg, analysis, branch))
                {
                    return;
                }
            }

            var args = call.ArgumentsInSourceOrder;

            // Clear out the constant value result from the previous run of this method (if it was valid, it will be reassigned below)
            call.ConstantValue = default;

            string str;

            switch (name)           // TODO: case insensitive
            {
            case "is_callable":     // bool is_callable( string $function_name )
            case "function_exists": // bool function_exists ( string $function_name )
                if (args.Length == 1 && args[0].Value.ConstantValue.TryConvertToString(out str))
                {
                    // TRUE <=> function is defined unconditionally in a reference library (PE assembly)
                    if (IsUnconditionalDeclaration(analysis.Model.ResolveFunction(NameUtils.MakeQualifiedName(str, true))))
                    {
                        call.ConstantValue = ConstantValueExtensions.AsOptional(true);
                    }
                }
                break;

            // bool class_exists ( string $class_name [, bool $autoload = true ] )
            case "class_exists":
            case "interface_exists":
                if (args.Length >= 1)
                {
                    // TRUE <=> class is defined unconditionally in a reference library (PE assembly)
                    var class_name = args[0].Value.ConstantValue.Value as string;
                    if (!string.IsNullOrEmpty(class_name))
                    {
                        var tmp = (TypeSymbol)analysis.Model.ResolveType(NameUtils.MakeQualifiedName(class_name, true));
                        if (tmp is PENamedTypeSymbol && !tmp.IsPhpUserType())       // TODO: + SourceTypeSymbol when reachable unconditional declaration
                        {
                            bool @interface = (name == "interface_exists");
                            if (tmp.TypeKind == (@interface ? TypeKind.Interface : TypeKind.Class))
                            {
                                call.ConstantValue = ConstantValueExtensions.AsOptional(true);
                            }
                        }
                    }
                }
                break;

            // bool method_exists ( string $class_name , string $method_name )
            case "method_exists":
                if (args.Length == 2)
                {
                    var class_name = args[0].Value.ConstantValue.Value as string;
                    if (class_name != null && args[1].Value.ConstantValue.TryConvertToString(out str))
                    {
                        var tmp = (NamedTypeSymbol)analysis.Model.ResolveType(NameUtils.MakeQualifiedName(class_name, true));
                        if (tmp is PENamedTypeSymbol && !tmp.IsPhpUserType())
                        {
                            if (tmp.LookupMethods(str).Count != 0)     // TODO: why not User Types // TODO: why not resolve FALSE as well below?
                            {
                                call.ConstantValue = ConstantValueExtensions.AsOptional(true);
                            }
                        }
                    }
                }
                break;

            case "defined":         // defined(CONST_NAME)
            case "constant":        // constant(CONST_NAME)
                if (args.Length == 1 && args[0].Value.ConstantValue.TryConvertToString(out str))
                {
                    // TODO: const_name in form of "{CLASS}::{NAME}"
                    // TODO: also user constants defined in the same scope?

                    // quick evaluation of PE constants that can't be changed at run time

                    var tmp = analysis.Model.ResolveConstant(str);
                    if (tmp is PEFieldSymbol fld)
                    {
                        if (name == "defined")
                        {
                            call.ConstantValue = ConstantValueExtensions.AsOptional(true);
                        }
                        else     // name == "constant"
                        {
                            if (fld.Type.Is_Func_Context_TResult(out var tresult))
                            {
                                call.TypeRefMask = TypeRefFactory.CreateMask(analysis.TypeCtx, tresult);
                            }
                            else
                            {
                                var cvalue = fld.GetConstantValue(false);
                                call.ConstantValue = (cvalue != null) ? new Optional <object>(cvalue.Value) : null;
                                call.TypeRefMask   = TypeRefFactory.CreateMask(analysis.TypeCtx, fld.Type, notNull: fld.IsNotNull());
                            }
                        }
                    }
                    else if (tmp is PEPropertySymbol prop)
                    {
                        if (name == "defined")
                        {
                            call.ConstantValue = ConstantValueExtensions.AsOptional(true);
                        }
                        else     // name == "constant"
                        {
                            call.TypeRefMask = TypeRefFactory.CreateMask(analysis.TypeCtx, prop.Type, notNull: prop.IsNotNull());
                        }
                    }
                }
                break;

            case "strlen":
                if (args.Length == 1 && args[0].Value.ConstantValue.TryConvertToString(out string value))
                {
                    call.ConstantValue = new Optional <object>(value.Length);
                }
                break;

            case "file_exists":
                if (args.Length == 1)
                {
                    if (TryResolveFile(analysis.Model, analysis.Routine, args[0].Value, out var script))
                    {
                        // there is compiled script at this path,
                        // the expression will be always true
                        call.ConstantValue = true.AsOptional();
                    }
                }
                break;
            }
        }
 public ExpressionTranslation(Expression expression, TranslationSettings settings)
 {
     _settings           = settings;
     _expressionAnalysis = ExpressionAnalysis.For(expression, settings);
     _root = GetTranslationFor(expression);
 }