Skip to content
This repository was archived by the owner on Jun 26, 2020. It is now read-only.

Finish documentation after OT refactor #1509

Merged
merged 3 commits into from
Aug 31, 2018
Merged

Finish documentation after OT refactor #1509

merged 3 commits into from
Aug 31, 2018

Conversation

scofalik
Copy link
Contributor

@scofalik scofalik commented Aug 24, 2018

Suggested merge commit message (convention)

Other: Updated OT documentation. Closes ckeditor/ckeditor5#4380.

Docs: Added docs for code related to OT.
@coveralls
Copy link

coveralls commented Aug 24, 2018

Coverage Status

Coverage decreased (-0.05%) to 98.562% when pulling b398775 on t/new-ot-docs into 49cd795 on master.

@Reinmar
Copy link
Member

Reinmar commented Aug 24, 2018

Coverage decreased? ;>

@scofalik
Copy link
Contributor Author

🤷‍♂️

@scofalik
Copy link
Contributor Author

scofalik commented Aug 24, 2018

Don't worry, I will get CC to 100% in next task :). But yeah, code changed a little little, but it shouldn't have an impact on CC. Code was changed to make some parts more clear.

* @param {module:engine/model/position~Position} data.sourcePosition Source position for move, remove and reinsert change types.
* @param {Object} data Object with additional information about the change.
* @param {null} data.deletionPosition Due to the nature of this event, this property is always set to `null`. It is passed
* for compatibility with {@link module:engine/model/liverange~LiveRange#event:change:range} event.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the sth event

@pjasiun pjasiun self-requested a review August 24, 2018 12:33
// Below we take an operation, check its type, then use its parameters in marking (private) methods.
// The general rule is to not mark elements inside inserted element. All inserted elements are re-rendered.
// Marking changes in them would cause a "double" changing then.
//
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do a lot of those to make comments more readable and separated from code, to make more breathing room so it is easier to read it all. These are not by mistake.

/**
* Checks whether given operation changes something inside the range (even if it does not change boundaries).
*
* @ignore
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually we use // comments instead of @ignore.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed all @ignore occurrences in the engine.

@@ -34,8 +34,7 @@ export default class LivePosition extends Position {
* @see module:engine/model/position~Position
* @param {module:engine/model/rootelement~RootElement} root
* @param {Array.<Number>} path
* @param {module:engine/model/position~PositionStickiness} [stickiness] Position stickiness. Defaults to `'toNone'`.
* See {@link module:engine/model/liveposition~LivePosition#stickiness}.
* @param {module:engine/model/position~PositionStickiness} [stickiness]
Copy link

@pjasiun pjasiun Aug 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any docs?

[stickiness='toNone'] Position stickiness. ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stickiness is described in typedef. I could go with something like See {@link ... } but this is a bit stupid cause in generated docs you will have a link to the typedef next to the parameter.

*
* For example, if `n` nodes are inserted before the position, the returned position {@link ~Position#offset} will be
* increased by `n`. If the position was in a merged element, it will be accordingly moved to the new element, etc.
*
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that this method is also safe to use it on non-existing positions. I you put such information for the previous method maybe all "safe" methods should get this warning?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least all public methods.

* **Note:** transformation may break one range into multiple ranges (e.g. when a part of the range is
* moved to a different part of document tree). For this reason, an array is returned by this method and it
* may contain one or more `Range` instances.
*
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One or more ranges may be returned as a result of this transformation.?

* both transformed `operationsA` and transformed `operationsB` are returned.
*
* Note, that the first operation in each set should base on the same context. A simplified version of context is
* {@link module:engine/model/document~Document#version document version}, so the
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A simplified version of context is document version.

It might be too abstract.

Can you just say:
Note, that the first operation in each set should base on the same document state ({@link module:engine/model/document~Document#version document version}).
?

* Base versions of the transformed operations sets are updated accordingly. For example, if base versions start from `4`
* and there are three operations in `operationsA` and five operations in `operationsB`, then transformed `operationsA`
* will start from base version `9` while transformed `operationsB` will start from base version `7`. If no operation was
* broken into two during transformation, then both sets will end up with an operation that bases on version `11`.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to read this 3 times to get it. What can be improved: three -> 3, five -> 5. Some "math helpers":

  • 9 (4 base + 5 operations A),
  • 7 (4 base + 3 operations B),
  • 11 (4 base + 5 operations A + 3 operation B trandormed by A = 4 base + 3 operations B + 3 operation A trandormed by B = 12, what means that the base of the last operation is 11),

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a note, I just say that describing base versions is difficult, because it is a little abstract concept and the reader won't understand that a version, say, 10 at one client is something different than version 10 on the other client.

So there is a problem, cause if you write too little, the reader will wonder why even care about versions and if you write too much it is too complicated and abstract and too long to comprehend :).

But I tried to clarify this with your suggestions.

* @param {Boolean} [options.useContext=false] Whether during transformation additional context information should be gathered and used.
* @param {Boolean} [options.padWithNoOps=false] Whether additional {@link module:engine/model/operation/nooperation~NoOperation}s
* should be added to the transformation results to force the same last base version for both transformed sets (in case
* if some operations got broken into multiple operations during transformation).
Copy link

@pjasiun pjasiun Aug 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any case where we do not want to pad with no-ops? Undo?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly

//
// So, suppose we have sets of two operations each: `operationsA` = `[ a1, a2 ]`, `operationsB` = `[ b1, b2 ]`.
//
// Remember, that we can only transform operations that base on the same context. We assert that `a1` and `a2` base on
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a1 and a2

a1 and b1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉 somebody read it!

// by `a11'`. Similarly, `a12'` is only transformed by `b1`. This leads to a conclusion that we need to start transforming `a12'`
// from the moment just after it was broken. So, `a12'` is transformed by `b2`. Now, "the whole" `a1` is transformed
// by `operationsB`, while all `operationsB` are transformed by "the whole" `a1`. This means that we can continue with
// following `operationsA` (in our case it is just `a2`).
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe some ASCII arts?

 * -a1-- * -a2- *

 |       |
b1      b1'
 |       |

 * -a1'- *

 |
b2
 |
 *

Or:

                 *
                / \
               a1  b1
              /     \
             *       *
            / \     / \
           a2  b1' a1' b2
          /     \ /     \
         *       *       *

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Especially some arts for operations splitting would be useful.

};

// Initialize context to use during transformations.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if you need to add comments here to EVERYTHING ;)

const opA = operationsA[ i ];

// For the "current" operation `a`, get the index of the next operation `b` to transform by.
const transformByIndex = nextTransformIndex.get( opA );
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not a big fan of this method. transformByIndex sounds more like a function than property.

nextTransformIndex.set( newOpA, transformByIndex + newOpsB.length );
}

// Update `operationsA` and `operationsB` so that in next loops transformed operations are processed.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it is late, but I have no idea what is going on here.

context.relations = new Map();

// Returns whether given operation `op` has already been undone.
//
// This is only used when additional context mode is on (options.useContext == true).
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't all context.* used only when additional context mode is on?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

context.isStrong is used always

// attributes on the inserted nodes in a way which would make the original operation correct:
//
// <p>Fo[z{<$text highlight="red">}x</$text>b]ar</p> <--- Change range `{}` from `red` to `null`.
// <p>Fo[zxb]ar</p> <--- Now change from `null` to `yellow` is completely fine.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something is wrong with indentation.

@@ -500,10 +806,8 @@ function _getComplementaryAttributeOperations( insertOperation, key, newValue )
setTransformation( AttributeOperation, MergeOperation, ( a, b ) => {
const ranges = [];

// Case 1: Attribute change on the merged element. In this case, the merged element was moved to graveyard.
// Case 1: Attribute change on the merged element. In this case, the merged element was moved to the graveyard.
// An additional attribute operation that will change the (re)moved element needs to be generated.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong indentation, use spaces instead of tabs.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the same everywhere in the file. I'll change them all.

* Helper function for `AttributeOperation` x `MoveOperation` transformation.
*
* Takes the passed `range` and transforms it by move operation `moveOp` in a specific way. Only top-level nodes of `range`
* are considered to be in the range. If move operation moves nodes from deep from inside of the range, those nodes won't
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If move operation moves nodes from deep from inside of the range

Is this sentence correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's rap.

* @returns {module:engine/model/operation/moveoperation~MoveOperation}
* @ignore
*/
function _makeMoveOperation( range, targetPosition ) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe move constructor should look like this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, well, maybe but probably nope. Because then you'd be able to pass non-flat range and you'd have to check it. But OTOH it would simplify places where transformation follows this scheme:

  1. Change sourcePosition + howMany into range.
  2. Transform that range.
  3. Read new sourcePosition and howMany from the transformed range and change them in the operation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I removed this function completely.

@pjasiun pjasiun merged commit 011bf56 into master Aug 31, 2018
@pjasiun pjasiun deleted the t/new-ot-docs branch August 31, 2018 16:34
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Finish documentation after OT refactor
4 participants