diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ParserFoldingStrategy.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ParserFoldingStrategy.cs index f10d50ada4..e9a0a85466 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ParserFoldingStrategy.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ParserFoldingStrategy.cs @@ -13,7 +13,7 @@ using ICSharpCode.SharpDevelop.Parser; namespace ICSharpCode.AvalonEdit.AddIn { /// - /// Uses SharpDevelop.Dom to create parsing information. + /// Uses the NRefactory type system to create parsing information. /// public class ParserFoldingStrategy : IDisposable { @@ -84,32 +84,50 @@ namespace ICSharpCode.AvalonEdit.AddIn return; } DomRegion cRegion = c.BodyRegion; - if (cRegion.IsEmpty) - cRegion = c.Region; - if (cRegion.BeginLine < cRegion.EndLine) { - newFoldMarkers.Add(new NewFolding(GetOffset(cRegion.BeginLine, cRegion.BeginColumn), - GetOffset(cRegion.EndLine, cRegion.EndColumn))); + if (c.BodyRegion.BeginLine < c.BodyRegion.EndLine) { + newFoldMarkers.Add(new NewFolding(GetStartOffset(c.BodyRegion), GetEndOffset(c.BodyRegion))); } foreach (var innerClass in c.NestedTypes) { AddClassMembers(innerClass, newFoldMarkers); } foreach (var m in c.Members) { - if (m.Region.EndLine < m.BodyRegion.EndLine) { - newFoldMarkers.Add(new NewFoldingDefinition(GetOffset(m.Region.EndLine, m.Region.EndColumn), - GetOffset(m.BodyRegion.EndLine, m.BodyRegion.EndColumn))); + if (m.BodyRegion.BeginLine < m.BodyRegion.EndLine) { + newFoldMarkers.Add(new NewFoldingDefinition(GetStartOffset(m.BodyRegion), GetEndOffset(m.BodyRegion))); } } } - int GetOffset(int line, int column) + int GetStartOffset(DomRegion bodyRegion) { - if (line < 1) + var document = textArea.Document; + if (bodyRegion.BeginLine < 1) + return 0; + if (bodyRegion.BeginLine > document.LineCount) + return document.TextLength; + var line = document.GetLineByNumber(bodyRegion.BeginLine); + int lineStart = line.Offset; + int bodyStartOffset = lineStart + bodyRegion.BeginColumn - 1; + for (int i = lineStart; i < bodyStartOffset; i++) { + if (!char.IsWhiteSpace(document.GetCharAt(i))) { + // Non-whitespace in front of body start: + // Use the body start as start offset + return bodyStartOffset; + } + } + // Only whitespace in front of body start: + // Use the end of the previous line as start offset + return line.PreviousLine != null ? line.PreviousLine.EndOffset : bodyStartOffset; + } + + int GetEndOffset(DomRegion region) + { + if (region.EndLine < 1) return 0; var document = textArea.Document; - if (line > document.LineCount) + if (region.EndLine > document.LineCount) return document.TextLength; - return document.GetOffset(line, column); + return document.GetOffset(region.End); } } } diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs index 9ec8883b9b..5a1680acdc 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/QuickClassBrowser.cs @@ -34,11 +34,18 @@ namespace ICSharpCode.AvalonEdit.AddIn get { return entity; } } - public EntityItem(IUnresolvedTypeDefinition typeDef) + public EntityItem(IUnresolvedTypeDefinition typeDef, ICompilation compilation) { this.IsInSamePart = true; this.entity = typeDef; - this.text = typeDef.Name; + var resolvedDefinition = typeDef.Resolve(new SimpleTypeResolveContext(compilation.MainAssembly)).GetDefinition(); + if (resolvedDefinition != null) { + var ambience = compilation.GetAmbience(); + ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList | ConversionFlags.ShowDeclaringType; + this.text = ambience.ConvertEntity(resolvedDefinition); + } else { + this.text = typeDef.Name; + } this.image = CompletionImage.GetImage(typeDef); } @@ -46,10 +53,7 @@ namespace ICSharpCode.AvalonEdit.AddIn { this.IsInSamePart = true; this.entity = member.UnresolvedMember; - if (entity is ITypeDefinition) - ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList | ConversionFlags.ShowDeclaringType; - else - ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList | ConversionFlags.ShowParameterList | ConversionFlags.ShowParameterNames; + ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList | ConversionFlags.ShowParameterList | ConversionFlags.ShowParameterNames; text = ambience.ConvertEntity(member); image = CompletionImage.GetImage(member); } @@ -130,11 +134,12 @@ namespace ICSharpCode.AvalonEdit.AddIn List classItems = new List(); List memberItems = new List(); - void DoUpdate(IUnresolvedFile compilationUnit) + void DoUpdate(IUnresolvedFile unresolvedFile) { classItems = new List(); - if (compilationUnit != null) { - AddClasses(compilationUnit.TopLevelTypeDefinitions); + if (unresolvedFile != null) { + ICompilation compilation = SD.ParserService.GetCompilationForFile(FileName.Create(unresolvedFile.FileName)); + AddClasses(unresolvedFile.TopLevelTypeDefinitions, compilation); } classItems.Sort(); classComboBox.ItemsSource = classItems; @@ -163,13 +168,13 @@ namespace ICSharpCode.AvalonEdit.AddIn } } - void AddClasses(IEnumerable classes) + void AddClasses(IEnumerable classes, ICompilation compilation) { foreach (var c in classes) { if (c.IsSynthetic) continue; - classItems.Add(new EntityItem(c)); - AddClasses(c.NestedTypes); + classItems.Add(new EntityItem(c, compilation)); + AddClasses(c.NestedTypes, compilation); } } diff --git a/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs b/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs index bd3d8e277d..a339537725 100644 --- a/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs +++ b/src/Main/Base/Project/Src/Services/ParserService/ParseProjectContent.cs @@ -141,6 +141,11 @@ namespace ICSharpCode.SharpDevelop.Parser return cacheFileName; } + /// + /// Magic number that identifies the SharpDevelop version used to create the cache file. + /// + const int cacheMagicNumber = 5002; + static IProjectContent TryReadFromCache(string cacheFileName) { if (cacheFileName == null || !File.Exists(cacheFileName)) @@ -149,6 +154,10 @@ namespace ICSharpCode.SharpDevelop.Parser try { using (FileStream fs = new FileStream(cacheFileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete, 4096, FileOptions.SequentialScan)) { using (BinaryReader reader = new BinaryReaderWith7BitEncodedInts(fs)) { + if (reader.ReadByte() != cacheMagicNumber) { + LoggingService.Warn("Incorrect magic number"); + return null; + } FastSerializer s = new FastSerializer(); return (IProjectContent)s.Deserialize(reader); } @@ -165,6 +174,10 @@ namespace ICSharpCode.SharpDevelop.Parser } catch (InvalidCastException ex) { LoggingService.Warn(ex); return null; + } catch (FormatException ex) { + // e.g. invalid 7-bit-encoded int + LoggingService.Warn(ex); + return null; } } @@ -174,6 +187,7 @@ namespace ICSharpCode.SharpDevelop.Parser Directory.CreateDirectory(Path.GetDirectoryName(cacheFileName)); using (FileStream fs = new FileStream(cacheFileName, FileMode.Create, FileAccess.Write)) { using (BinaryWriter writer = new BinaryWriterWith7BitEncodedInts(fs)) { + writer.Write(cacheMagicNumber); FastSerializer s = new FastSerializer(); s.Serialize(writer, pc); }