Beispiel #1
0
            void IOutput.Suggestion(string kind, APC pc, string suggestion, List <uint> causes)
            {
                var msg = String.Format("Suggestion: {0}", suggestion);

                // TODO: It would be better to have a different way to tell the issue provider
                // that this issue is related to the method as a whole and not any particular
                // location so that it could decide on what span to attach the issue to.
                var startIndex = 0;
                var length     = 0;
                MethodReferenceAdaptor meth;
                var ok = pc.TryGetContainingMethod(out meth);

                if (ok && IteratorHelper.EnumerableIsNotEmpty(meth.reference.Locations))
                {
                    var l = IteratorHelper.First(meth.reference.Locations) as ISourceLocation;
                    if (l != null)
                    {
                        startIndex = l.StartIndex;
                        length     = l.Length;
                    }
                }
                this.results.Add(Tuple.Create(msg, new TextSpan(startIndex, length)));
            }
Beispiel #2
0
        private bool RemapParameterToLoadStack(APC pc, ref Parameter param, out bool isLoadResult, out int loadStackOffset, out bool isOld, out APC lookupPC)
        {
            if (pc.SubroutineContext == null)
            {
                isLoadResult    = false;
                loadStackOffset = 0;
                isOld           = false;
                lookupPC        = pc;
                return(false);
            }

            if (pc.Block.Subroutine.IsRequires)
            {
                isLoadResult = false;
                isOld        = false;
                lookupPC     = pc;
                for (LispList <Edge <CFGBlock, EdgeTag> > list = pc.SubroutineContext; list != null; list = list.Tail)
                {
                    EdgeTag edgeTag = list.Head.Tag;
                    if (edgeTag == EdgeTag.Entry)
                    {
                        param           = RemapParameter(param, list.Head.From, pc.Block);
                        loadStackOffset = 0;
                        return(false);
                    }
                    if (edgeTag.Is(EdgeTag.BeforeMask))
                    {
                        int stackDepth = this.parent.LocalStackDepth(pc);
                        loadStackOffset = this.parent.MetaDataProvider.ParameterStackIndex(param) + stackDepth;
                        return(true);
                    }
                }
                throw new InvalidOperationException();
            }

            if (pc.Block.Subroutine.IsEnsuresOrOldValue)
            {
                isOld = true;
                for (LispList <Edge <CFGBlock, EdgeTag> > ctx = pc.SubroutineContext; ctx != null; ctx = ctx.Tail)
                {
                    EdgeTag tag = ctx.Head.Tag;
                    if (tag == EdgeTag.Exit)
                    {
                        param           = RemapParameter(param, ctx.Head.From, pc.Block);
                        isLoadResult    = false;
                        loadStackOffset = 0;
                        lookupPC        = pc;
                        return(false);
                    }

                    if (tag == EdgeTag.AfterCall)
                    {
                        loadStackOffset = this.parent.MetaDataProvider.ParameterStackIndex(param);
                        isLoadResult    = false;
                        lookupPC        = new APC(ctx.Head.From, 0, ctx.Tail);
                        return(true);
                    }

                    if (tag == EdgeTag.AfterNewObj)
                    {
                        if (this.parent.MetaDataProvider.ParameterIndex(param) == 0)
                        {
                            loadStackOffset = this.parent.LocalStackDepth(pc);
                            isLoadResult    = true;
                            lookupPC        = pc;
                            isOld           = false;
                            return(false);
                        }

                        loadStackOffset = this.parent.MetaDataProvider.ParameterIndex(param);
                        isLoadResult    = false;
                        lookupPC        = new APC(ctx.Head.From, 0, ctx.Tail);
                        return(true);
                    }
                    if (tag == EdgeTag.OldManifest)
                    {
                        param           = RemapParameter(param, ctx.Tail.Head.From, pc.Block);
                        isOld           = false;
                        isLoadResult    = false;
                        loadStackOffset = 0;
                        lookupPC        = pc;
                        return(false);
                    }
                }
                throw new InvalidOperationException();
            }

            if (pc.Block.Subroutine.IsInvariant)
            {
                for (LispList <Edge <CFGBlock, EdgeTag> > list = pc.SubroutineContext; list != null; list = list.Tail)
                {
                    EdgeTag tag = list.Head.Tag;
                    if (tag == EdgeTag.Entry || tag == EdgeTag.Exit)
                    {
                        Method method;
                        if (pc.TryGetContainingMethod(out method))
                        {
                            param           = this.parent.MetaDataProvider.This(method);
                            isLoadResult    = false;
                            loadStackOffset = 0;
                            isOld           = tag == EdgeTag.Exit;
                            lookupPC        = pc;
                            return(false);
                        }
                        isLoadResult    = false;
                        loadStackOffset = 0;
                        isOld           = false;
                        lookupPC        = pc;
                        return(false);
                    }
                    if (tag == EdgeTag.AfterCall)
                    {
                        Method calledMethod;
                        bool   isNewObj;
                        bool   isVirtual;
                        list.Head.From.IsMethodCallBlock(out calledMethod, out isNewObj, out isVirtual);
                        int count = this.parent.MetaDataProvider.Parameters(calledMethod).Count;
                        loadStackOffset = count;
                        isLoadResult    = false;
                        isOld           = true;
                        lookupPC        = new APC(list.Head.From, 0, list.Tail);
                        return(true);
                    }
                    if (tag == EdgeTag.AfterNewObj)
                    {
                        isLoadResult    = true;
                        loadStackOffset = this.parent.LocalStackDepth(pc);
                        isOld           = false;
                        lookupPC        = pc;
                        return(false);
                    }
                    if (tag.Is(EdgeTag.BeforeMask))
                    {
                        throw new InvalidOperationException("this should never happen");
                    }
                }
                throw new InvalidOperationException("this should never happen");
            }

            isLoadResult    = false;
            loadStackOffset = 0;
            isOld           = false;
            lookupPC        = pc;
            return(false);
        }
