/// <summary> /// Validates the document and updates the descriptor. /// </summary> /// <param name="document"> /// The document. /// </param> /// <param name="descriptorToUpdate"> /// The descriptor to update. /// </param> private void ValidateDocument([NotNull] ParsedDocument document, [NotNull] SerializableDocumentDescriptor descriptorToUpdate) { document.Root = Validator.Validate(document.Context, document.Root, out var functionDefinitions); var messages = document.Context.Messages.Select(message => new SerializableMessage(message)).ToArray(); var functions = functionDefinitions.SelectMany(lookup => lookup.Select(function => new SerializableFunctionDescriptor(lookup.Key, function))).ToArray(); descriptorToUpdate.Messages = messages; descriptorToUpdate.Functions = functions; descriptorToUpdate.Plugins = document.Context.GetPlugins().Select(p => p.Name).ToList(); }
private ParsedDocument ParseContent(string content, [NotNull] SerializableDocumentDescriptor descriptorToUpdate) { using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(content))) { var tokens = new List <Token>(); var context = new ExecutionContextImplementation(this.session.Context, this.Filename); var root = ConnectQlContext.Parse(stream, context.NodeData, context.Messages, true, tokens); descriptorToUpdate.Tokens = Classifier.Classify(tokens).Select(token => new SerializableToken(token)).ToArray(); return(new ParsedDocument(context, root)); } }
private SerializableDocumentDescriptor GetChanges(SerializableDocumentDescriptor currentDocument) { var result = new SerializableDocumentDescriptor { Filename = this.Filename, Version = this.Version }; var updated = this.TryUpdate(currentDocument, result, d => d.Tokens) | this.TryUpdate(currentDocument, result, d => d.Functions) | this.TryUpdate(currentDocument, result, d => d.Messages) | this.TryUpdate(currentDocument, result, d => d.Sources) | this.TryUpdate(currentDocument, result, d => d.Variables) | this.TryUpdate(currentDocument, result, d => d.Plugins); return(updated ? result : null); }
/// <summary> /// Tries to update the property that the selector uses. /// </summary> /// <param name="newDocument"> /// The new version of the document. Only non-null items are updated in the current document. /// </param> /// <param name="delta"> /// The delta document. Has all changes that differ from the document. /// </param> /// <param name="selector"> /// Returns the <see cref="IEnumerable{T}"/> to update. /// </param> /// <typeparam name="T"> /// The type of the items in the selector. /// </typeparam> /// <returns> /// True if the document was updated, false otherwise. /// </returns> private bool TryUpdate <T>(SerializableDocumentDescriptor newDocument, SerializableDocumentDescriptor delta, [NotNull] Expression <Func <SerializableDocumentDescriptor, IReadOnlyList <T> > > selector) { var propertyInfo = (PropertyInfo)((MemberExpression)selector.Body).Member; var getValue = selector.Compile(); var newValue = getValue(newDocument); var existingValue = getValue(this.Descriptor); if (newValue == null || existingValue != null && EnumerableComparer.Equals(newValue, existingValue)) { return(false); } propertyInfo.SetValue(delta, newValue); propertyInfo.SetValue(this.Descriptor, newValue); return(true); }
/// <summary> /// Parses this document. /// </summary> /// <param name="documentText"> /// The document Text. /// </param> private void Update(string documentText) { Action updateIntellisenseData = null; updateIntellisenseData = () => { try { var descriptor = new SerializableDocumentDescriptor(); var parsedDocument = this.ParseContent(documentText, descriptor); var delta = this.GetChanges(descriptor); if (delta != null) { this.session.OnDocumentChanged(delta); } if (this.Contents == documentText) { this.ValidateDocument(parsedDocument, descriptor); delta = this.GetChanges(descriptor); if (delta != null) { this.session.OnDocumentChanged(delta); } } if (this.Contents == documentText) { var data = Evaluator.GetIntellisenseData(parsedDocument, descriptor.Tokens); delta = this.GetChanges(new SerializableDocumentDescriptor { Variables = data.Variables.ToArray(), Sources = data.Sources.ToArray(), }); if (delta != null) { this.session.OnDocumentChanged(delta); } } var shouldUpdate = false; lock (this.updateLock) { if (this.Contents == documentText) { this.updating = false; } else { shouldUpdate = true; } } if (shouldUpdate) { documentText = this.Contents; Task.Run(updateIntellisenseData); } } catch { lock (this.updateLock) { this.updating = false; } } }; Task.Run(updateIntellisenseData); }
/// <summary> /// Sends the classification changed event. /// </summary> /// <param name="document"> /// The serialized document. /// </param> internal void OnDocumentChanged(SerializableDocumentDescriptor document) { this.DocumentUpdated?.Invoke(this, new DocumentUpdatedEventArgs(document)); this.InternalDocumentUpdated?.Invoke(this, ProtocolSerializer.Serialize(document)); }