public static bool IsChange(this CodeModelEventType eventType) { if (eventType is CodeModelEventType.Add or CodeModelEventType.Remove) { return(false); } // Check that Add and Remove are not set if ((eventType & CodeModelEventType.Add) == 0 && (eventType & CodeModelEventType.Remove) == 0) { // Check that one or more of the change flags are set var allChanges = CodeModelEventType.Rename | CodeModelEventType.Unknown | CodeModelEventType.BaseChange | CodeModelEventType.SigChange | CodeModelEventType.TypeRefChange | CodeModelEventType.ArgChange; if ((eventType & allChanges) != 0) { return(true); } } Debug.Fail("Invalid combination of change type flags!"); return(false); }
protected bool CompareChildren <TNode, TParent>( NodeComparison <TNode, TParent> compare, IReadOnlyList <TNode> oldChildren, IReadOnlyList <TNode> newChildren, TParent newNodeParent, CodeModelEventType eventType, CodeModelEventQueue eventQueue ) where TNode : SyntaxNode where TParent : SyntaxNode { var oldCount = oldChildren.Count; var newCount = newChildren.Count; if (oldCount == newCount) { return(FindDifferentChild( compare, oldChildren, newChildren, newNodeParent, eventQueue )); } else if (Math.Abs(oldCount - newCount) > MaxChildDelta) { // We got two discrepancies, enqueue element changed node for containing node EnqueueChangeEvent(newNodeParent, null, eventType, eventQueue); } else { if (oldCount > newCount) { FindRemovedChild( compare, oldChildren, newChildren, newNodeParent, oldCount - newCount, eventQueue ); } else { FindAddedChild( compare, oldChildren, newChildren, newNodeParent, newCount - oldCount, eventQueue ); } } return(false); }
// Finds the child node which is different OR enqueues a unknown on containing node. private bool FindDifferentChild <TNode, TParent>( NodeComparison <TNode, TParent> compare, IReadOnlyList <TNode> oldChildren, IReadOnlyList <TNode> newChildren, TParent newNodeParent, CodeModelEventType codeModelEventType, CodeModelEventQueue eventQueue) where TNode : SyntaxNode where TParent : SyntaxNode { Debug.Assert(oldChildren.Count == newChildren.Count); var eventCount = eventQueue != null ? eventQueue.Count : 0; var hasChanges = false; // Find first child that is different. int i; for (i = 0; i < oldChildren.Count; i++) { if (!compare(oldChildren[i], newChildren[i], newNodeParent, eventQueue)) { hasChanges = true; i++; break; } } // Look for a second different child. If there is one, we'll throw away any events from // the first different child and enqueue an unknown event on the containing node. for (; i < oldChildren.Count; i++) { if (!compare(oldChildren[i], newChildren[i], newNodeParent, null)) { // rollback any events added by the first difference if (eventQueue != null) { while (eventQueue.Count > eventCount) { eventQueue.Discard(); } } EnqueueChangeEvent(newNodeParent, null, CodeModelEventType.Unknown, eventQueue); return(false); } } return(!hasChanges); }
private void FindRemovedChild <TNode, TParent>( NodeComparison <TNode, TParent> compare, IReadOnlyList <TNode> oldChildren, IReadOnlyList <TNode> newChildren, TParent newNodeParent, CodeModelEventType codeModelEventType, int delta, CodeModelEventQueue eventQueue) where TNode : SyntaxNode where TParent : SyntaxNode { Debug.Assert(oldChildren.Count - delta == newChildren.Count); // The strategy is to assume that all of the removed children are contiguous. // If that turns out not to be the case, an unknown change event is raised // for the containing node. var firstRemoved = -1; // Look for the first different child. If there is one, track that index as // the first added node. int oldIndex, newIndex; for (oldIndex = 0, newIndex = 0; oldIndex < oldChildren.Count; oldIndex++, newIndex++) { if (newIndex >= newChildren.Count || !compare(oldChildren[oldIndex], newChildren[newIndex], newNodeParent, null)) { firstRemoved = oldIndex; oldIndex += delta; break; } } // Look for a second different child. If there is one, we'll throw away any events from // the first different child and enqueue an unknown event on the containing node. for (; oldIndex < oldChildren.Count; oldIndex++, newIndex++) { if (!compare(oldChildren[oldIndex], newChildren[newIndex], newNodeParent, null)) { EnqueueChangeEvent(newNodeParent, null, CodeModelEventType.Unknown, eventQueue); return; } } if (firstRemoved >= 0) { for (var i = 0; i < delta; i++) { EnqueueRemoveEvent(oldChildren[firstRemoved + i], newNodeParent, eventQueue); } } }
private static void ChangeEventQueueForAttributes( AttributeSyntax attribute, SyntaxNode parent, CodeModelEventType eventType, CodeModelEventQueue eventQueue ) { if (parent is BaseFieldDeclarationSyntax baseField) { foreach (var variableDeclarator in baseField.Declaration.Variables) { eventQueue.EnqueueChangeEvent(attribute, variableDeclarator, eventType); } } else { eventQueue.EnqueueChangeEvent(attribute, parent, eventType); } }
protected override void EnqueueChangeEvent( SyntaxNode node, SyntaxNode parent, CodeModelEventType eventType, CodeModelEventQueue eventQueue ) { if (eventQueue == null) { return; } if (node is IncompleteMemberSyntax) { return; } if (node is BaseFieldDeclarationSyntax baseField) { foreach (var variableDeclarator in baseField.Declaration.Variables) { eventQueue.EnqueueChangeEvent(variableDeclarator, parent, eventType); } } else if (node is AttributeListSyntax attributeList) { foreach (var attribute in attributeList.Attributes) { ChangeEventQueueForAttributes(attribute, parent, eventType, eventQueue); } } else if (node is AttributeSyntax attribute) { ChangeEventQueueForAttributes(attribute, parent, eventType, eventQueue); } else { eventQueue.EnqueueChangeEvent(node, parent, eventType); } }
private EnvDTE80.vsCMChangeKind ConvertToChangeKind(CodeModelEventType eventType) { EnvDTE80.vsCMChangeKind result = 0; if ((eventType & CodeModelEventType.Rename) != 0) { result |= EnvDTE80.vsCMChangeKind.vsCMChangeKindRename; } if ((eventType & CodeModelEventType.Unknown) != 0) { result |= EnvDTE80.vsCMChangeKind.vsCMChangeKindUnknown; } if ((eventType & CodeModelEventType.BaseChange) != 0) { result |= EnvDTE80.vsCMChangeKind.vsCMChangeKindBaseChange; } if ((eventType & CodeModelEventType.TypeRefChange) != 0) { result |= EnvDTE80.vsCMChangeKind.vsCMChangeKindTypeRefChange; } if ((eventType & CodeModelEventType.SigChange) != 0) { result |= EnvDTE80.vsCMChangeKind.vsCMChangeKindSignatureChange; } if ((eventType & CodeModelEventType.ArgChange) != 0) { result |= EnvDTE80.vsCMChangeKind.vsCMChangeKindArgumentChange; } return(result); }
private EnvDTE.CodeElement GetAttributeElementForCodeModelEvent(SyntaxNode node, SyntaxNode parentNode, CodeModelEventType eventType, EnvDTE.CodeElements elementsToSearch, object parentObject) { if (elementsToSearch == null) { return(null); } string name; int ordinal; CodeModelService.GetAttributeNameAndOrdinal(parentNode, node, out name, out ordinal); if (eventType == CodeModelEventType.Remove) { if (parentObject is EnvDTE.CodeElement) { var parentCodeElement = ComAggregate.TryGetManagedObject <AbstractCodeElement>(parentObject); if (parentCodeElement != null) { return((EnvDTE.CodeElement)CodeAttribute.Create(this.State, this, parentCodeElement, name, ordinal)); } } else if (parentObject is EnvDTE.FileCodeModel) { var parentFileCodeModel = ComAggregate.TryGetManagedObject <FileCodeModel>(parentObject); if (parentFileCodeModel != null && parentFileCodeModel == this) { return((EnvDTE.CodeElement)CodeAttribute.Create(this.State, this, null, name, ordinal)); } } } else { int testOridinal = 0; foreach (EnvDTE.CodeElement element in elementsToSearch) { if (element.Kind != EnvDTE.vsCMElement.vsCMElementAttribute) { continue; } if (element.Name == name) { if (ordinal == testOridinal) { return(element); } testOridinal++; } } } return(null); }
private static void ChangeEventQueueForAttributes(AttributeSyntax attribute, SyntaxNode parent, CodeModelEventType eventType, CodeModelEventQueue eventQueue) { if (parent is BaseFieldDeclarationSyntax) { foreach (var variableDeclarator in ((BaseFieldDeclarationSyntax)parent).Declaration.Variables) { eventQueue.EnqueueChangeEvent(attribute, variableDeclarator, eventType); } } else { eventQueue.EnqueueChangeEvent(attribute, parent, eventType); } }
protected override void EnqueueChangeEvent(SyntaxNode node, SyntaxNode parent, CodeModelEventType eventType, CodeModelEventQueue eventQueue) { if (eventQueue == null) { return; } if (node is IncompleteMemberSyntax) { return; } if (node is BaseFieldDeclarationSyntax) { foreach (var variableDeclarator in ((BaseFieldDeclarationSyntax)node).Declaration.Variables) { eventQueue.EnqueueChangeEvent(variableDeclarator, parent, eventType); } } else if (node is AttributeListSyntax) { foreach (var attribute in ((AttributeListSyntax)node).Attributes) { ChangeEventQueueForAttributes(attribute, parent, eventType, eventQueue); } } else if (node is AttributeSyntax) { ChangeEventQueueForAttributes((AttributeSyntax)node, parent, eventType, eventQueue); } else { eventQueue.EnqueueChangeEvent(node, parent, eventType); } }
private EnvDTE80.vsCMChangeKind ConvertToChangeKind(CodeModelEventType eventType) { EnvDTE80.vsCMChangeKind result = 0; if ((eventType & CodeModelEventType.Rename) != 0) { result |= EnvDTE80.vsCMChangeKind.vsCMChangeKindRename; } if ((eventType & CodeModelEventType.Unknown) != 0) { result |= EnvDTE80.vsCMChangeKind.vsCMChangeKindUnknown; } if ((eventType & CodeModelEventType.BaseChange) != 0) { result |= EnvDTE80.vsCMChangeKind.vsCMChangeKindBaseChange; } if ((eventType & CodeModelEventType.TypeRefChange) != 0) { result |= EnvDTE80.vsCMChangeKind.vsCMChangeKindTypeRefChange; } if ((eventType & CodeModelEventType.SigChange) != 0) { result |= EnvDTE80.vsCMChangeKind.vsCMChangeKindSignatureChange; } if ((eventType & CodeModelEventType.ArgChange) != 0) { result |= EnvDTE80.vsCMChangeKind.vsCMChangeKindArgumentChange; } return result; }
private EnvDTE.CodeElement GetAttributeElementForCodeModelEvent(SyntaxNode node, SyntaxNode parentNode, CodeModelEventType eventType, EnvDTE.CodeElements elementsToSearch, object parentObject) { if (elementsToSearch == null) { return null; } CodeModelService.GetAttributeNameAndOrdinal(parentNode, node, out var name, out var ordinal); if (eventType == CodeModelEventType.Remove) { if (parentObject is EnvDTE.CodeElement) { var parentCodeElement = ComAggregate.TryGetManagedObject<AbstractCodeElement>(parentObject); if (parentCodeElement != null) { return (EnvDTE.CodeElement)CodeAttribute.Create(this.State, this, parentCodeElement, name, ordinal); } } else if (parentObject is EnvDTE.FileCodeModel) { var parentFileCodeModel = ComAggregate.TryGetManagedObject<FileCodeModel>(parentObject); if (parentFileCodeModel != null && parentFileCodeModel == this) { return (EnvDTE.CodeElement)CodeAttribute.Create(this.State, this, null, name, ordinal); } } } else { int testOrdinal = 0; foreach (EnvDTE.CodeElement element in elementsToSearch) { if (element.Kind != EnvDTE.vsCMElement.vsCMElementAttribute) { continue; } if (element.Name == name) { if (ordinal == testOrdinal) { return element; } testOrdinal++; } } } return null; }
public void EnqueueChangeEvent(SyntaxNode node, SyntaxNode parent, CodeModelEventType eventType) { EnqueueEvent(new CodeModelEvent(node, parent, eventType)); }
public CodeModelEvent(SyntaxNode node, SyntaxNode parentNode, CodeModelEventType type) { this.Node = node; this.ParentNode = parentNode; this.Type = type; }
protected abstract void EnqueueChangeEvent(SyntaxNode node, SyntaxNode parent, CodeModelEventType eventType, CodeModelEventQueue eventQueue);