Beispiel #3
0
            void IOutput.Suggestion(string kind, APC pc, string suggestion, List <uint> causes)
            {
                var isExtractMethodSuggestion = kind.Contains("for the extracted method");
                var isInvariantAtSuggestion   = kind.Contains("abstract state");

                Contract.Assert(!isExtractMethodSuggestion || isExtractMethodSuggestion != isInvariantAtSuggestion);

                var extraInfo = ClousotOutput.ExtraInfo.None;

                if (isExtractMethodSuggestion)
                {
                    extraInfo = ClousotOutput.ExtraInfo.IsExtractMethodSuggestion;
                }
                if (isInvariantAtSuggestion)
                {
                    extraInfo = ClousotOutput.ExtraInfo.IsInvariantAtSuggestion;
                }

                var msg = String.Format("Suggestion: {0}", suggestion);

                if (kind.Contains("Code fix") && pc.HasRealSourceContext)
                {
                    var si       = pc.Block.SourceStartIndex(pc);
                    var l        = pc.Block.SourceLength(pc);
                    var fixIndex = suggestion.IndexOf("Fix:");
                    if (fixIndex == -1)
                    { // TODO: cater to other kinds of fixes (adds, delete)
                        return;
                    }
                    var newText = suggestion.Substring(fixIndex + 5);
                    var sp      = new TextSpan(si, l);
                    var a       = new CodeFix(this.document, sp, newText);
                    this.results.Add(new ClousotOutput(null /* no outcome */, msg, new TextSpan(si, l), null, a, ClousotOutput.ExtraInfo.None));

                    return;
                }

                // TODO: It would be better to have a different way to tell the issue provider
                // that this issue is related to the method as a whole and not any particular
                // location so that it could decide on what span to attach the issue to.
                var startIndex = 0;
                var length     = 0;
                MethodReferenceAdaptor meth;
                var ok = pc.TryGetContainingMethod(out meth);

                if (ok && IteratorHelper.EnumerableIsNotEmpty(meth.reference.Locations))
                {
                    var l = IteratorHelper.First(meth.reference.Locations) as ISourceLocation;
                    if (l != null)
                    {
                        startIndex = l.StartIndex;
                        length     = l.Length;
                    }
                }
                var span           = new TextSpan(startIndex, length); // should be the span of the method name
                var st             = this.document.GetSyntaxTree();
                var roslynLocation = st.GetLocation(span);
                BaseMethodDeclarationSyntax method;

                if (this.span2Method.TryGetValue(span, out method))
                {
                    if (!isExtractMethodSuggestion && !isInvariantAtSuggestion)
                    {
                        if (method.ContainsSuggestion(suggestion))
                        {
                            return;
                        }

                        var action = new ContractInjector(this.document, kind.ToContractKind(), suggestion, method);
                        this.results.Add(new ClousotOutput(null /* no outcome */, msg, span, null, (ICodeAction)action, extraInfo));
                    }
                    else
                    {
                        this.results.Add(new ClousotOutput(null /* no outcome */, msg, span, null, (ICodeAction)null, extraInfo));
                    }
                }
                else
                {
                    this.results.Add(new ClousotOutput(null /* no outcome */, msg, span, null, (ICodeAction)null, extraInfo));
                }
            }