private void AddCommentToSideOfAstValue(ParseTreeNode owner, Token comment, CommentPlacement commentPlacement, int?lineIndexDistanceFromOwnerExplicit) { // first we calculate the lineIndexDistanceFromOwner, then we find a proper node with a non-null astNode to decorate (it can be in another line) int lineIndexDistanceFromOwner = lineIndexDistanceFromOwnerExplicit ?? Math.Abs(comment.Location.Line - owner.Span.Location.Line); owner = Util.Recurse(owner, GetParent).First(_parseTreeNode => _parseTreeNode.AstNode != null); object astValue = GrammarHelper.AstNodeToValue(owner.AstNode); Comments domainComments = astValue.GetComments(); if (domainComments == null) { domainComments = new Comments(); astValue.SetComments(domainComments); } var commentList = commentPlacement == CommentPlacement.OwnerLeft ? domainComments.left : domainComments.right; commentList.Add(CommentToDomainComment(comment, owner, commentPlacement, lineIndexDistanceFromOwner)); decoratedComments.Add(comment); }
private void StoreAstValueToParseTreeNodeRecursive(ParseTreeNode currentNode, int nodeIndex, object astValueParent) { object astValue = GrammarHelper.AstNodeToValue(currentNode.AstNode); if (astValue != null && astValue.GetType().IsClass&& !astValueToParseTreeNode.ContainsKey(astValue)) { astValueToParseTreeNode.Add(astValue, currentNode); } if (astValue != null && astValue.GetDirectParent() == null) { astValue.SetDirectParent(astValueParent); } foreach (var parseTreeChild in currentNode.ChildNodes.Select((parseTreeChild, childIndex) => new { Value = parseTreeChild, Index = childIndex })) { parseTreeNodeToParent.Add(parseTreeChild.Value, currentNode); StoreAstValueToParseTreeNodeRecursive(parseTreeChild.Value, parseTreeChild.Index, astValueParent: astValue); } if (currentNode.Comments != null && currentNode.Comments.Count > 0) { bool isTextInLineAtLeftOfFirstComment = IsTextInLineAtLeftOfComment(currentNode.Comments[0]); int lineIndexForFirstComment = currentNode.Comments[0].Location.Line; foreach (Token comment in currentNode.Comments) { if (decoratedComments.Contains(comment)) { continue; // we have already decorated this comment } ParseTreeNode parentNode = GetParent(currentNode); bool isCommentInLineOfFirstComment = comment.Location.Line == lineIndexForFirstComment; bool isTextInLineAtLeftOfComment = isTextInLineAtLeftOfFirstComment && isCommentInLineOfFirstComment; if (!isTextInLineAtLeftOfComment && parentNode != null && parentNode.Comments.Contains(comment) && parentNode.Span.Location.Line == currentNode.Span.Location.Line && !(GrammarHelper.AstNodeToValue(parentNode.AstNode) is IEnumerable)) { /* * Try to go up so we decorate the comment on the largest "subparsetree", but stop before lists * */ continue; } if (isTextInLineAtLeftOfComment && currentLine != null && comment.Location.Line == currentLine.Span.Location.Line && currentLine.AstNode != null) { /* * The comment belongs to the previous node (they are in the same line). * * Now we have one of the followings: * * code_prev (*comment*) code_this * */ AddCommentToRightOfAstValue(currentLine, comment); } else if (isTextInLineAtLeftOfComment && prevLine != null && comment.Location.Line == prevLine.Span.Location.Line && prevLine.AstNode != null) { /* * The comment belongs to the previous node (they are in the same line). * * code_prev (*comment*) * code_this * */ AddCommentToRightOfAstValue(prevLine, comment); } else if (currentNode.AstNode != null) { AddCommentToLeftOfAstValue(currentNode, comment); // the comment belongs to this node } else if (nodeIndex > 0) { // could not decorate comment, because we have no ast (if nodeIndex == 0 then Irony has already copied it onto the parent) Debug.Assert(parentNode != null); if (currentLine != null) { AddCommentToRightOfAstValue(currentLine, comment); // decorate the comment onto currentLine } else { parentNode.Comments.Add(comment); // copy the comment onto the parent and handle it there } } } } if (currentLine == null || currentNode.Term is Terminal || currentNode.Span.Location.Line == currentLine.Span.Location.Line) { if (currentLine != null && currentNode.Span.Location.Line > currentLine.Span.Location.Line) { prevLine = currentLine; } currentLine = currentNode; } }