diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin index f08bc138af..2061021bd5 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin @@ -130,78 +130,88 @@ - - - - - - - - - + + + + + + + + + + class = "ICSharpCode.NRefactory.CSharp.Refactoring.AddAnotherAccessorAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.CheckIfParameterIsNullAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertDecToHexAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertHexToDecAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.ConvertForeachToForAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateBackingStoreAction" /> + + + + class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateEventInvocatorAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateFieldAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreateLocalVariableAction" /> + + class = "ICSharpCode.NRefactory.CSharp.Refactoring.CreatePropertyAction" /> + + class = "ICSharpCode.NRefactory.CSharp.Refactoring.FlipOperatorArgumentsAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.GenerateGetterAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.GeneratePropertyAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.GenerateSwitchLabelsAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.InsertAnonymousMethodSignatureAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.IntroduceFormatItemAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.InvertIfAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.RemoveBackingStoreAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.RemoveBracesAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.RemoveRegionAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.ReplaceEmptyStringAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.SplitDeclarationAndAssignmentAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.SplitStringAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseExplicitTypeAction" /> + class = "ICSharpCode.NRefactory.CSharp.Refactoring.UseVarKeywordAction" /> diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpFullParseInformation.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpFullParseInformation.cs index 73afd1abd0..cf074d7a67 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpFullParseInformation.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/CSharpFullParseInformation.cs @@ -6,6 +6,7 @@ using System.Threading; using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.CSharp.TypeSystem; +using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.SharpDevelop.Parser; @@ -14,14 +15,16 @@ namespace CSharpBinding.Parser public class CSharpFullParseInformation : ParseInformation { readonly CompilationUnit compilationUnit; + readonly ITextSourceVersion parsedVersion; - public CSharpFullParseInformation(CSharpParsedFile parsedFile, CompilationUnit compilationUnit) + public CSharpFullParseInformation(CSharpParsedFile parsedFile, ITextSourceVersion parsedVersion, CompilationUnit compilationUnit) : base(parsedFile, isFullParseInformation: true) { if (parsedFile == null) throw new ArgumentNullException("parsedFile"); if (compilationUnit == null) throw new ArgumentNullException("compilationUnit"); + this.parsedVersion = parsedVersion; this.compilationUnit = compilationUnit; } @@ -33,6 +36,10 @@ namespace CSharpBinding.Parser get { return compilationUnit; } } + public ITextSourceVersion ParsedVersion { + get { return parsedVersion; } + } + public CSharpAstResolver GetResolver(ICompilation compilation) { return (CSharpAstResolver)compilation.CacheManager.GetOrAddShared( diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs index db45491d63..5e4f35b019 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Parser/Parser.cs @@ -79,7 +79,7 @@ namespace CSharpBinding.Parser ParseInformation parseInfo; if (fullParseInformationRequested) - parseInfo = new CSharpFullParseInformation(file, cu); + parseInfo = new CSharpFullParseInformation(file, fileContent.Version, cu); else parseInfo = new ParseInformation(file, fullParseInformationRequested); diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs index e22f95122a..e1d5c5b9d1 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs @@ -92,6 +92,7 @@ namespace CSharpBinding.Refactoring this.editor = editor; this.markerService = editor.GetService(typeof(ITextMarkerService)) as ITextMarkerService; //SD.ParserService.ParserUpdateStepFinished += ParserService_ParserUpdateStepFinished; + SD.ParserService.ParseInformationUpdated += new EventHandler(SD_ParserService_ParseInformationUpdated); editor.ContextActionProviders.Add(this); } @@ -218,17 +219,19 @@ namespace CSharpBinding.Refactoring analyzedVersion = null; } - void ParserService_ParserUpdateStepFinished(object sender, ParserUpdateStepEventArgs e) + void SD_ParserService_ParseInformationUpdated(object sender, ParseInformationEventArgs e) { - var parseInfo = e.ParseInformation as CSharpFullParseInformation; + var parseInfo = e.NewParseInformation as CSharpFullParseInformation; ITextSourceVersion currentVersion = editor.Document.Version; - ITextSourceVersion parsedVersion = e.Content.Version; - if (parseInfo != null && parsedVersion != null && currentVersion != null && parsedVersion.BelongsToSameDocumentAs(currentVersion)) { + if (parseInfo == null) + return; + ITextSourceVersion parsedVersion = parseInfo.ParsedVersion; + if (parsedVersion != null && currentVersion != null && parsedVersion.BelongsToSameDocumentAs(currentVersion)) { if (analyzedVersion != null && analyzedVersion.CompareAge(parsedVersion) == 0) { // don't analyze the same version twice return; } - RunAnalysis(e.Content, parseInfo); + RunAnalysis(editor.Document.CreateSnapshot(), parseInfo); } } diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDScript.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDScript.cs index 971b84ecf3..66f1a9045d 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDScript.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/SDScript.cs @@ -73,5 +73,12 @@ namespace CSharpBinding.Refactoring { // TODO } + + public override void Dispose() + { + base.Dispose(); + // refresh parse information so that the issue can disappear immediately + SD.ParserService.ParseAsync(editor.FileName, editor.Document).FireAndForget(); + } } } diff --git a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParser.cs b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParser.cs index da8a98eaeb..ca7ca6743e 100644 --- a/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParser.cs +++ b/src/AddIns/BackendBindings/XamlBinding/XamlBinding/XamlParser.cs @@ -48,91 +48,20 @@ namespace ICSharpCode.XamlBinding return false; } -// volatile ITextSourceVersion lastParsedVersion; - - /// - /// Parse the given text and enter read lock. - /// No parsing is done if the text is older than seen before. - /// -// public IDisposable ParseAndLock(ITextSource fileContent) -// { -// // Copy to ensure thread-safety -// var lastVer = this.lastParsedVersion; -// if (lastVer == null || // First parse -// fileContent.Version == null || // Versioning not supported -// !fileContent.Version.BelongsToSameDocumentAs(lastVer) || // Different document instance? Can happen after closing and reopening of file. -// fileContent.Version.CompareAge(lastVer) > 0) // Is fileContent newer? -// { -// parser.Lock.EnterWriteLock(); -// // Double check, now that we are thread-safe -// lastVer = this.lastParsedVersion; -// if (lastVer == null || fileContent.Version == null || !fileContent.Version.BelongsToSameDocumentAs(lastVer)) { -// // First parse or versioning not supported -// using (DebugTimer.Time("normal parse")) -// parser.Parse(fileContent.Text, null); -// this.lastParsedVersion = fileContent.Version; -// } else if (fileContent.Version.CompareAge(lastParsedVersion) > 0) { -// // Incremental parse -// var changes = lastParsedVersion.GetChangesTo(fileContent.Version). -// Select(c => new DocumentChangeEventArgs(c.Offset, c.RemovedText, c.InsertedText)); -// using (DebugTimer.Time("incremental parse")) -// parser.Parse(fileContent.Text, changes); -// this.lastParsedVersion = fileContent.Version; -// } else { -// // fileContent is older - no need to parse -// } -// parser.Lock.EnterReadLock(); -// parser.Lock.ExitWriteLock(); -// } else { -// // fileContent is older - no need to parse -// parser.Lock.EnterReadLock(); -// } -// return new CallbackOnDispose(() => parser.Lock.ExitReadLock()); -// } -// -// public ICompilationUnit Parse(IProjectContent projectContent, string fileName, ITextSource fileContent) -// { -// ICompilationUnit compilationUnit; -// -// using (ParseAndLock(fileContent)) { -// var document = parser.LastDocument; -// -// CompilationUnitCreatorVisitor visitor = -// new CompilationUnitCreatorVisitor(projectContent, fileContent.Text, fileName, lexerTags); -// -// document.AcceptVisitor(visitor); -// -// compilationUnit = visitor.CompilationUnit; -// } -// -// // During project load all XAML files are parsed -// // most of them are not opened, thus fileContent.Version is null. -// // We can clear the parser data, because the file will be reparsed -// // as soon as it is opened by the user. -// -// // This will save us some memory, because we only use the -// // compilation unit created by the visitor above for code completion. -// if (fileContent.Version == null) { -// parser.Lock.EnterWriteLock(); -// // double-checked locking (other threads might parse the document in the meantime) -// if (lastParsedVersion == null) { -// parser.Clear(); -// } -// parser.Lock.ExitWriteLock(); -// } -// -// return compilationUnit; -// } - volatile IncrementalParserState parserState; - public ParseInformation Parse(FileName fileName, ITextSource fileContent, bool fullParseInformationRequested, + public ParseInformation Parse(FileName fileName, ITextSource fileContent, bool fullParseInformationRequested, IProject parentProject, CancellationToken cancellationToken) { AXmlParser parser = new AXmlParser(); AXmlDocument document; IncrementalParserState newParserState; - document = parser.ParseIncremental(parserState, fileContent, out newParserState); + if (fileContent.Version is OnDiskTextSourceVersion) { + document = parser.Parse(fileContent, cancellationToken); + newParserState = null; + } else { + document = parser.ParseIncremental(parserState, fileContent, out newParserState, cancellationToken); + } parserState = newParserState; XamlParsedFile parsedFile = XamlParsedFile.Create(fileName, fileContent, document); ParseInformation parseInfo; diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/EditorActionsProvider.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/EditorActionsProvider.cs index 512eb92e8f..de6d62f44a 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/EditorActionsProvider.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/EditorActionsProvider.cs @@ -50,6 +50,7 @@ namespace ICSharpCode.AvalonEdit.AddIn.ContextActions throw new ArgumentNullException("editorContext"); if (providers == null) throw new ArgumentNullException("providers"); + LoadProviderVisibilities(providers); this.providers = providers; this.editorContext = editorContext; } diff --git a/src/Main/Base/Project/Src/Project/Solution/SolutionPreferences.cs b/src/Main/Base/Project/Src/Project/Solution/SolutionPreferences.cs index f9c586c7c4..afd64f1608 100644 --- a/src/Main/Base/Project/Src/Project/Solution/SolutionPreferences.cs +++ b/src/Main/Base/Project/Src/Project/Solution/SolutionPreferences.cs @@ -78,7 +78,7 @@ namespace ICSharpCode.SharpDevelop.Project /// Properties IMementoCapable.CreateMemento() { - Properties p = properties; + Properties p = properties.Clone(); p.Set("StartupProject", startupProject); p.Set("ActiveConfiguration", activeConfiguration); p.Set("ActivePlatform", activePlatform); diff --git a/src/Main/SharpDevelop/Parser/ParserService.cs b/src/Main/SharpDevelop/Parser/ParserService.cs index e2120ac546..a6df298bdb 100644 --- a/src/Main/SharpDevelop/Parser/ParserService.cs +++ b/src/Main/SharpDevelop/Parser/ParserService.cs @@ -142,9 +142,7 @@ namespace ICSharpCode.SharpDevelop.Parser #endregion #region Entry management - const int cachedEntryCount = 5; Dictionary fileEntryDict = new Dictionary(); - Queue cacheExpiryQueue = new Queue(); ParserServiceEntry GetFileEntry(FileName fileName, bool createIfMissing) { @@ -182,16 +180,22 @@ namespace ICSharpCode.SharpDevelop.Parser } } + const int cachedEntryCount = 5; + List cacheExpiryQueue = new List(); + internal void RegisterForCacheExpiry(ParserServiceEntry entry) { // This method should not be called within any locks Debug.Assert(!Monitor.IsEntered(entry)); ParserServiceEntry expiredItem = null; lock (cacheExpiryQueue) { + cacheExpiryQueue.Remove(entry); // remove entry from queue if it's already enqueued if (cacheExpiryQueue.Count >= cachedEntryCount) { - expiredItem = cacheExpiryQueue.Dequeue(); + // dequeue item at front + expiredItem = cacheExpiryQueue[0]; + cacheExpiryQueue.RemoveAt(0); } - cacheExpiryQueue.Enqueue(entry); + cacheExpiryQueue.Add(entry); // add entry to back } if (expiredItem != null) expiredItem.ExpireCache(); diff --git a/src/Main/SharpDevelop/Parser/ParserServiceEntry.cs b/src/Main/SharpDevelop/Parser/ParserServiceEntry.cs index 1c6be6c166..8890eeba38 100644 --- a/src/Main/SharpDevelop/Parser/ParserServiceEntry.cs +++ b/src/Main/SharpDevelop/Parser/ParserServiceEntry.cs @@ -156,7 +156,7 @@ namespace ICSharpCode.SharpDevelop.Parser fileContent = SD.FileService.GetFileContent(fileName); } - return DoParse(fileContent, parentProject, false, cancellationToken).CachedParseInformation; + return DoParse(fileContent, parentProject, true, cancellationToken).CachedParseInformation; } public IParsedFile ParseFile(ITextSource fileContent, IProject parentProject, CancellationToken cancellationToken) @@ -231,10 +231,10 @@ namespace ICSharpCode.SharpDevelop.Parser // Only if all parse runs succeeded, register the parse information. currentVersion = fileContent.Version; for (int i = 0; i < entries.Count; i++) { - if (fullParseInformationRequested || entries[i].CachedParseInformation != null) - entries[i] = new ProjectEntry(entries[i].Project, entries[i].ParsedFile, results[i].NewParseInformation); + if (fullParseInformationRequested || (entries[i].CachedParseInformation != null && results[i].NewParseInformation.IsFullParseInformation)) + entries[i] = new ProjectEntry(entries[i].Project, results[i].NewParsedFile, results[i].NewParseInformation); else - entries[i] = new ProjectEntry(entries[i].Project, entries[i].ParsedFile, null); + entries[i] = new ProjectEntry(entries[i].Project, results[i].NewParsedFile, null); if (entries[i].Project != null) entries[i].Project.OnParseInformationUpdated(results[i]); parserService.RaiseParseInformationUpdated(results[i]);