From a71bf193d7e533142b465ad8debccea2cf53ceda Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Fri, 27 Jun 2014 20:33:11 +0200 Subject: [PATCH] Merge several bugfixes from SharpDevelop repository to NRefactory. --- .../CreateOverloadWithoutParameterAction.cs | 7 +- .../CodeIssues/Custom/UnreachableCodeIssue.cs | 18 ++++- .../CodeIssues/Custom/XmlDocIssue.cs | 74 ++++++++++--------- .../RedundantCatchClauseIssue.cs | 7 +- .../InsertMissingTokensDecorator.cs | 1 + .../TextWriterOutputFormatter.cs | 8 +- .../Xml/XmlReaderTest.cs | 9 +-- .../DocumentationElement.cs | 2 + 8 files changed, 76 insertions(+), 50 deletions(-) diff --git a/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateOverloadWithoutParameterAction.cs b/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateOverloadWithoutParameterAction.cs index bbbcb262..6b612457 100644 --- a/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateOverloadWithoutParameterAction.cs +++ b/ICSharpCode.NRefactory.CSharp.Refactoring/CodeActions/CreateOverloadWithoutParameterAction.cs @@ -53,7 +53,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring return null; // find existing method - var method = (IMethod)((MemberResolveResult)context.Resolve (methodDecl)).Member; + var resolveResult = context.Resolve(methodDecl) as MemberResolveResult; + if (resolveResult == null) + return null; + var method = resolveResult.Member as IMethod; + if (method == null) + return null; var parameters = new List (method.Parameters.Where (param => param.Name != node.Name)); if (method.DeclaringType.GetMethods ( m => m.Name == method.Name && m.TypeParameters.Count == method.TypeParameters.Count) diff --git a/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Custom/UnreachableCodeIssue.cs b/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Custom/UnreachableCodeIssue.cs index 75817fdb..82adad72 100644 --- a/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Custom/UnreachableCodeIssue.cs +++ b/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Custom/UnreachableCodeIssue.cs @@ -133,6 +133,18 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring if (statement == null || !AddStatement(statement)) base.VisitChildren(node); } + + static TextLocation GetPrevEnd(AstNode node) + { + var prev = node.GetPrevNode(n => !(n is NewLineNode)); + return prev != null ? prev.EndLocation : node.StartLocation; + } + + static TextLocation GetNextStart(AstNode node) + { + var next = node.GetNextNode(n => !(n is NewLineNode)); + return next != null ? next.StartLocation : node.EndLocation; + } bool AddStatement(Statement statement) { @@ -147,7 +159,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring } - var prevEnd = statement.GetPrevNode(n => !(n is NewLineNode)).EndLocation; + var prevEnd = GetPrevEnd(statement); TextLocation start; TextLocation end; @@ -159,12 +171,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring collectedStatements.Add(statement); visitor.unreachableNodes.Add(statement); collectedStatements.Add(ife.ElseToken); - end = ife.ElseToken.GetNextNode(n => !(n is NewLineNode)).StartLocation; + end = GetNextStart(ife.ElseToken); } else if (statement.Role == IfElseStatement.FalseRole) { var ife = (IfElseStatement)statement.Parent; start = ife.ElseToken.StartLocation; collectedStatements.Add(ife.ElseToken); - prevEnd = ife.ElseToken.GetPrevNode(n => !(n is NewLineNode)).EndLocation; + prevEnd = GetPrevEnd(ife.ElseToken); collectedStatements.Add(statement); visitor.unreachableNodes.Add(statement); end = statement.EndLocation; diff --git a/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Custom/XmlDocIssue.cs b/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Custom/XmlDocIssue.cs index 373f3075..e6e41e11 100644 --- a/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Custom/XmlDocIssue.cs +++ b/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Custom/XmlDocIssue.cs @@ -38,25 +38,25 @@ using ICSharpCode.NRefactory.CSharp.TypeSystem; namespace ICSharpCode.NRefactory.CSharp.Refactoring { [IssueDescription("Validate Xml documentation", - Description = "Validate Xml docs", - Category = IssueCategories.CompilerWarnings, - Severity = Severity.Warning)] + Description = "Validate Xml docs", + Category = IssueCategories.CompilerWarnings, + Severity = Severity.Warning)] public class XmlDocIssue : GatherVisitorCodeIssueProvider { protected override IGatherVisitor CreateVisitor(BaseRefactoringContext context) { return new GatherVisitor(context); } - + class GatherVisitor : GatherVisitorBase { readonly List storedXmlComment = new List(); - + public GatherVisitor(BaseRefactoringContext ctx) : base (ctx) { } - + void InvalideXmlComments() { if (storedXmlComment.Count == 0) @@ -77,37 +77,37 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring )); storedXmlComment.Clear(); } - + public override void VisitComment(Comment comment) { if (comment.CommentType == CommentType.Documentation) storedXmlComment.Add(comment); } - + public override void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration) { InvalideXmlComments(); base.VisitNamespaceDeclaration(namespaceDeclaration); } - + public override void VisitUsingDeclaration(UsingDeclaration usingDeclaration) { InvalideXmlComments(); base.VisitUsingDeclaration(usingDeclaration); } - + public override void VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration) { InvalideXmlComments(); base.VisitUsingAliasDeclaration(usingDeclaration); } - + public override void VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration) { InvalideXmlComments(); base.VisitExternAliasDeclaration(externAliasDeclaration); } - + TextLocation TranslateOffset(int offset) { int line = storedXmlComment.First().StartLocation.Line; @@ -120,7 +120,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring } return TextLocation.Empty; } - + void AddXmlIssue(int offset, int length, string str) { var textLocation = TranslateOffset(offset); @@ -150,14 +150,14 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring foreach (var cmt in storedXmlComment) xml.Append(cmt.Content + "\n"); xml.Append("\n"); - + var doc = new AXmlParser().Parse(new StringTextSource(xml.ToString())); - + var stack = new Stack(); stack.Push(doc); foreach (var err in doc.SyntaxErrors) AddXmlIssue(err.StartOffset - firstline.Length, err.EndOffset - err.StartOffset, err.Description); - + while (stack.Count > 0) { var cur = stack.Pop(); var el = cur as AXmlElement; @@ -183,6 +183,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring var m = member as IParameterizedMember; if (m != null && m.Parameters.Any(p => p.Name == name.Value)) break; + var dtype = member as ITypeDefinition; + if ((dtype != null) && (dtype.Kind == TypeKind.Delegate)) { + var invokeMethod = dtype.Methods.FirstOrDefault(method => method.Name == "Invoke"); + if ((invokeMethod != null) && invokeMethod.Parameters.Any(p => p.Name == name.Value)) + break; + } if (name.Value == "value" && member != null && (member.SymbolKind == SymbolKind.Property || member.SymbolKind == SymbolKind.Indexer || member.SymbolKind == SymbolKind.Event) && el.Name == "paramref") break; AddXmlIssue(name.ValueSegment.Offset - firstline.Length + 1, name.ValueSegment.Length - 2, string.Format(ctx.TranslateString("Parameter '{0}' not found"), name.Value)); @@ -204,7 +210,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring trctx = trctx.WithUsingScope(state.CurrentUsingScope); var cdc = new CSharpDocumentationComment (emptySource, trctx); var entity = cdc.ResolveCref(cref.Value); - + if (entity == null) { AddXmlIssue(cref.ValueSegment.Offset - firstline.Length + 1, cref.ValueSegment.Length - 2, string.Format(ctx.TranslateString("Cannot find reference '{0}'"), cref.Value)); } @@ -212,15 +218,15 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring AddXmlIssue(cref.ValueSegment.Offset - firstline.Length + 1, cref.ValueSegment.Length - 2, string.Format(ctx.TranslateString("Reference parsing error '{0}'."), e.Message)); } break; - - } + + } } foreach (var child in cur.Children) stack.Push(child); } storedXmlComment.Clear(); } - + protected virtual void VisitXmlChildren(AstNode node, Action checkDocumentationAction) { AstNode next; @@ -231,7 +237,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring child = next; } checkDocumentationAction(); - + for (; child != null; child = next) { // Store next to allow the loop to continue // if the visitor removes/replaces child. @@ -240,47 +246,47 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring } InvalideXmlComments(); } - + protected virtual void VisitXmlChildren(AstNode node) { VisitXmlChildren(node, () => CheckXmlDoc(node)); } - + public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration) { VisitXmlChildren(typeDeclaration); } - + public override void VisitMethodDeclaration(MethodDeclaration methodDeclaration) { VisitXmlChildren(methodDeclaration); } - + public override void VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration) { VisitXmlChildren(delegateDeclaration); } - + public override void VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration) { VisitXmlChildren(constructorDeclaration); } - + public override void VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration) { VisitXmlChildren(eventDeclaration); } - + public override void VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration) { VisitXmlChildren(destructorDeclaration); } - + public override void VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration) { VisitXmlChildren(enumMemberDeclaration); } - + public override void VisitEventDeclaration(EventDeclaration eventDeclaration) { VisitXmlChildren(eventDeclaration, () => { @@ -289,7 +295,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring } }); } - + public override void VisitFieldDeclaration(FieldDeclaration fieldDeclaration) { VisitXmlChildren(fieldDeclaration, () => { @@ -298,17 +304,17 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring } }); } - + public override void VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration) { VisitXmlChildren(indexerDeclaration); } - + public override void VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration) { VisitXmlChildren(propertyDeclaration); } - + public override void VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration) { VisitXmlChildren(operatorDeclaration); diff --git a/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Synced/RedundanciesInCode/RedundantCatchClauseIssue.cs b/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Synced/RedundanciesInCode/RedundantCatchClauseIssue.cs index 351e0d40..ff2b2b61 100644 --- a/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Synced/RedundanciesInCode/RedundantCatchClauseIssue.cs +++ b/ICSharpCode.NRefactory.CSharp.Refactoring/CodeIssues/Synced/RedundanciesInCode/RedundantCatchClauseIssue.cs @@ -146,8 +146,11 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring if (nextClause != null) { if (nextClause.Type.IsNull && !IsThrowsClause(nextClause)) return false; - if (!IsThrowsClause(nextClause) && type.GetDefinition ().IsDerivedFrom (ctx.Resolve (nextClause.Type).Type.GetDefinition ())) - return false; + if (!IsThrowsClause(nextClause)) { + var typeDef = type.GetDefinition(); + if (typeDef == null || typeDef.IsDerivedFrom(ctx.Resolve(nextClause.Type).Type.GetDefinition())) + return false; + } } n = n.NextSibling; } diff --git a/ICSharpCode.NRefactory.CSharp/OutputVisitor/InsertMissingTokensDecorator.cs b/ICSharpCode.NRefactory.CSharp/OutputVisitor/InsertMissingTokensDecorator.cs index 4f390d92..3f920014 100644 --- a/ICSharpCode.NRefactory.CSharp/OutputVisitor/InsertMissingTokensDecorator.cs +++ b/ICSharpCode.NRefactory.CSharp/OutputVisitor/InsertMissingTokensDecorator.cs @@ -61,6 +61,7 @@ namespace ICSharpCode.NRefactory.CSharp public override void WriteToken(Role role, string token) { CSharpTokenNode t = new CSharpTokenNode(locationProvider.Location, (TokenRole)role); + t.Role = role; EmptyStatement node = nodes.Peek().LastOrDefault() as EmptyStatement; if (node == null) currentList.Add(t); diff --git a/ICSharpCode.NRefactory.CSharp/OutputVisitor/TextWriterOutputFormatter.cs b/ICSharpCode.NRefactory.CSharp/OutputVisitor/TextWriterOutputFormatter.cs index 67c93cda..7e14ea19 100644 --- a/ICSharpCode.NRefactory.CSharp/OutputVisitor/TextWriterOutputFormatter.cs +++ b/ICSharpCode.NRefactory.CSharp/OutputVisitor/TextWriterOutputFormatter.cs @@ -321,7 +321,11 @@ namespace ICSharpCode.NRefactory.CSharp } } - static string ConvertCharLiteral(char ch) + /// + /// Gets the escape sequence for the specified character within a char literal. + /// Does not include the single quotes surrounding the char literal. + /// + public static string ConvertCharLiteral(char ch) { if (ch == '\'') { return "\\'"; @@ -333,7 +337,7 @@ namespace ICSharpCode.NRefactory.CSharp /// Gets the escape sequence for the specified character. /// /// This method does not convert ' or ". - public static string ConvertChar(char ch) + static string ConvertChar(char ch) { switch (ch) { case '\\': diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/Xml/XmlReaderTest.cs b/ICSharpCode.NRefactory.ConsistencyCheck/Xml/XmlReaderTest.cs index ea3ed47d..418c2dc9 100644 --- a/ICSharpCode.NRefactory.ConsistencyCheck/Xml/XmlReaderTest.cs +++ b/ICSharpCode.NRefactory.ConsistencyCheck/Xml/XmlReaderTest.cs @@ -89,14 +89,7 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck.Xml static string ToString(object val) { - if (val == null) - return "null"; - else if (val is string) - return "\"" + TextWriterTokenWriter.ConvertString((string)val) + "\""; - else if (val is char) - return "'" + TextWriterTokenWriter.ConvertChar((char)val) + "'"; - else - return val.ToString(); + return TextWriterTokenWriter.PrintPrimitiveValue(val); } } } diff --git a/ICSharpCode.NRefactory.Xml/DocumentationElement.cs b/ICSharpCode.NRefactory.Xml/DocumentationElement.cs index 6cfd57c4..d3dcc391 100644 --- a/ICSharpCode.NRefactory.Xml/DocumentationElement.cs +++ b/ICSharpCode.NRefactory.Xml/DocumentationElement.cs @@ -39,6 +39,8 @@ namespace ICSharpCode.NRefactory.Xml /// public static XmlDocumentationElement Get(IEntity entity, bool inheritDocIfMissing = true) { + if (entity == null) + return null; var documentationComment = entity.Documentation; if (documentationComment != null) { return Create(documentationComment, entity);