1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-04-10 19:38:34 +02:00
Commit graph

136 commits

Author SHA1 Message Date
Andre Klapper
b44b566b13 Add missing variable names to PHPDoc @param of methods
Summary:
Add variable names (`$varname` in `@param type $varname explanation`) to PHPDoc method headers, for fun and profit.

Closes T15923

Test Plan:
* Read the method signatures and their corresponding PHPDoc headers at your fireplace
* Still run `./bin/diviner generate` without explosions (though it is very lenient anyway?)

Reviewers: O1 Blessed Committers, valerio.bozzolan

Reviewed By: O1 Blessed Committers, valerio.bozzolan

Subscribers: tobiaswiese, valerio.bozzolan, Matthew, Cigaryno

Maniphest Tasks: T15923

Differential Revision: https://we.phorge.it/D25794
2024-08-21 15:06:26 +02:00
epriestley
ad880491e8 Remove product literal strings in "pht()", part 5
Summary: Ref T13658

Test Plan:
This test plan is non-exhaustive.

  - Looked at some of the config.
  - Looked at guides.

Maniphest Tasks: T13658

Differential Revision: https://secure.phabricator.com/D21769
2022-04-25 12:22:27 -07:00
epriestley
dbdfac1e07 Recover inline comments which are "adjusted" off the end of a diff
Summary:
See PHI1834. Currently, the inline adjustment engine can sometime "adjust" an inline off the end of a diff. If it does, we lay it out on an invalid display line here and never render it.

Instead, make sure that layout never puts a comment on an invalid line, so the UI is robust against questionable decisions by the adjustment engine: no adjustment should be able to accidentally discard an inline.

Test Plan:
  - Created a two diff revision, where Diffs 1 and 2 have "alphabet.txt" with A-Z on one line each. The file is unchanged across diffs; some other file is changed.
  - Added a comment to lines P-Z of Diff 1.
  - Before: comment is adjusted out of range on Diff 2 and not shown in the UI.
  - After: comment is still adjusted out of range internally, but now corrected into the display range and shown.

Differential Revision: https://secure.phabricator.com/D21435
2020-08-05 13:12:52 -07:00
epriestley
017ef1927c Revert use of "user-select: all" to modify tab selection behavior
Summary:
Reverts D21419. See PHI1814. Previously, I used "user-select: all" to group sequences of spaces for selection.

However, this has a side effect: the sequence is now selected with a single click. I didn't read the docuementation on the CSS property thoroughly and missed this in testing, since I was focused on drag-selection behavior.

This behavior is enough of a net negative that I think we're in a worse state overall; revert it.

Test Plan: Straight revert.

Differential Revision: https://secure.phabricator.com/D21429
2020-07-24 13:41:26 -07:00
epriestley
0ed5569e9f Likely, fix a warning when rendering modified coverage
Summary: See PHI1819. This structure may have `null` elements.

Test Plan: Will confirm user reproduction case.

Differential Revision: https://secure.phabricator.com/D21420
2020-07-17 19:45:26 -07:00
epriestley
37ffb71c4d In source views, wrap display tabs in "user-select: all" to improve cursor selection behavior
Summary:
Ref T2495. See PHI1814. Currently, Phabricator replaces tabs with spaces when rendering diffs.

This may or may not be the best behavior in the long term, but it gives us more control over expansion of tabs than using tab literals.

However, one downside is that you can use your mouse cursor to select "half a tab", and can't use your mouse cursor to distinguish between tabs and spaces. Although you probably shouldn't be doing this, this behavior is less accurate/correct than selecting the entire block as a single unit.

A specific correctness issue with this behavior is that the entire block is copied to the clipboard as a tab literal if you select any of it, so two different visual selection ranges can produce the same clipboard content.

This particular behavior can be improved with "user-select: all", to instruct browsers to select the entire element as a single logical element. Now, selecting part of the tab selects the whole thing, as though it were really a tab literal.

