예제 #1
0
 //public UnresolvedInterfaceAnnotation(
 //                            CCCheckExtraInfo extra_info,
 //                            Squiggle squiggle,
 //                            ClousotSuggestion.Kind kind)
 // : base(null, null, extra_info.SuggestedCode, squiggle, kind)
 //{
 //  // TODO there are ways this can fail to create a valid annotation
 //  // there is a lot of string parsing going on that could go wrong
 //  // could be refactored into a TryXXXX?
 //  //this.extraInfo = extra_info;
 //  this.InterfaceMethod = extra_info.CalleeDocumentId;
 //  this.InterfaceName = extra_info.TypeDocumentId;
 //  if (InterfaceName.Contains('<'))
 //  {
 //    var lastAngle = InterfaceName.LastIndexOf('<');
 //    var beforeAngle = InterfaceName.Remove(lastAngle);
 //    var afterAngle = InterfaceName.Replace(beforeAngle, "");
 //    InterfaceName = beforeAngle;
 //    var parts = afterAngle.Trim('<', '>').Split(',');
 //    NumberParameters = parts.Count();
 //    ParametersString = "<" + parts[0].Replace("type parameter.", "");
 //    for (int i = 1; i < parts.Length; i++)
 //    {
 //      ParametersString += ',' + parts[i].Replace("type parameter.", "");
 //    }
 //    ParametersString += ">";
 //  }
 //  this.InterfaceShortName = InterfaceAnnotationHelpers.GetUnqualifiedName(InterfaceName);
 //}
 public UnresolvedInterfaceAnnotation(string annotation, Squiggle squiggle, ClousotSuggestion.Kind kind, string parameterstring, string interfacename, string interfacemethod)
     : base(null, null, annotation, squiggle, kind)
 {
     this.ParametersString   = parameterstring;
     this.InterfaceName      = interfacename;
     this.InterfaceMethod    = interfacemethod;
     this.InterfaceShortName = InterfaceAnnotationHelpers.GetUnqualifiedName(interfacename);
 }
예제 #2
0
        private static Compilation ImplementContractsClass(Project project, Compilation original, string filename, string interfacename, string contractname)
        {
            #region CodeContracts
            Contract.Requires(project != null);
            Contract.Requires(original != null);
            Contract.Requires(filename != null);
            Contract.Requires(interfacename != null);
            Contract.Requires(contractname != null);
            Contract.Ensures(Contract.Result <Compilation>() != null);
            #endregion CodeContracts

            var interfaceShortName = InterfaceAnnotationHelpers.GetUnqualifiedName(interfacename);
            var doc     = project.Documents.First(x => x.FilePath.Equals(filename, StringComparison.OrdinalIgnoreCase));
            var orig_st = original.SyntaxTrees.First(x => x.FilePath.Equals(filename, StringComparison.OrdinalIgnoreCase));
            doc = doc.WithSyntaxRoot(orig_st.GetRoot());
            var st = doc.GetSyntaxTreeAsync().Result;
            Contract.Assert(st != null);
            //var st = CSharpSyntaxTree.Create(doc.GetSyntaxRootAsync().Result as CSharpSyntaxNode, orig_st.FilePath, null);
            var newcomp = original.ReplaceSyntaxTree(orig_st, st);
            var sm      = newcomp.GetSemanticModel(st);
            //Console.WriteLine(doc.GetTextAsync().Result);
            var classes = st.GetRoot().DescendantNodesAndSelf().Where(x => x.CSharpKind().Equals(SyntaxKind.ClassDeclaration));
            var node    = classes.First(x => sm.GetDeclaredSymbol(x).GetDocumentationCommentId().Equals(contractname));
            //var node = st.GetRoot().DescendantNodesAndSelf().First(x => x.CSharpKind().Equals(SyntaxKind.ClassDeclaration)
            //                                                        && sm.GetDeclaredSymbol(x).GetDocumentationCommentId().Equals(contractname));
            var baselist = node.DescendantNodes().First(x => x.CSharpKind().Equals(SyntaxKind.BaseList));
            var inode    = baselist.DescendantTokens().First(x => x.Text.Equals(interfaceShortName));
            //var assembly = Assembly.LoadFrom(@"C:\cci\Microsoft.Research\Imported\Tools\Roslyn\v4.5.1\Microsoft.CodeAnalysis.CSharp.Features.dll");
            //var assembly = Assembly.LoadFrom(@"C:\Users\t-scottc\Desktop\Signed_20140201.1\Microsoft.CodeAnalysis.CSharp.Features.dll");
            //var assembly = Assembly.LoadFrom(@"C:\cci\Microsoft.Research\CCTools\ReviewBot\bin\Debug\Microsoft.CodeAnalysis.CSharp.Features.dll");
            Assembly assembly;

            if (UsingHelpers.TryGetMicrosoftCodeAnalysisCSharpFeatures(out assembly))
            {
                try
                {
                    var type    = assembly.GetType("Microsoft.CodeAnalysis.CSharp.ImplementInterface.CSharpImplementInterfaceService");
                    var method  = type.GetMethod("ImplementInterfaceAsync");
                    var service = Activator.CreateInstance(type);
                    var result  = method.Invoke(service, new object[] { doc, inode.Parent, CancellationToken.None }) as Task <Document>;
                    var newdoc  = result.Result;

                    return(newcomp.ReplaceSyntaxTree(st, newdoc.GetSyntaxTreeAsync().Result));
                }
                catch (Exception e)
                {
                    Output.WriteWarning("Something went wrong while trying to invoke Roslyn refactoring engine. Details: {0}", e.Message);
                    Output.WriteLine("We continue skipping this interface");
                    return(original);
                }
            }
            else
            {
                Output.WriteWarning("Can't add the interface contract to {0} as we failed loading the Roslyn refactoring engine", interfacename);
                return(original);
            }
        }
