/// <summary> /// Handler called for every node that is removed (recursively from removedNode to descendants). /// </summary> /// <param name="view">View where node has been removed.</param> /// <param name="removedNode">Node that has been removed.</param> /// <param name="alreadyRemovedChild">Child that has been already removed.</param> private void onNodeRemoved(ExecutionView view, INodeAST removedNode, INodeAST alreadyRemovedChild = null) { if (removedNode == null) { return; } var context = EditContext(view); if (context.IsRemoved(removedNode)) { //we have already registered remove action return; } //report node removing context.NodeRemoved(removedNode); //report parent removing to all children foreach (var removedChild in removedNode.AllChildren) { if (removedChild != alreadyRemovedChild) { onParentRemoved(view, removedChild); } } }
/// <summary> /// Remove token from source in given view. /// </summary> /// <param name="view">View where source node will be removed.</param> /// <param name="token">Token that will be removed.</param> private void remove(ExecutionView view, IToken token) { var p1 = token.Position.Offset; var p2 = token.Position.Offset + token.Value.Length; write(view, p1, p2, ""); }
/// <summary> /// Get sweep line of instance scopes /// at end returns <c>null</c> /// </summary> /// <param name="view">View where scopes are stepped</param> /// <returns>Sweep line if there are available scopes, <c>null</c> otherwise</returns> public IEnumerable <InstanceScope> Step(ExecutionView view) { if (_enumerators == null) { //stepper is already at the end return(null); } var result = (from enumerator in _enumerators select enumerator.Current).ToArray(); var currentEnds = from scope in result select scope.End; var earliestEnd = view.EarliestBlock(currentEnds); foreach (var enumerator in _enumerators) { if (enumerator.Current.End == earliestEnd) { if (!enumerator.MoveNext()) { //there is no more scopes for instance _enumerators = null; } break; } } return(result); }
/// <summary> /// Dialog for getting path input. /// </summary> /// <param name="view">The view.</param> /// <returns>System.Object.</returns> private object _pathInput(ExecutionView view) { var oldPath = FullPath.Get(); if (oldPath == null) { oldPath = ResolveFullPath(".", Services); } var fullpath = Dialogs.PathProvider.GetFolderPath(oldPath); if (fullpath == null) { view.Abort("Path hasn't been selected"); return(null); } var relative = RelativePath(Services.CodeBaseFullPath, fullpath); if (relative.Length > fullpath.Length) { return(fullpath); } return(relative); }
/// <summary> /// Reports the view commit. /// </summary> /// <param name="view">The view.</param> internal void ReportViewCommit(ExecutionView view) { if (OnViewCommit != null) { OnViewCommit(view); } }
internal EditContext(ExecutionView view, Source source, string code) { _view = view; Code = code; Strips = new StripManager(Code); _source = source; }
/// <summary> /// Remove node from source in given view. Is only syntactical. Should be called only after /// proper node hierarchy remove handling. /// </summary> /// <param name="view">View where source node will be removed.</param> /// <param name="node">Node that will be removed.</param> private void remove(ExecutionView view, INodeAST node) { int p1, p2; getBorderPositions(node, out p1, out p2); write(view, p1, p2, ""); }
/// <summary> /// Write data to region between start, end. /// </summary> /// <param name="view">The view.</param> /// <param name="start">Start offset of replaced region.</param> /// <param name="end">End offset of replaced region.</param> /// <param name="data">Written data.</param> private void write(ExecutionView view, int start, int end, string data) { EditContext(view).Strips.Remove(start, end - start); if (data.Length > 0) { EditContext(view).Strips.Write(start, data); } }
public static bool Shift(ExecutedBlock toShift, ExecutedBlock target, ExecutionView view) { var shiftTransformation = new ShiftBehindTransformation(toShift, target); view.Apply(shiftTransformation); return(!view.IsAborted); }
public ScopeMonitor(IEnumerable <Instance> instances, ExecutionView view) { _monitoredInstances = new HashSet <Instance>(instances); var instanceStarts = from instance in instances where instance.CreationBlock != null select instance.CreationBlock; var earliestStart = view.EarliestBlock(instanceStarts); initializeScopes(view, earliestStart); }
/// <summary> /// Mark given node as removed by given child. Marked node has no chance to be /// preserved and has to be removed. It is possible to recursively mark parent /// and let be removed by the parent. /// </summary> /// <param name="view">View where node has been removed.</param> /// <param name="removedNode">Node that is removed.</param> /// <param name="markingChild">Child that marked its parent as removed.</param> private void markRemoved(ExecutionView view, INodeAST removedNode, INodeAST markingChild) { //report parent removing to all children except marking child onNodeRemoved(view, removedNode, markingChild); var parent = removedNode.Parent; var parentType = parent == null ? NodeTypes.hierarchy : parent.NodeType; //detect that parent has to be marked as removed var removeParent = false; switch (parentType) { case NodeTypes.call: if (isOptionalArgument(parent, removedNode)) { removeParent = false; //removed node is optional node of its parent //check only for remaining argument delimiters var argCount = parent.Arguments.Length; if (argCount > 1) { //there is delimiter that should be also removed var argIndex = parent.GetArgumentIndex(removedNode); //last argument has leading delimiter, non last has trailing delimiter var isLastArg = argCount - 1 == argIndex; var delimiterToken = isLastArg ? removedNode.StartingToken.Previous : removedNode.EndingToken.Next; remove(view, delimiterToken); } } else { //non optional argument cannot be removed from parent //so we will remove parent removeParent = true; } break; default: removeParent = true; break; } //handle removing if (parent != null && removeParent) { markRemoved(view, parent, removedNode); } else { //removedNode is last removed node in hierarchy - remove it from source remove(view, removedNode); } }
/// <summary> /// Append call at new line after lineNode. /// </summary> /// <param name="view">View where transformation is processed.</param> /// <param name="lineNode">Node with line where call will be appended.</param> /// <param name="call">Prepended call.</param> internal void PrependCall(ExecutionView view, INodeAST lineNode, CallEditInfo call) { var callRepresentation = callToCSharp(call); ensureNamespaces(view, call); var beforeLineOffset = getBeforeOffset(lineNode); write(view, beforeLineOffset, callRepresentation); }
/// <summary> /// Rewrite given node with code representation of given value. /// </summary> /// <param name="view">View where transformation is processed.</param> /// <param name="node">Node that is rewritten.</param> /// <param name="value">Value which rewrite given node.</param> internal void Rewrite(ExecutionView view, INodeAST node, object value) { preserveSideEffect(view, node); int p1, p2; getBorderPositions(node, out p1, out p2); write(view, p1, p2, toCSharp(value)); }
/// <summary> /// Gets the source of method with given <see cref="MethodID"/>. /// </summary> /// <param name="method">The method.</param> /// <param name="view">The view.</param> /// <returns>System.String.</returns> public string GetSource(MethodID method, ExecutionView view) { var parsedGenerator = _methods.AccordingId(method) as ParsedGenerator; if (parsedGenerator == null) { return("Source not available for " + method); } return(parsedGenerator.Source.GetCode(view)); }
/// <summary> /// Processes given remove edits. /// </summary> /// <param name="result">The result.</param> /// <param name="view">The view.</param> /// <param name="editAction">The edit action.</param> /// <returns>ExecutionView.</returns> /// <exception cref="System.NotSupportedException">Remove edit doesn't succeeded</exception> private static ExecutionView processRemoveEdit(AnalyzingResult result, ExecutionView view, EditAction editAction) { var inst = result.EntryContext.GetValue(editAction.Variable); var success = view.Remove(inst); if (!success) { throw new NotSupportedException("Remove edit doesn't succeeded"); } return(view); }
/// <summary> /// Accepts the component by appending to ComposeParts call. /// </summary> /// <param name="e">The edits provider used for accepting.</param> /// <param name="view">The view where instance will be accepted.</param> /// <returns>Variable with accepted instance and correct scope.</returns> private object acceptAppendComponent(EditsProvider e, ExecutionView view) { var toAccept = UserInteraction.DraggedInstance; var componentInfo = Services.GetComponentInfo(toAccept.Info); if (componentInfo == null) { view.Abort("Can accept only components"); return(null); } return(e.GetVariableFor(toAccept, view)); }
/// <summary> /// Preserve side effect of node in given view. /// </summary> /// <param name="view">View where side effect is preserved.</param> /// <param name="node">Node which side effect is preserved.</param> private void preserveSideEffect(ExecutionView view, INodeAST node) { if (!hasSideEffect(node)) { return; } var keepExpression = getCode(node) + ";\n"; var insertPos = BeforeStatementOffset(node); write(view, insertPos, keepExpression); }
/// <summary> /// Accepts the component. /// </summary> /// <param name="view">The view where component will be accepted.</param> /// <returns>CallEditInfo.</returns> private CallEditInfo acceptComponent(ExecutionView view) { var toAccept = UserInteraction.DraggedInstance; var componentInfo = Services.GetComponentInfo(toAccept.Info); if (componentInfo == null) { view.Abort("Can accept only components"); return(null); } return(new CallEditInfo(This, "AddPart", toAccept)); }
/// <summary> /// Handler for accept catalog edit. /// </summary> /// <param name="view">The view.</param> /// <returns>CallEditInfo.</returns> private CallEditInfo acceptCatalog(ExecutionView view) { var instance = UserInteraction.DraggedInstance; var isCatalog = Services.IsAssignable(TypeDescriptor.Create <ComposablePartCatalog>(), instance.Info); if (!isCatalog) { view.Abort("AggregateCatalog can only accept part catalogs"); return(null); } return(new CallEditInfo(This, "Catalogs.Add", instance)); }
/// <summary> /// Dialog for path input. /// </summary> /// <param name="view">View where path edit will be processed.</param> /// <returns>System.Object.</returns> private object _pathInput(ExecutionView view) { var oldPath = FullPath.Get(); var path = Dialogs.PathProvider.GetAssemblyPath(oldPath); if (path == null) { view.Abort("Path hasn't been selected"); return(null); } return(path); }
/// <summary> /// Dialog for getting pattern input. /// </summary> /// <param name="view">The view.</param> /// <returns>System.Object.</returns> private object _patternInput(ExecutionView view) { var oldPattern = Pattern.Get(); var inputPattern = Dialogs.ValueProvider.GetSearchPattern(oldPattern); if (inputPattern == null || inputPattern == "") { view.Abort("No pattern has been selected"); return(null); } return(inputPattern); }
/// <summary> /// Accepts the component. /// </summary> /// <param name="thisObj">The this object.</param> /// <param name="services">The services.</param> /// <returns>CallEditInfo.</returns> private CallEditInfo acceptComponent(Instance thisObj, ExecutionView services) { var instance = UserInteraction.DraggedInstance; var componentInfo = Services.GetComponentInfo(instance.Info); if (componentInfo == null) { //allow accepting only components services.Abort("CompositionTester can only accept components"); return(null); } return(new CallEditInfo(thisObj, "Add", instance)); }
/// <summary> /// Accepts the part catalog in constructor. /// </summary> /// <param name="e">The edits provider used for accepting.</param> /// <param name="view">The view where instance will be accepted.</param> /// <returns>Variable with accepted catalog and correct scope.</returns> private object acceptPartCatalog(EditsProvider e, ExecutionView view) { var instance = UserInteraction.DraggedInstance; var isCatalog = Services.IsAssignable(TypeDescriptor.Create <ComposablePartCatalog>(), instance.Info); if (!isCatalog) { //allow accepting only components view.Abort("CompositionContainer can accept only single part catalog"); return(null); } return(e.GetVariableFor(instance, view)); }
/// <summary> /// Dialog for adding component type. /// </summary> /// <param name="callerAssembly">The caller assembly.</param> /// <param name="v">View where component type will be added.</param> /// <returns>System.Object.</returns> private object addComponentTypeProvider(TypeAssembly callerAssembly, ExecutionView v) { var components = getComponents(callerAssembly); var dialog = new ComponentType(components); if (dialog.ShowDialog() == true) { return(dialog.SelectedComponent); } else { v.Abort("No component has been selected"); return(null); } }
/// <summary> /// Add component into composition point. /// </summary> /// <param name="component">The component to add.</param> /// <param name="v">View of composition point.</param> /// <returns>Edit info for component adding.</returns> private CallEditInfo addComponent(ComponentInfo component, ExecutionView v) { var call = new CallEditInfo(component.ComponentType, Naming.CtorName); var name = TypeSystem.Dialogs.VariableName.GetName(component.ComponentType, _currentResult.EntryContext); if (name == null) { v.Abort("User aborted component adding"); return(null); } call.ReturnName = name; return(call); }
/// <summary> /// Shift shiftedLine behind behindLine in given view. /// </summary> /// <param name="view">View where transformation is processed.</param> /// <param name="shiftedLine">Line that will be shifted behind behindLine.</param> /// <param name="behindLine">Line that will be before shiftedLine.</param> internal void ShiftBehind(ExecutionView view, INodeAST shiftedLine, INodeAST behindLine) { INodeAST currentShiftedLine; INodeAST currentBehindLine; findShiftLines(shiftedLine, behindLine, out currentShiftedLine, out currentBehindLine); var shiftTargetOffset = getBehindOffset(currentBehindLine); int shiftStart, shiftEnd; getBorderPositions(currentShiftedLine, out shiftStart, out shiftEnd); var shiftLen = shiftEnd - shiftStart; move(view, shiftStart, shiftTargetOffset, shiftLen); }
/// <summary> /// Is called when parent of given node has been removed. If node has side effect it will be preserved. /// </summary> /// <param name="view">View where parent has been removed.</param> /// <param name="node">Node which parent has been removed.</param> private void onParentRemoved(ExecutionView view, INodeAST node) { if (node == null) { return; } if (hasSideEffect(node)) { preserveSideEffect(view, node); } else { onNodeRemoved(view, node); } }
/// <summary> /// Accepts the instance in given view. /// </summary> /// <param name="view">The view where instance will be accepted.</param> /// <returns>Accepting call.</returns> private CallEditInfo acceptInstance(ExecutionView view) { var toAccept = UserInteraction.DraggedInstance; if (Services.IsAssignable(CompositionBatchDefinition.Info, toAccept.Info)) { return(new CallEditInfo(This, "Compose", toAccept)); } var componentInfo = Services.GetComponentInfo(toAccept.Info); if (componentInfo == null) { view.Abort("Can accept only components"); return(null); } return(new CallEditInfo(TypeDescriptor.Create(typeof(AttributedModelServices)), "ComposeParts", true, This, toAccept)); }
/// <summary> /// Ensure that required namespaces are present. /// </summary> /// <param name="view">The view.</param> /// <param name="call">Call which namespaces are required.</param> private void ensureNamespaces(ExecutionView view, CallEditInfo call) { if (!call.IsExtensionCall) { return; } var typeSignature = PathInfo.GetSignature(call.ThisObj as TypeDescriptor); var lastDot = typeSignature.LastIndexOf('.'); if (lastDot <= 0) { //there is no required namespace return; } var ns = typeSignature.Substring(0, lastDot); EditContext(view).EnsureNamespace(ns); }
/// <summary> /// Shift given shiftedBlock behind target, if possible /// </summary> /// <param name="shiftedBlock"></param> /// <param name="target"></param> /// <param name="view"></param> private bool shiftBehind(ExecutedBlock shiftedBlock, ExecutedBlock target, ExecutionView view) { //cumulative list of blocks that has to be shifted //It has reverse ordering of transformations that will be generated var shiftedBlocks = new List <ExecutedBlock>(); shiftedBlocks.Add(shiftedBlock); var borderInstances = new HashSet <Instance>(); borderInstances.UnionWith(view.AffectedInstances(shiftedBlock)); //find all colliding blocks, so we can move them with shifted block if possible var currentBlock = shiftedBlock; while (currentBlock != target) { currentBlock = view.NextBlock(currentBlock); if (!canCross(currentBlock, borderInstances, view)) { //this block cannot be crossed borderInstances.UnionWith(view.AffectedInstances(currentBlock)); shiftedBlocks.Add(currentBlock); } } //shifting is not possible, due to collisions between blocks if (!canCross(target, borderInstances, view)) { return(false); } shiftedBlocks.Reverse(); foreach (var block in shiftedBlocks) { view.ShiftBehind(block, target); } return(true); }