(Some future change might abandon this approach and opt to use real tab literals with "tab-size" CSS, but we lose some ability to control alignment behavior if we do that and it doesn't have any obvious advantages over this approach other than cursor selection behavior.)

Test Plan:
  - In Safari and Firefox, dragged text to select a whitespace-expanded tab literal. Saw browsers select the whole sequence as though it were a single tab.
  - In Chorme, this also mostly works, but there's some glitchiness and flickering. I think this is still a net improvement, it's just not as smooth as Safari and Firefox.

Maniphest Tasks: T2495

Differential Revision: https://secure.phabricator.com/D21419
2020-07-17 15:10:06 -07:00
epriestley
6d0dbeb77f Use the changeset parse cache to cache suggestion changesets
Summary:
Ref T13513. Syntax highlighting is potentially expensive, and the changeset rendering pipeline can cache it. However, the cache is currently keyed ONLY by Differential changeset ID.

Destroy the existing cache and rebuild it with a more standard cache key so it can be used in a more ad-hoc way by inline suggestion snippets.

Test Plan: Used Darkconsole, saw cache hits and no more inline syntax highlighting for changesets with many inlines.

Subscribers: PHID-OPKG-gm6ozazyms6q6i22gyam

Maniphest Tasks: T13513

Differential Revision: https://secure.phabricator.com/D21280
2020-05-20 14:29:27 -07:00
epriestley
10f241352d Render inline comment suggestions as real diffs
Summary: Ref T13513. When rendering an inline suggestion for display, use highlighting and diffing.

Test Plan: {F7495053}

Maniphest Tasks: T13513

Differential Revision: https://secure.phabricator.com/D21277
2020-05-20 14:27:40 -07:00
epriestley
df139f044b Render proper "Show Context" links in DocumentEngine diffs, not just bullets
Summary:
Ref T13513. Currently, viewing a Jupyter document, hidden context just gets a plain "* * *" facade with no way to expand it.

Support click-to-expand, like source changes.

Test Plan:
  - Clicked to expand various Jupyter diffs.
  - Clicked to expand normal source changes.

Maniphest Tasks: T13513

Differential Revision: https://secure.phabricator.com/D21243
2020-05-12 16:09:22 -07:00
epriestley
acc1fa1655 Make "View as Document Type..." only show valid options
Summary:
Ref T13513. Currently, "View as Document Type..." lists every available engine.

This is hard to get completely right because we can't always rebuild the document ref accurately in the endpoint, but try harder to fake something reasonable.

Test Plan: Used "View as Document Type..." on Jupyter notebooks, was given "Jupyter" and "Source" as options.

Maniphest Tasks: T13513

Differential Revision: https://secure.phabricator.com/D21241
2020-05-12 14:25:37 -07:00
epriestley
0cca40db3b When creating an inline, save the current document engine
Summary:
Ref T13513. As part of inline metadata, save the document engine the change is being rendered with.

This will allow other parts of the UI to detect that an inline was created on a Jupyter notebook but is being rendered on raw source, or whatever else.

The immediate goal is to fix nonsensical inline snippet rendering in email on Jupyter notebooks.

Test Plan:
  - Created inlines and replies on normal soure code, saw no document engine annotated in the database.
  - Created inlines and replies on a Jupyter notebook rendered in Jupyter mode, saw "jupyter" annotations in the database.
  - Swapped document engines between Jupyter and Source, etc.

Maniphest Tasks: T13513

Differential Revision: https://secure.phabricator.com/D21240
2020-05-12 14:25:09 -07:00
epriestley
fe501bd7f7 Save drafts for inline comments currently being edited
Summary:
Ref T13513. As users type text into inline comments, save the comment state as a draft on the server.

This has some rough edges, particularly around previews, but mostly works. See T13513 for notes.

Test Plan: Started an inline, typed some text, waited a second, reloaded the page, saw an editing inline with the saved text.

Maniphest Tasks: T13513

Differential Revision: https://secure.phabricator.com/D21216
2020-05-04 13:19:42 -07:00
epriestley
b48a22bf50 Make "editing" state persistent for inline comments
Summary:
Ref T13513. This is mostly an infrastructure cleanup change.

In a perfect world, this would be a series of several changes, but they're tightly interconnected and don't have an obvious clean, nontrivial partition (or, at least, I don't see one). Followup changes will exercise this code repeatedly and all of these individual mutations are "obviously good", so I'm not too worried about the breadth of this change.

---

Inline comments are stored as transaction comments in the `PhabricatorAuditTransactionComment` and `DifferentialTransactionComment` classes.

On top of these two storage classes sit `PhabricatorAuditInlineComment` and `DifferentialInlineComment`. Historically, these were an indirection layer over significantly different storage classes, but nowadays both storage classes look pretty similar and most of the logic is actually the same. Prior to this change, these two classes were about 80% copy/pastes of one another.

Part of the reason they're so copy/pastey is that they implement a parent `Interface`. They are the only classes which implement this interface, and the interface does not provide any correctness guarantees (the storage objects are not actually constrained by it).

To simplify this:

  - Make `PhabricatorInlineCommentInterface` an abstract base class instead.
  - Lift as much code out of the `Audit` and `Differential` subclasses as possible.
  - Delete methods which no longer have callers, or have only trivial callers.

---

Inline comments have two `View` rendering classes, `DetailView` and `EditView`. They share very little code.

Partly, this is because `EditView` does not take an `$inline` object. Historically, it needed to be able to operate on inlines that did not have an ID yet, and even further back in history this was probably just an outgrowth of a simple `<form />`.

These classes can be significantly simplified by passing an `$inline` to the `EditView`, instead of individually setting all the properties on the `View` itself. This allows the `DetailView` and `EditView` classes to share a lot of code.

The `EditView` can not fully render its content. Move the content rendering code into the view.

---

Prior to this change, some operations need to work on inlines that don't have an inline ID yet (we assign an ID the first time you "Save" a comment). Since "editing" comments will now be saved, we can instead create a row immediately.

This means that all the inline code can always rely on having a valid ID to work with, even if that ID corresponds to an empty, draft, "isEditing" comment. This simplifies more code in `EditView` and allows the "create" and "reply" code to be merged in `PhabricatorInlineCommentController`.

---

Client-side inline events are currently handled through a mixture of `ChangesetList` listeners (good) and ad-hoc row-level listeners (less good). In particular, the "save", "cancel", and "undo" events are row-level. All other events are list-level.

Move all events to list-level. This is supported by all inlines now having an ID at all stages of their lifecycle.

This allows some of the client behavior to be simplified. It currently depends on binding complex ad-hoc dictionaries into event handlers in `_drawRows()`, but it seems like almost all of this code can be removed. In fact, no more than one row ever seems to be drawn, so this code can probably be simplified further.

---

Finally, save an "isEditing" state. When we rebuild a revision on the client, click the "edit" button if it's in this state. This is a little hacky, but simpler to get into a stable state, since the row layout of an inline depends on a "view row" followed by an "edit row".

Test Plan:
  - Created comments on either side of a diff.
  - Edited a comment, reloaded, saw edit stick.
  - Saved comments, reloaded, saw save stick.
  - Edited a comment, typed text, cancelled, "unedited" to get state back.
  - Created a comment, typed text, cancelled, "unedited" to get state back.
  - Deleted a comment, "undeleted" to get state back.

Weirdness / known issues:

  - Drafts don't autosave yet.
  - Fixed in D21187:
    - When you create an empty comment then reload, you get an empty editor. This is a bit silly.
    - "Cancel" does not save state, but should, once drafts autosave.
  - Mostly fixed in D21188:
    - "Editing" comments aren't handled specially by the overall submission flow.
    - "Editing" comments submitted in that state try to edit themselves again on load, which doesn't work.

Subscribers: jmeador

Maniphest Tasks: T13513

Differential Revision: https://secure.phabricator.com/D21186
2020-05-04 13:10:30 -07:00
epriestley
17426a60f0 Fix an issue where text intradiff bodies may not render
Summary:
Ref T13523. In the caching layer, there's a tricky clause about filetypes that skips some body rendering behavior.

Provide file type information which at least has a better chance of representing all changes (e.g., an image file may be replaced with a text file, but this can not be represented by a single file type).

Formalize "hasSourceTextBody()", to mean the changeset parser should engage the change as source text.

Test Plan: Intradiffed text changes, saw the body render properly.

Maniphest Tasks: T13523

Differential Revision: https://secure.phabricator.com/D21210
2020-05-04 07:40:47 -07:00
epriestley
befeb17f6f Improve the construction of synthetic "comparison/intradiff" changesets
Summary:
Ref T13523. Currently, when building a "comparison" changeset, metadata is taken from the left changeset. This is somewhat arbitrary.

This means that intradiffs of images don't work properly because the rendered changeset has only the left (usually "old") information.

Later, some of the code attempts to ignore the file data stored on the changeset and reconstruct the correct file data, which is how the result ends up not-completely-wrong.

Be more careful about building sensible-ish metadata, and then just use it directly later on. This fixes the "spooky" code referencing D955 + D6851.

There are some related issues, where "change type" and "file type" are selected arbitrarily and then used to determine whether the change has an "old/new" state or not (i.e., is the left side of the diff empty, since the change creates the file)?

In many cases, neither of the original changesets have a "change type" which will answer this question correctly. Separate this concept from "has state" from "change type", and make more of the code ask narrower questions about the specific conditions or states it cares about, rather than "change type".

Test Plan:
  - Created a revision with Diff 1, Diff 2, and Diff 3. Diff 1 takes an image from "null -> A". Diff 2 takes the same image from "null -> B". Diff 3 takes the same image from "A -> B'.
  - Intradiffed 1v2 and 1v3.
  - Before patch:
    - Left side usually missing, which is incorrect (should always be "A").
    - Change properties are a mess ("null -> image/png" for MIME type, e.g.)
    - Uninteresting/incorrect "unix:filemode" stuff.
  - After patch;
    - Left side shows state "A".
    - Change properties only show size changes (which is correct).

{F7402012}

Maniphest Tasks: T13523

Differential Revision: https://secure.phabricator.com/D21180
2020-04-28 05:09:22 -07:00
epriestley
aa20faeaa5 Fix an invalid index access for synthetic lint inline comments from Harbormaster
Summary:
Ref T13524. If a Harbormaster lint message has no line number (which is permitted), we try to access an invalid index here. This is an exception after D21044.

Treat comments with no line number as unchanged. These comments do not have "ghost" behavior and do not port across diffs.

Test Plan:
  - Used "harbormaster.sendmessage" to submit lint with no line number on a changeset.
  - Viewed changeset.
    - Before patch: "Undefined index: <null>" error.
    - After patch: Clean changeset with lint message.

{F7400072}

Maniphest Tasks: T13524

Differential Revision: https://secure.phabricator.com/D21178
2020-04-27 14:20:55 -07:00
epriestley
c12db28251 For changesets that affect binaries, use the new binary file content hash as an effect hash
Summary: Ref T13522. When changesets update an image, we currently compute no effect hash. A content hash of the image (or other binary file) is a reasonable effect hash, and enalbes effect-hash-based behavior, including hiding files in intradiffs.

Test Plan:
  - Created a revision affecting `cat.png` and `quack.txt` (currently, there must be 2+ changesets to trigger the hide logic).
  - Updated it with the exact same changes.
  - Viewed revision:
    - Saw the image renderered in the interdiff.
  - Applied patch.
  - Ran `bin/differential rebuild-changesets ...`.
  - Viewed revision:
    - Saw both changesets collapse as unchanged.

Maniphest Tasks: T13522

Differential Revision: https://secure.phabricator.com/D21174
2020-04-27 08:34:55 -07:00
epriestley
b0c295e545 Fix some PHP 7.4 array index access issues
Summary: Ref T13518. See <https://discourse.phabricator-community.org/t/more-exceptions-when-viewing-diffs/3789/>. Under PHP 7.4, accessing an array index of values like `false` and `null` is no longer valid. This is great, but we occasionally do it.

Test Plan:
  - Upgraded to PHP 7.4.
  - Loaded revisions with added/changed lines, inlines, and Asana support configured.
  - Before patch: saw various fatals around accessing indexes of booleans and nulls.
  - After patch: clean revision.

Maniphest Tasks: T13518

Differential Revision: https://secure.phabricator.com/D21172
2020-04-26 08:35:06 -07:00
epriestley
7355bb7f29 Skip "null" lines when constructing raw documents for DocumentEngine rendering
Summary: See <https://discourse.phabricator-community.org/t/more-exceptions-when-viewing-diffs/3789>. This is a similar issue with the same datastructure.

Test Plan: Works correctly under PHP 7.3, but this may not be the end of things.

Differential Revision: https://secure.phabricator.com/D21171
2020-04-25 17:34:45 -07:00
epriestley
befbea2f00 Don't pass "No newline at end of file." annotations to DocumentEngines as literal diff text
Summary: See PHI1707, which has a Jupyter notebook which fails to diff nicely when modified. The root cause seems to be that the document does not end in a newline.

Test Plan: Applied patch, diffed the file, got a Jupyter diff out of it.

Differential Revision: https://secure.phabricator.com/D21159
2020-04-22 20:22:33 -07:00
epriestley
60de1506fe Make "hidden" changesets sticky, and show hidden state in the filetree
Summary:
Ref T13455. Make "hidden" a changeset property similar to other changeset properties.

We don't need to render this on the server, so we make a request (to update the setting) and just discard the response.

Test Plan: {F7375468}

Maniphest Tasks: T13455

Differential Revision: https://secure.phabricator.com/D21158
2020-04-22 16:12:42 -07:00
epriestley
c3c55d82ae Make "renderer", "engine", and "encoding" sticky across reloads in Differential and Diffusion
Summary:
Ref T13455. Update the other "view state" properties to work like "highlight" now works.

Some complexity here arises from these concerns:

  - In "View Standalone", we render the changeset inline. This is useful for debugging/development, and desirable to retain.
  - In all other cases, we render the changeset with AJAX.

So the client needs to be able to learn about the "state" properties of the changeset on two different flows. Prior to this change, each pathway had a fair amount of unique code.

Then, some bookkeeping issues:

  - At inital rendering time, we may not know which renderer will be selected: it may be based on the client viewport dimensions.
  - Prior to this change, the client didn't separate "value of the property for the changeset as rendered" and "desired value of the property".

Test Plan:
  - Viewed changes in Differential, Diffusion, and in standalone mode.
  - Toggled renderer, character sets, and document engine (this one isn't terribly useful). Reloaded, saw them stick.
  - Started typing a comment, cancelled it, hit the undo UI.

Maniphest Tasks: T13455

Differential Revision: https://secure.phabricator.com/D21138
2020-04-19 08:59:09 -07:00
epriestley
8aac55cc57 Make "Highlight As..." sticky across reloads in Diffusion and Differential
Summary:
Ref T13455. Add container-level storage for persistent view state, and persist "Highlight As..." inside it.

The storage generates a "PhabricatorChangesetViewState" configuration object as an output.

When preferences are expressed on a diff and that diff is later attached to a revision, we attempt to copy the preferences.

The internal storage tracks per-changeset settings, but currently always uses "last update wins" to apply the settings in the UI.

Test Plan:
  - Viewed revisions, changed highlighting, reloaded. Saw highlighting stick in revision view and standalone view.
  - Viewed commits, changed highlighting, reloaded. Saw highlighting stick.
  - Created a diff, changed highlighting, turned it into a revision, saw highlighting persist.

Subscribers: jmeador, PHID-OPKG-gm6ozazyms6q6i22gyam

Maniphest Tasks: T13455

Differential Revision: https://secure.phabricator.com/D21137
2020-04-19 08:58:39 -07:00
epriestley
3adf082002 When inlines would disable a file shield in a diff, still apply the shield if all the comments are collapsed
Summary:
Ref T13515. We "shield" some changesets, including generated code and intradiffs with no intermediate changes.

These files don't get shielded if they have inline comments.

But, if the viewer has collapsed all the comments, we can shield the file again.

Test Plan:
  - Created a change affecting files A and B, with three diffs:
    - Touch A and B.
    - Touch B only.
    - Touch nothing.
  - Added an inline to A and collapsed it.
  - Viewed Diff 1 vs Diff 2:
    - Saw A collapse with a note about inlines.
    - Saw B changes, normally.
  - Viewed Diff 2 vs Diff 3:
    - Saw A collapse with a note about inlines.
    - Saw B collapse normally.
  - Uncollapsed the inline, viewed 1v2 and 2v3, saw A expand in both cases.

Maniphest Tasks: T13515

Differential Revision: https://secure.phabricator.com/D21136
2020-04-17 10:52:40 -07:00
epriestley
f9b3e3360b Continue moving classes with no callers in libphutil or Arcanist to Phabricator
Summary: Ref T13395. Move cache classes, syntax highlighters, other markup classes, and sprite sheets to Phabricator.

Test Plan: Attempted to find any callers for any of this stuff in libphutil or Arcanist and couldn't.

Maniphest Tasks: T13395

Differential Revision: https://secure.phabricator.com/D20977
2020-02-12 13:14:04 -08:00
epriestley
292f8fc612 Fix an issue where added or removed source files could incorrectly select a DocumentEngine
Summary:
Ref T13425. The changes in D20865 could incorrectly lead to selection of a DocumentEngine that can not generate document diffs if a file was added or removed (for example, when a source file is added).

Move the engine pruning code to be shared -- we should always discard engines which can't generate a diff, even if we don't have both documents.

Test Plan: Viewed an added source file, no more document ref error arising from document engine selection.

Maniphest Tasks: T13425

Differential Revision: https://secure.phabricator.com/D20866
2019-10-26 12:16:49 -07:00
epriestley
8ff0e3ab35 Support rich diff rendering with DocumentEngine for added/removed files
Summary: Ref T13425. When a file (like a Jupyter notebook) is added or removed, we can still render a useful line-by-line diff.

Test Plan:
  - Viewed add/modify/remove of Jupyter, source code, and images in 2up/1up mode, everything looked okay.

Maniphest Tasks: T13425

Differential Revision: https://secure.phabricator.com/D20865
2019-10-26 08:21:46 -07:00
epriestley
9f7aaa8ee4 Fix an issue where any diff which could possibly be rendered as Jupyter decided to render as Jupyter
Summary:
See PHI1468. Engine selection for diffs is currently too aggressive in trying to find a shared engine and will fall back a shared engine with a very low score, causing all ".json" files to render as Jupyter files.

Only pick an engine as a difference engine by default if it's the highest-scoring engine for the new file.

Test Plan: Viewed ".json" files and ".ipynb" files in a revision. Before, both rendered as Jupyter. Now, the former rendered as JSON and the latter rendered as Jupyter.

Differential Revision: https://secure.phabricator.com/D20850
2019-10-01 18:52:36 -07:00
epriestley
d9515e82a3 Perform basic block interdiffs when diffing abstract blocks, and interdiff markdown in Jupyter notebooks
Summary:
Depends on D20844. Ref T13425. When we line up two blocks and they can be interdiffed (generally: they both have the same type of content), let the Engine interdiff them.

Then, make the Jupyter engine interdiff markdown.

Test Plan: {F6898583}

Maniphest Tasks: T13425

Differential Revision: https://secure.phabricator.com/D20845
2019-09-30 10:43:15 -07:00
epriestley
5afdc620db Make basic Juypter notebook rendering improvements and roughly support folding unchanged context
Summary:
Depends on D20843. Ref T13425. Add very basic support for "Show Hidden Context", in the form of folding it behind an unclickable shield. This isn't ideal, but should be better than nothing.

Prepare for "intraline" diffs on content blocks.

Fix newline handling in Markdown sections in Jupyter notebooks.

Remove the word "visibile" from the codebase.

Test Plan: {F6898192}

Maniphest Tasks: T13425

Differential Revision: https://secure.phabricator.com/D20844
2019-09-30 10:41:21 -07:00
epriestley
a7f3316aa3 Improve sequencing of various content/header checks in abstract block diffs
Summary:
Ref T13425. Some diff checks currently sequence incorrectly:

  - When we're rendering block lists, syntax highlighting isn't relevant.
  - The "large change" guard can prevent rendering of otherwise-renderable changes.
  - Actual errors in the document engine (like bad JSON in a ".ipynb" file) aren't surfaced properly.

Improve sequencing somewhat to resolve these issues.

Test Plan:
  - Viewed a notebook, no longer saw a "highlighting disabled" warning.
  - Forced a notebook to fail, got a useful inline error instead of a popup dialog error.
  - Forced a notebook to have a large number of differences, got a rendering out of it.

Maniphest Tasks: T13425

Differential Revision: https://secure.phabricator.com/D20843
2019-09-30 10:40:12 -07:00
epriestley
1c4450d39f Allow the Jupyter engine to elect to emit diffs, and emit Jupyter documents as blocks
Summary:
Depends on D20832. Ref T13425. Emit Jupyter notebooks as diffable blocks with block keys.

No diffing or proper inlines yet.

Test Plan: {F6888058}

Maniphest Tasks: T13425

Differential Revision: https://secure.phabricator.com/D20833
2019-09-25 16:32:36 -07:00
epriestley
7ae711ed3e Add a "View as..." option to diff dropdowns for selecting between document engines
Summary:
Depends on D20831. Ref T13425. As an escape hatch to get out of future DocumentEngine rendering behavior, provide a "View As.." option.

Now I can break DocumentEngine real bad and no one can complain.

Test Plan: Used "View As" to swap document engines for image files.

Maniphest Tasks: T13425

Differential Revision: https://secure.phabricator.com/D20832
2019-09-25 16:29:21 -07:00
epriestley
bb71ef6ad6 Render image diffs as abstract blocks diffs via DocumentEngine
Summary:
Depends on D20830. Ref T13425. Have the image engine elect into block rendering, then emit blocks.

This is rough (the blocks aren't actually diffed yet) but image diffs were already pretty rough so this is approximately a net improvement.

Test Plan: Viewed image diffs, saw nothing worse than before.

Maniphest Tasks: T13425

Differential Revision: https://secure.phabricator.com/D20831
2019-09-25 16:25:06 -07:00
epriestley
a73f592d7d Allow DocumentEngine to elect into diff construction
Summary:
Ref T13425. Allow DocumentEngines to claim they can produce diffs. If both sides of a change can be diffed by the same document engine and it can produce diffs, have it diff them.

This has no impact on runtime behavior because no upstream engine elects into diff generation yet.

Test Plan: Loaded some revisions, nothing broke.

Maniphest Tasks: T13425

Differential Revision: https://secure.phabricator.com/D20830
2019-09-25 16:23:06 -07:00
epriestley
6bff2cee22 Improve the performance of tab replacement in common cases
Summary:
See PHI1210. For certain large inputs, we spend more time than we need to replacing tabs with spaces. Add some fast paths:

  - When a line only has tabs at the beginning of the line, we don't need to do as much work parsing the rest of the line.
  - When a line has no unicode characters, we don't need to vectorize it to get the right result.

Test Plan:
  - Added test coverage.
  - Profiled this, got a ~60x performance increase on a 36,000 line 3MB text file.

Reviewers: amckinley

Reviewed By: amckinley

Differential Revision: https://secure.phabricator.com/D20477
2019-05-16 12:28:39 -07:00
epriestley
fe7047d12d Display some invisible/nonprintable characters in diffs by default
Summary:
Ref T12822. Ref T2495. This is the good version of D20193.

Currently, we display various nonprintable characters (ZWS, nonbreaking space, various control characters) as themselves, so they're generally invisible.

In T12822, one user reports that all their engineers frequently type ZWS characters into source somehow? I don't really believe this (??), and this should be fixed in lint.

That said, the only real reason not to show these weird characters in a special way was that it would break copy/paste: if we render ZWS as "🐑", and a user copy-pastes the line including the ZWS, they'll get a sheep.

At least, they would have, until D20191. Now that this whole thing is end-to-end Javascript magic, we can copy whatever we want.

In particular, we can render any character `X` as `<span data-copy-text="Y">X</span>`, and then copy "Y" instead of "X" when the user copies the node. Limitations:

  - If users select only "X", they'll get "X" on their clipboard. This seems fine. If you're selecting our ZWS marker *only*, you probably want to copy it?
  - If "X" is more than one character long, users will get the full "Y" if they select any part of "X". At least here, this only matters when "X" is several spaces and "Y" is a tab. This also seems fine.
  - We have to be kind of careful because this approach involves editing an HTML blob directly. However, we already do that elsewhere and this isn't really too hard to get right.

With those tools in hand:

  - Replace "\t" (raw text / what gets copied) with the number of spaces to the next tab stop for display.
  - Replace ZWS and NBSP (raw text) with a special marker for display.
  - Replace control characters 0x00-0x19 and 0x7F, except for "\t", "\r", and "\n", with the special unicode "control character pictures" reserved for this purpose.

Test Plan:
- Generated and viewed a file like this one:

{F6220422}

- Copied text out of it, got authentic raw original source text instead of displayed text.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T12822, T2495

Differential Revision: https://secure.phabricator.com/D20194
2019-02-19 15:21:44 -08:00
epriestley
3f8eccdaec Put some whitespace behaviors back, but only for "diff alignment", not display
Summary:
Depends on D20185. Ref T13161. Fixes T6791.

See some discusison in T13161. I want to move to a world where:

  - whitespace changes are always shown, so users writing YAML and Python are happy without adjusting settings;
  - the visual impact of indentation-only whitespace changes is significanlty reduced, so indentation changes are easy to read and users writing Javascript or other flavors of Javascript are happy.

D20181 needs a little more work, but generally tackles these visual changes and lets us always show whitespace changes, but show them in a very low-impact way when they're relatively unimportant.

However, a second aspect to this is how the diff is "aligned". If this file:

```
A
```

..is changed to this file:

```
X
A
Y
Z
```

...diff tools will generally produce this diff:

```
+ X
  A
+ Y
+ Z
```

This is good, and easy to read, and what humans expect, and it will "align" in two-up like this:

```
       1 X
1 A    2 A
       3 Y
       4 Z
```

However, if the new file looks like this instead:

```
X
A'
Y
Z
```

...we get a diff like this:

```
- A
+ X
+ A'
+ Y
+ Z
```

This one aligns like this:

```
1 A
        1 X
        2 A'
        3 Y
        4 Z
```

This is correct if `A` and `A'` are totally different lines. However, if `A'` is pretty much the same as `A` and it just had a whitespace change, human viewers would prefer this alignment:

```
        1 X
1 A     2 A'
        3 Y
        4 Z
```

Note that `A` and `A'` are different, but we've aligned them on the same line. `diff`, `git diff`, etc., won't do this automatically, and a `.diff` doesn't have a way to say "these lines are more or less the same even though they're different", although some other visual diff tools will do this.

Although `diff` can't do this for us, we can do it ourselves, and already have the code to do it, because we already nearly did this in the changes removed in D20185: in "Ignore All" or "Ignore Most" mode, we pretty much did this already.

This mostly just restores a bit of the code from D20185, with some adjustments/simplifications. Here's how it works:

  - Rebuild the text of the old and new files from the diff we got out of `arc`, `git diff`, etc.
  - Normalize the files (for example, by removing whitespace from each line).
  - Diff the normalized files to produce a second diff.
  - Parse that diff.
  - Take the "alignment" from the normalized diff (whitespace removed) and the actual text from the original diff (whitespace preserved) to build a new diff with the correct text, but also better diff alignment.

Originally, we normalized with `diff -bw`. I've replaced that with `preg_replace()` here mostly just so that we have more control over things. I believe the two behaviors are pretty much identical, but this way lets us see more of the pipeline and possibly add more behaviors in the future to improve diff quality (e.g., normalize case? normalize text encoding?).

Test Plan:
{F6217133}

(Also, fix a unit test.)

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13161, T6791

Differential Revision: https://secure.phabricator.com/D20187
2019-02-19 13:11:50 -08:00
epriestley
5310f1cdd9 Remove all whitespace options/configuration everywhere
Summary:
Depends on D20181. Depends on D20182. Fixes T3498. Ref T13161. My claim, at least, is that D20181 can be tweaked to be good enough to throw away this "feature" completely.

I think this feature was sort of a mistake, where the ease of access to `diff -bw` shaped behavior a very long time ago and then the train just ran a long way down the tracks in the same direction.

Test Plan: Grepped for `whitespace`, deleted almost everything. Poked around the UI a bit. I'm expecting the whitespace changes to get some more iteration this week so I not being hugely pedantic about testing this stuff exhaustively.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13161, T3498

Differential Revision: https://secure.phabricator.com/D20185
2019-02-19 13:09:29 -08:00
epriestley
661c758ff9 Render indent depth changes more clearly
Summary:
Ref T13161. See PHI723. Our whitespace handling is based on whitespace flags like `diff -bw`, mostly just for historical reasons: long ago, the easiest way to minimize the visual impact of indentation changes was to literally use `diff -bw`.

However, this approach is very coarse and has a lot of problems, like detecting `"ab" -> "a b"` as "only a whitespace change" even though this is always semantic. It also causes problems in YAML, Python, etc. Over time, we've added a lot of stuff to mitigate the downsides to this approach.

We also no longer get any benefits from this approach being simple: we need faithful diffs as the authoritative source, and have to completely rebuild the diff to `diff -bw` it. In the UI, we have a "whitespace mode" flag. We have the "whitespace matters" configuration.

I think ReviewBoard generally has a better approach to indent depth changes than we do (see T13161) where it detects them and renders them in a minimal way with low visual impact. This is ultimately what we want: reduce visual clutter for depth-only changes, but preserve whitespace changes in strings, etc.

Move toward detecting and rendering indent depth changes. Followup work:

  - These should get colorblind colors and the design can probably use a little more tweaking.
  - The OneUp mode is okay, but could be improved.
  - Whitespace mode can now be removed completely.
  - I'm trying to handle tabs correctly, but since we currently mangle them into spaces today, it's hard to be sure I actually got it right.

Test Plan: {F6214084}

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13161

Differential Revision: https://secure.phabricator.com/D20181
2019-02-19 12:40:05 -08:00
epriestley
92abe3c8fb Extract scope line selection logic from the diff rendering engine so it can reasonably be iterated on
Summary:
Ref T13249. Ref T11738. See PHI985. Currently, we have a crude heuristic for guessing what line in a source file provides the best context.

We get it wrong in a lot of cases, sometimes selecting very silly lines like "{". Although we can't always pick the same line a human would pick, we //can// pile on heuristics until this is less frequently completely wrong and perhaps eventually get it to work fairly well most of the time.

Pull the logic for this into a separate standalone class and make it testable to prepare for adding heuristics.

Test Plan: Ran unit tests, browsed various files in the web UI and saw as-good-or-better context selection.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13249, T11738

Differential Revision: https://secure.phabricator.com/D20171
2019-02-19 10:55:10 -08:00
epriestley
bcc90d8c6b Fix an off-by-one error affecting mail rendering of inlines on the final line of a file
Summary: Depends on D19837. Ref T13216. See PHI985. There's an off-by-one error here between how inline comments store "length" and how context rendering treats "length". We need to add 1 to the length, but currently do it a little too early. Do it slightly later so that inlines on the final line of a file render properly.

Test Plan: Left an inline on the final line of a new file, saw it render properly in HTML mail.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13216

Differential Revision: https://secure.phabricator.com/D19838
2018-11-26 10:12:09 -08:00
epriestley
79fdf5c127 Separate changeset analysis code from DifferentialDiff and provide a standalone rebuild-changesets workflow
Summary:
Ref T13137. The "analyze/cache data about changesets" step is becoming more involved. We recently added detection for generated code to support "Ignore generated changes" in Owners, and I now plan to hash the new file content so we can hide changes which have no effect.

Before adding this new hashing step, pull the "detect copied code" and "detect generated code" stuff out and move them to a separate `ChangesetEngine`. Then support doing a changeset rebuild directly with `bin/differential rebuild-changesets`.

This simplifies things a bit and makes testing easier since you don't need to keep creating new revisions to re-run copy/generated/hash logic.

Test Plan: Ran `bin/differential rebuild-changesets --revision Dxxx`, saw changesets rebuild. See also next change.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13137

Differential Revision: https://secure.phabricator.com/D19452
2018-05-16 17:17:28 -07:00
epriestley
af295341c8 Classify changesets as "generated" at creation time, in addition to display time
Summary:
Ref T13130. See PHI251. Currently, changesets are marked as "generated" (i.e., the file contains generated code and does not normally need to be reviewed) at display time.

An install would like support for having Owners rules ignore generated files. Additionally, future changes anticipate making "generated" and some other similar behaviors more flexible and more general.

To support these, move toward a world where:

  - Changesets have "attributes": today, generated. In the future, perhaps: third-party, highlight-as, encoding, enormous-text-file, etc.
  - Attributes are either "trusted" (usually: the server assigned the attribute) or "untrusted" (usually: the client assigned the attribute). For attributes like "highlight-as", this isn't relevant, but I'd like to provide tools so that you can't make `arc` mark every file as "generated" and sneak past review rules in the future.

Here, the `differential.generated-paths` config can mark a file as "generated" with a trusted attribute. The `@generated`-in-content rule can mark a file as "generated" with an untrusted attribute.

Putting these attributes on changesets at creation time instead of display time will let Owners interact with changesets cheaply: it won't have to render an entire changeset just to figure out if it's generated or not.

Test Plan:
  - Created a revision touching several files, some generated and some not.
  - Saw the generated files get marked properly with attribute metadata in the database, and show/fold as "Generated" in the UI.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13130

Differential Revision: https://secure.phabricator.com/D19425
2018-05-05 08:46:25 -07:00
Dmitri Iouchtchenko
9bd6a37055 Fix spelling
Summary: Noticed a couple of typos in the docs, and then things got out of hand.

Test Plan:
  - Stared at the words until my eyes watered and the letters began to swim on the screen.
  - Consulted a dictionary.

Reviewers: #blessed_reviewers, epriestley

Reviewed By: #blessed_reviewers, epriestley

Subscribers: epriestley, yelirekim, PHID-OPKG-gm6ozazyms6q6i22gyam

Differential Revision: https://secure.phabricator.com/D18693
2017-10-09 10:48:04 -07:00
Chad Little
283a95d2aa Build a page for viewing all inline comments
Summary: Adds a very basic list of all inline comments, threaded, and their status. Kept this a little simpler than the mock, mostly because sorting here feels a little strange given threads would be all over the place. Not sure sorted is needed in practice anyways. I'd probably lean towards just adding a JS checkbox to hide certain rows if needed in the future.

Test Plan:
Test various commenting structures:

 - Leave Comment
 - Update Diff
 - Leave new comment
 - Reply to comment
 - Reply to comment as revision author
 - Mark items as done
 - Update diff again

{F4996915}

Reviewers: epriestley

Reviewed By: epriestley

Subscribers: Korvin, epriestley

Differential Revision: https://secure.phabricator.com/D18112
2017-06-12 11:31:20 -07:00
epriestley
edfc6a6934 Convert some loadPreferences() to getUserSetting()
Summary:
Ref T4103. This doesn't get everything, but takes care of most of the easy stuff.

The tricky-ish bit here is that I need to move timezones, pronouns and translations to proper settings. I expect to pursue that next.

Test Plan:
- Grepped for `loadPreferences` to identify callsites.
- Changed start-of-week setting, loaded Calendar, saw correct start.
- Visited welcome page, read "Adjust Settings" point.
- Loaded Conpherence -- I changed behavior here slightly (switching threads drops the title glyph) but it wasn't consistent to start with and this seems like a good thing to push to the next version of Conpherence.
- Enabled Filetree, toggled in Differential.
- Disabled Filetree, no longer visible in Differential.
- Changed "Unified Diffs" preference to "Small Screens" vs "Always".
- Toggled filetree in Diffusion.
- Edited a task, saw sensible projects in policy dropdown.
- Viewed user profile, uncollapsed/collapsed side nav, reloaded page, sticky'd.
- Toggled "monospaced textareas", used a comment box, got appropriate fonts.
- Toggled durable column.
- Disabled title glyphs.
- Changed monospaced font to 18px/36px impact.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T4103

Differential Revision: https://secure.phabricator.com/D16004
2016-06-02 06:29:20 -07:00
epriestley
92ea4fb098 Stop two special cache writes in read-only mode
Summary:
Ref T10769. The user availability cache write shouldn't happen in read-only mode, nor should the Differential parse cache write.

(We might want to turn off the availbility feature completely since it's potentially expensive if we can't cache it, but I think we're OK for now.)

Test Plan:
In read-only mode:

  - Browsed as a user with an out-of-date availability cache.
  - Loaded an older revision without cached parse data.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T10769

Differential Revision: https://secure.phabricator.com/D15988
2016-05-30 10:12:09 -07:00
epriestley
bd9bcaa8ff Improve HTML mail rendering of inline patches
Summary: Fixes T9790. This uses a simple renderer, like the inline context renderer, that emphasizes getting a quick glance at small changes and working reasonably on mobile devices.

Test Plan:
  - Set `inline` setting to `9999`.
  - Created a diff.
  - Saw it render reasonably in HTML mail.
  - Also tested text mail to make sure I didn't break that.

{F1310137, size=full}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T9790

Differential Revision: https://secure.phabricator.com/D15901
2016-05-12 12:13:40 -07:00
epriestley
1baef494c1 Pick context windows for inlines in a slightly smarter way
Summary:
Ref T10694. This mostly prevents us from having a degenerate case if someone leaves a 200-line inline.

  - For one-line inlines, show 1 line of context above and below (3 lines total).
  - For 3+ line inlines, show just the inline.
  - For 7+ line inlines, show only the first part.

Test Plan: Made a bunch of weird long/short/different-sized comments, saw reasonble-appearing context in text and HTML mail output.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T10694

Differential Revision: https://secure.phabricator.com/D15853
2016-05-05 11:15:09 -07:00