예제 #3
0
        private static SyntaxNode MakeContractsClassForNode(string interfacename, string parameters)
        {
            string intRawName   = InterfaceAnnotationHelpers.GetUnqualifiedName(interfacename);
            string intName      = InterfaceAnnotationHelpers.GetUnqualifiedName(interfacename);
            var    numberparams = GetNumberParameters(parameters);

            //string contractParams = "";
            //var IsInterfaceParameterized = interfacename.Contains('`');
            //if (IsInterfaceParameterized)
            if (numberparams > 0)
            {
                //var tickIndex = interfacename.LastIndexOf('`') + 1;
                //var afterTick = interfacename.Replace(interfacename.Remove(tickIndex), "");
                //var numberParameters = int.Parse(afterTick);
                intName += '<';
                for (int i = 1; i < numberparams; i++)
                {
                    intName += ',';
                }
                intName += '>';

                //contractParams += "<T";
                //for (int i = 1; i < numberParameters; i++)
                //{
                //contractParams += ",T" + i;
                //}
                //contractParams += '>';
            }
            var text = String.Format(@"
using System; 
[ContractClassFor(typeof({0}))]
internal abstract class {1}Contracts{2} : {1}{2} 
{{
}}"
                                     , intName, intRawName, parameters);
            var parsed = SyntaxFactory.ParseCompilationUnit(text);

            return(parsed.SyntaxTree.GetRoot().DescendantNodesAndSelf().OfType <ClassDeclarationSyntax>().First());
        }
예제 #4
0
        private static Compilation AddContractsClassAttributeToInterface(Project project, Compilation original, string filename, string interfacename, string parameterstring)
        {
            #region CodeContracts
            Contract.Requires(project != null);
            Contract.Requires(original != null);
            Contract.Requires(filename != null);
            Contract.Requires(interfacename != null);
            Contract.Ensures(Contract.Result <Compilation>() != null);
            #endregion CodeContracts

            var interfaceShortName = InterfaceAnnotationHelpers.GetUnqualifiedName(interfacename);
            var st   = original.SyntaxTrees.Where(x => x.FilePath.Equals(filename, StringComparison.OrdinalIgnoreCase)).First();
            var doc  = project.GetDocument(st);
            var sm   = original.GetSemanticModel(st);
            var node = st.GetRoot().DescendantNodes().Where(x => x.CSharpKind() == SyntaxKind.InterfaceDeclaration &&
                                                            sm.GetDeclaredSymbol(x).GetDocumentationCommentId().Equals(interfacename)).First() as InterfaceDeclarationSyntax;
            Contract.Assert(node != null);
            var parameters   = "";
            var numberparams = GetNumberParameters(parameterstring);
            if (numberparams > 0)
            {
                parameters = "<";
                var commas = new String(',', numberparams - 1);
                parameters += commas;
                parameters += ">";
            }
            var attr_name  = SyntaxFactory.ParseName("ContractClass");
            var attr_args  = SyntaxFactory.ParseAttributeArgumentList(String.Format("(typeof({0}Contracts{1}))", interfaceShortName, parameters));
            var attr       = SyntaxFactory.Attribute(attr_name, attr_args);
            var attributes = SyntaxFactory.SeparatedList <AttributeSyntax>().Add(attr);
            var attr_list  = SyntaxFactory.AttributeList(attributes);
            var newnode    = node.AddAttributeLists(attr_list) as SyntaxNode;
            newnode = node.SyntaxTree.GetRoot().ReplaceNode(node, newnode);
            var newst = CSharpSyntaxTree.Create(newnode.SyntaxTree.GetRoot() as CSharpSyntaxNode, null, st.FilePath, null);
            return(original.ReplaceSyntaxTree(st, newst));
        }
