private MetadataTracker(IWpfTextView textView, double defaultFontSize = 10.0d) { this.defaultFontSize = defaultFontSize; this.textView = textView; bool isMetadataFile = false; fileName = textView.TextBuffer.GetFileName(); if (fileName.Contains('$'))//TODO: This is a very weak check, we need a better way to check this! { isMetadataFile = true; } if (!isMetadataFile) { return; } adornmentManager = AdornmentManager.GetOrCreateAdornmentManager(textView, "MetadataAdornments"); //timer = new Timer(); //timer.BeginInit(); //timer.AutoReset = false; //timer.Elapsed += OnLayoutSettled; //timer.Interval = 2000; //timer.EndInit(); //timer.Start(); textView.LayoutChanged += OnLayoutChanged; var foo = new ContractAdornment(11, textView.TextSnapshot.CreateTrackingSpan(0, 10, SpanTrackingMode.EdgeExclusive), defaultFontSize); }
void OnLayoutSettled(object sender, ElapsedEventArgs e) { var splitFileName = fileName.Split('$');//TODO: This may have holes, check for corner cases! string assemblyName = splitFileName[1]; string assemblyVersion = splitFileName[2]; string typeName = Path.GetFileNameWithoutExtension(fileName);//.Split('.').Last(); ContractsProviderHost host = null; string codeContractsInstallDir = Environment.GetEnvironmentVariable("CodeContractsInstallDir"); if (!String.IsNullOrEmpty(codeContractsInstallDir)) { string contractsDir = Path.Combine(codeContractsInstallDir, @"contracts\3.5"); host = new ContractsProviderHost(new string[] { contractsDir }); } if (host == null) { return;//TODO: Throw error? } //var assemlyIdentity = new AssemblyIdentity(host.NameTable.GetNameFor(assemblyName), null, new Version(assemblyVersion), null, null); //var assembly = host.FindAssembly(assemlyIdentity); var assembly = host.LoadUnitFrom(Path.Combine(codeContractsInstallDir, @"Contracts\v3.5", Path.GetFileNameWithoutExtension(assemblyName) + ".contracts.dll")); if (assembly == null || assembly == Dummy.Assembly) { return;//TODO: Throw error? } var contractsProvider = host.GetContractProvider(assembly.UnitIdentity); if (contractsProvider == null) { return; //TODO Throw error? Will it ever be null? } var type = UnitHelper.FindType(host.NameTable, assembly, typeName); var methodsToContracts = new Dictionary <string, IMethodContract>(type.Methods.Count()); var gettersToContracts = new Dictionary <string, IMethodContract>(); var settersToContracts = new Dictionary <string, IMethodContract>(); System.Xml.XmlDocument doc; foreach (var method in type.Methods) { var methodContract = contractsProvider.GetMethodContractFor(method); if (methodContract != null) { if (IsGetter(method)) { var getterSignature = MemberHelper.GetMemberSignature(method, NameFormattingOptions.OmitContainingNamespace | NameFormattingOptions.ReturnType | NameFormattingOptions.TypeParameters | NameFormattingOptions.UseTypeKeywords | NameFormattingOptions.OmitContainingType | NameFormattingOptions.Visibility ); getterSignature = getterSignature.Substring(0, getterSignature.LastIndexOf('.')); gettersToContracts.Add(getterSignature, methodContract); } else if (IsSetter(method)) { var setterSignature = MemberHelper.GetMemberSignature(method, NameFormattingOptions.OmitContainingNamespace | NameFormattingOptions.ReturnType | NameFormattingOptions.TypeParameters | NameFormattingOptions.UseTypeKeywords | NameFormattingOptions.OmitContainingType | NameFormattingOptions.Visibility ); setterSignature = setterSignature.Substring(0, setterSignature.LastIndexOf('.')); settersToContracts.Add(setterSignature, methodContract); } else { var methodSignature = MemberHelper.GetMemberSignature(method, NameFormattingOptions.OmitContainingNamespace | NameFormattingOptions.ReturnType | NameFormattingOptions.ParameterName | NameFormattingOptions.ParameterModifiers | NameFormattingOptions.TypeParameters | NameFormattingOptions.UseTypeKeywords | NameFormattingOptions.OmitContainingType | NameFormattingOptions.Modifiers | NameFormattingOptions.Signature | NameFormattingOptions.Visibility ); methodsToContracts.Add(methodSignature, methodContract); } } } foreach (var line in textView.TextSnapshot.Lines) { var lineText = line.GetText(); if (lineText.Contains("//")) { continue; //Skip comments } if (lineText.Contains('{') && (lineText.Contains(" get; ") || lineText.Contains(" set; ")) && lineText.Contains('}')) // If property { int endOfSig = lineText.IndexOf('{') - 1; int startOfSig = endOfSig - 1; bool hitSpace = false; for (int i = startOfSig; i > 0; i--) { char c = lineText[i]; if (c == ' ' && hitSpace) { startOfSig = i + 1; break; } else if (c == ' ') { hitSpace = true; } } var propertySignature = lineText.Substring(startOfSig, endOfSig - startOfSig); IMethodContract getterContract; IMethodContract setterContract = null; if (gettersToContracts.TryGetValue(propertySignature, out getterContract) || settersToContracts.TryGetValue(propertySignature, out setterContract)) { var tag = propertySignature.GetHashCode(); int firstNonWhitespace = 0; for (int i = 0; i < lineText.Count(); i++) { char c = lineText[i]; if (c != ' ') { firstNonWhitespace = i; break; } } var span = textView.TextSnapshot.CreateTrackingSpan(line.Start + firstNonWhitespace, propertySignature.Length, SpanTrackingMode.EdgeExclusive); var adornment = new ContractAdornment(tag, span, defaultFontSize, false, null, getterContract, setterContract, "Contracts from " + typeName + "."); adornmentManager.AddAdornment(adornment, tag);//TODO: Inherit from info is wrong. } } else if (lineText.Contains('(') && lineText.Contains('(') && lineText.Contains(';')) //If method { int endOfSig = lineText.LastIndexOf(')') + 1; int startOfSig = lineText.IndexOf('('); bool hitSpace = false; for (int i = startOfSig; i > 0; i--) { char c = lineText[i]; if (c == ' ' && hitSpace) { startOfSig = i + 1; break; } else if (c == ' ') { hitSpace = true; } } var methodSignature = lineText.Substring(startOfSig, endOfSig - startOfSig); IMethodContract methodContract; if (methodsToContracts.TryGetValue(methodSignature, out methodContract)) { var tag = methodSignature.GetHashCode(); int firstNonWhitespace = 0; for (int i = 0; i < lineText.Count(); i++) { char c = lineText[i]; if (c != ' ') { firstNonWhitespace = i; break; } } var span = textView.TextSnapshot.CreateTrackingSpan(line.Start + firstNonWhitespace, methodSignature.Length, SpanTrackingMode.EdgeExclusive); var adornment = new ContractAdornment(tag, span, defaultFontSize, false, null, methodContract, "Contracts from " + typeName + "."); adornmentManager.AddAdornment(adornment, tag);//TODO: Inherit from info is wrong. } } } if (true) { } }