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