예제 #5
0
        /// <summary>
        /// Take all the annotations, select only the interface annotations, create their contract classes (if necessary),
        /// resolve the contract class name and contract class method names
        /// </summary>
        /// <param name="annotations"></param>
        /// <param name="project"></param>
        /// <param name="compilation"></param>
        /// <param name="resolvedannotations">All the annotations with the interface annotation fields completed</param>
        /// <returns>The compilation with potentially new empty contract classes</returns>
        internal static Compilation CreateOrFindContractsClasses(IEnumerable <BaseAnnotation> annotations,
                                                                 Project project,
                                                                 Compilation compilation,
                                                                 out IEnumerable <BaseAnnotation> resolvedannotations)
        {
            #region CodeContracts
            Contract.Requires(annotations != null);
            Contract.Requires(project != null);
            Contract.Requires(compilation != null);
            Contract.Ensures(Contract.ValueAtReturn <IEnumerable <BaseAnnotation> >(out resolvedannotations) != null);
            Contract.Ensures(Contract.Result <Compilation>() != null);
            #endregion CodeContracts

            Output.WriteLine("Gathering (and creating) contract classes for interfaces and abstract classes");

            var resolvedList = annotations.Where(x => !(x is UnresolvedInterfaceAnnotation)).ToList();
            foreach (var interfaceGroup in annotations.OfType <UnresolvedInterfaceAnnotation>().GroupBy(x => x.InterfaceName))
            {
                var    first = interfaceGroup.First();
                var    interfaceSymbol = InterfaceAnnotationHelpers.GetInterfaceSymbol(project, compilation, first.InterfaceName, first.InterfaceShortName);
                string contractName, fileName, interfaceName;
                interfaceName = first.InterfaceName;
                if (!InterfaceAnnotationHelpers.TryFindContractsClass(compilation, interfaceSymbol, out contractName, out fileName))
                {
                    //fileName = first.FileName;
                    fileName = interfaceSymbol.Locations[0].SourceTree.FilePath; // hopefully index 0 is where the declaration is?
                    var interfaceMethod = first.InterfaceMethod;
                    contractName = GetCreatedContractClassName(interfaceName, interfaceMethod);
                    compilation  = InterfaceAnnotationHelpers.MakeContractsClassFor(project, compilation, interfaceName, fileName, first.ParametersString);
                    compilation  = InterfaceAnnotationHelpers.ImplementContractsClass(project, compilation, fileName, interfaceName, contractName);
                    var syntaxTree    = compilation.SyntaxTrees.First(x => x.FilePath.Equals(fileName, StringComparison.OrdinalIgnoreCase));
                    var newSyntaxTree = Replacer.AddUsingsContracts(syntaxTree);
                    compilation = compilation.ReplaceSyntaxTree(syntaxTree, SyntaxFactory.SyntaxTree(newSyntaxTree.GetRoot(), null, fileName));
                    compilation = InterfaceAnnotationHelpers.AddContractsClassAttributeToInterface(project, compilation, fileName, interfaceName, first.ParametersString);
                }
                foreach (var methodgroup in interfaceGroup.GroupBy(annotation => annotation.InterfaceMethod))
                {
                    first = methodgroup.First();
                    var methodName = InterfaceAnnotationHelpers.GetMethodName(first.InterfaceName, first.InterfaceMethod, contractName);
                    resolvedList.AddRange(methodgroup.Select(x => new ResolvedInterfaceAnnotation(fileName, methodName, x.Annotation, x.Squiggle, x.Kind, x)));
                }
                //var methodName = InterfaceAnnotationHelpers.GetMethodName(first.InterfaceName, first.InterfaceMethod, contractName);
                //resolvedList.AddRange(interfaceGroup.Select(x => new ResolvedInterfaceAnnotation(fileName, methodName, x.Annotation, x.Squiggle, x.Kind, x)));
                //return compilation;
                //compilation = first.MakeOrFindContractsClass(project, compilation);
                //foreach (var intf in interfaceGroup)
                //{
                //  //intf.CopyFileNameAndContractsClass(first);
                //
                //}
                //foreach (var grp in interfaceGroup.GroupBy(x => x.MethodName))
                //{
                //  first = grp.First();
                //  first.FindMethodName(compilation);
                //  foreach (var intf in grp)
                //  {
                //    intf.CopyMethodName(first);
                //  }
                //}
            }
            resolvedannotations = resolvedList.AsReadOnly();
            return(compilation);
        }
예제 #6
0
        public static bool TryMakeAnnotation(CCCheckOutputAssemblyMethod method,
                                             CCCheckOutputAssemblyMethodSuggestion suggestion,
                                             ClousotSuggestion.Kind suggestionKind,
                                             string path,
                                             Squiggle squiggle,
                                             out BaseAnnotation annotation, out string whyFailed)
        {
            #region CodeContracts
            Contract.Ensures(!Contract.Result <bool>() || Contract.ValueAtReturn(out annotation) != null);
            Contract.Ensures(Contract.Result <bool>() || Contract.ValueAtReturn(out whyFailed) != null);
            #endregion CodeContracts

            whyFailed  = null;
            annotation = null;
            switch (suggestionKind)
            {
            case ClousotSuggestion.Kind.AssumeOnEntry:
            case ClousotSuggestion.Kind.Ensures:
            case ClousotSuggestion.Kind.Requires:
            {
                annotation = new Precondition(path, method.Name, suggestion.Suggested, squiggle, suggestionKind);
                return(true);
            }

            case ClousotSuggestion.Kind.ObjectInvariant:
            {
                Contract.Assert(suggestion.SuggestionExtraInfo != null, "We expect to have extra info for the suggestion of an object invariant");
                var exinfo2 = suggestion.SuggestionExtraInfo[0];
                annotation = new UnresolvedObjectInvariant(path, method.Name, exinfo2.TypeDocumentId, exinfo2.SuggestedCode, squiggle, suggestionKind);
                return(true);
            }

            case ClousotSuggestion.Kind.EnsuresNecessary:
            {
                Contract.Assert(suggestion.SuggestionExtraInfo != null, "We expect to have extra info for the suggestion of an ensures necessary");
                if (suggestion.SuggestionExtraInfo.First().CalleeMemberKind == "Interface")
                {
                    var exinfo = suggestion.SuggestionExtraInfo[0];
                    if (exinfo.CalleeIsDeclaredInTheSameAssembly.Equals("False"))
                    {
                        whyFailed = "Don't know what to do when callee is in another assembly";
                        return(false);
                    }
                    //annotation = new UnresolvedInterfaceAnnotation(exinfo, squiggle, suggestionKind);
                    UnresolvedInterfaceAnnotation ann;
                    if (InterfaceAnnotationHelpers.TryMakeUnresolvedInterfaceAnnotation(exinfo, squiggle, suggestionKind, out ann))
                    {
                        annotation = ann;
                        return(true);
                    }
                    whyFailed = "Unknown suggestion";
                    return(false);
                }
                whyFailed = string.Format("Unhandled clousot suggestion kind {0} {1}", suggestionKind, suggestion.SuggestionExtraInfo.First().CalleeMemberKind);
                return(false);
            }

            case ClousotSuggestion.Kind.ReadonlyField:
            {
                Contract.Assert(suggestion.SuggestionExtraInfo != null, "We expect to have extra info for the suggestion of a readonly field");
                var extraInfo = suggestion.SuggestionExtraInfo[0];
                annotation = new ReadonlyField(extraInfo.CalleeDocumentId, path, extraInfo.TypeDocumentId, method.Name, squiggle, ClousotSuggestion.Kind.ReadonlyField);
                return(true);
            }

            default:
            {
                whyFailed = string.Format("Unhandled clousot suggestion kind {0}", suggestionKind);
                return(false);
            }
            }
        }