Commit Graph

176 Commits

Author SHA1 Message Date
Utkarsh Saxena 55925da4c9 [clangd] Add semantic selection to ClangdLSPServer.
Summary:
This adds semantic selection to the LSP Server.
Adds support for serialization of input request and the output reply.
Also adds regression tests for the feature.

Currently we do not support multi cursor.The LSP Server only accepts single position in the request as opposed to many position in the spec.

Spec:
https://github.com/microsoft/language-server-protocol/blob/dbaeumer/3.15/specification.md#textDocument_selectionRange

Reviewers: hokein

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D67720

llvm-svn: 372753
2019-09-24 13:38:33 +00:00
Kadir Cetinkaya 5b270932cc [clangd] Support multifile edits as output of Tweaks
Summary:
First patch for propogating multifile changes from tweak outputs to LSP
WorkspaceEdits.

Uses SM to convert tooling::Replacements to TextEdits.
Errors out if there are any inconsistencies between the draft version and the
version generated the edits.

Reviewers: sammccall

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D66637

llvm-svn: 371392
2019-09-09 12:28:44 +00:00
Ilya Biryukov 63d5d16237 [clangd] Replace HighlightingKind::NumKinds with LastKind. NFC
Summary:
The latter simplifies the client code by avoiding the need to handle it
as a separate case statement.

Reviewers: hokein

Reviewed By: hokein

Subscribers: nridge, MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D67277

llvm-svn: 371375
2019-09-09 08:57:17 +00:00
Haojian Wu 0a6000f2cb [clangd] Send highlighting diff beyond the end of the file.
Summary: This would make the client life (tracking the changes) easier.

Reviewers: jvikstrom

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D66541

llvm-svn: 369884
2019-08-26 08:38:45 +00:00
Haojian Wu 08d93f1ed3 [clangd] Send suppported codeActionKinds to the client.
Summary:
This would make client know which codeActionKinds that clangd may
return.

VSCode will add a new entry "Refactor..." (which shows all
refactoring-kind code actions) in the right-click menu.

Reviewers: ilya-biryukov

Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D66592

llvm-svn: 369656
2019-08-22 14:53:45 +00:00
Haojian Wu 427762f03d [clangd] suppress -Wparentheses warning: suggest parentheses around ‘&&’ within ‘||’
llvm-svn: 369105
2019-08-16 13:20:51 +00:00
Ilya Biryukov 12864001a6 [clangd] Simplify code of ClangdLSPServer::onCommand
Summary:
By inlining a complicated lambda into its single call-site.

Also ensure we call Reply() exactly once even if tweaks return both
ShowMessage and ApplyEdit effects.

Reviewers: hokein

Reviewed By: hokein

Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D66343

llvm-svn: 369100
2019-08-16 12:46:41 +00:00
Ilya Biryukov b3c2f5d2ee [clangd] Remove Bind, use C++14 lambda captures instead. NFC
llvm-svn: 369089
2019-08-16 09:20:01 +00:00
Benjamin Kramer 9880b5dd21 [clangd] Don't use Bind() where C++14 move capture works
llvm-svn: 369005
2019-08-15 14:16:06 +00:00
Jonas Devlieghere 1c705d9c53 [clang-tools-extra] Migrate llvm::make_unique to std::make_unique
Now that we've moved to C++14, we no longer need the llvm::make_unique
implementation from STLExtras.h. This patch is a mechanical replacement
of (hopefully) all the llvm::make_unique instances across the monorepo.

Differential revision: https://reviews.llvm.org/D66259

llvm-svn: 368944
2019-08-14 23:52:23 +00:00
Haojian Wu f25163498b [clangd] Add a callback mechanism for handling responses from client.
Summary:
The callback will be invoked in clangd when we receive a reply from the client.

This is a prerequisite of implementing a generic mechanism for chainable
refactorings (e.g. extract variable and rename), this would allow server to
trigger a new request to the LSP client after receiving a reply from the client.

Reviewers: sammccall

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D65387

llvm-svn: 367845
2019-08-05 12:48:09 +00:00
Johan Vikstrom c2653ef27c [clangd] Duplicate lines of semantic highlightings sent removed.
Summary: Added a class for diffing highlightings and removing duplicate lines. Integrated into the highlighting generation flow. Only works correctly if all tokens are on a single line. Also returns empty lines if the IDE should remove previous highlightings on a line.

Reviewers: hokein, sammccall, ilya-biryukov

Subscribers: MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D64475

llvm-svn: 367521
2019-08-01 08:08:44 +00:00
Haojian Wu f429ab60e6 [clangd] Implement "prepareRename"
Summary:
- "prepareRename" request is added in LSP v3.12.0
- also update the vscode-client dependency to pick-up the rename bug fix[1]

[1]: https://github.com/microsoft/vscode-languageserver-node/issues/447

Reviewers: sammccall

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D63126

llvm-svn: 366873
2019-07-24 07:49:23 +00:00
Nathan Ridge 087b044c49 [clangd] Implement typeHierarchy/resolve for subtypes
Summary:
This allows the client to resolve subtypes one level at a time.

For supertypes, this is not necessary, because we eagerly compute
supertypes and return all levels.

Reviewers: sammccall

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D64308

llvm-svn: 365986
2019-07-13 03:24:48 +00:00
Russell Gallop de54e2c4df Revert "[clangd] Implement typeHierarchy/resolve for subtypes"
Causing test failure on Windows bot

This reverts commit 5b9484e559.

llvm-svn: 365899
2019-07-12 13:35:58 +00:00
Nathan Ridge 5b9484e559 [clangd] Implement typeHierarchy/resolve for subtypes
Summary:
This allows the client to resolve subtypes one level at a time.

For supertypes, this is not necessary, because we eagerly compute
supertypes and return all levels.

Reviewers: sammccall

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D64308

llvm-svn: 365867
2019-07-12 03:26:32 +00:00
Haojian Wu 6b043f0518 [clangd] Add a flag to clangdServer rename function to control whether we want format the replacements.
Summary:
This would allow clangd embedders to use the ClangdServer::rename for other
purposes (highlighting all the occurrences of the symbol in prepare
stage).

Reviewers: sammccall, ilya-biryukov

Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D64481

llvm-svn: 365631
2019-07-10 13:44:22 +00:00
Sam McCall 5f092e31ab [clangd] Use -completion-style=bundled by default if signature help is available
Summary:
I didn't manage to find something nicer than optional<bool>, but at least I
found a sneakier comment.

Reviewers: kadircet

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D64216

llvm-svn: 365356
2019-07-08 17:27:15 +00:00
Haojian Wu 1ca2ee4dc1 [clangd] Some tweaks on semantic highlighting lookuptable.
Summary:
- move toTextMateScope to SemanticHighlighting.h;
- move the buildLookupTable to LSP layer (as LSP requires such form);

Reviewers: sammccall, jvikstrom

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D64202

llvm-svn: 365135
2019-07-04 12:27:21 +00:00
Johan Vikstrom a848dab7a3 [clangd] Emit publishSemanticHighlighting in LSP if enabled
Summary: Emit publishSemanticHighlighting in LSP if enabled

Reviewers: hokein, kadircet

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D63919

llvm-svn: 365111
2019-07-04 07:53:12 +00:00
Kadir Cetinkaya 256247cfb7 [clangd] Enable extraction of system includes from custom toolchains
Summary:
Some custom toolchains come with their own header files and compiler
drivers. Those compiler drivers implicitly know about include search path for
those headers. This patch aims to extract that information from drivers and add
it to the command line when invoking clang frontend.

Reviewers: sammccall

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D62804

llvm-svn: 364389
2019-06-26 07:45:27 +00:00
Sam McCall 08372eb73b Revert "[clangd] Return vector<TextEdit> from applyTweak. NFC"
This reverts commit r363691.

llvm-svn: 363766
2019-06-19 07:29:10 +00:00
Ilya Biryukov df9ee08b64 [clangd] Return vector<TextEdit> from applyTweak. NFC
For the same reasons as r363150, which got overwritten by changes in
r363680.

Sending without review to unbreak our integrate.

llvm-svn: 363691
2019-06-18 15:15:41 +00:00
Sam McCall 395fde753c [clangd] Add hidden tweaks to dump AST/selection.
Summary:
This introduces a few new concepts:
 - tweaks have an Intent (they don't all advertise as refactorings)
 - tweaks may produce messages (for ShowMessage notification). Generalized
   Replacements -> Effect.
 - tweaks (and other features) may be hidden (clangd -hidden-features flag).
   We may choose to promote these one day. I'm not sure they're worth their own
   feature flags though.

Verified it in vim-clangd (not yet open source), curious if the UI is ok in VSCode.

Reviewers: ilya-biryukov

Subscribers: mgorny, MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D62538

llvm-svn: 363680
2019-06-18 13:37:54 +00:00
Sam McCall 8d41294c18 [clangd] Add a capability to enable completions with fixes.
Reviewers: ilya-biryukov

Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D63091

llvm-svn: 363664
2019-06-18 11:57:26 +00:00
Ilya Biryukov 04112ecd41 [clangd] Return TextEdits from ClangdServer::applyTweak
Summary:
Instead of `tooling::Replacements`. So that embedders do not need to store
the contents of the file.

This also aligns better with `ClangdServer::rename`.

Reviewers: kadircet, hokein

Reviewed By: hokein

Subscribers: MaskRay, jkorous, arphaman, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D63140

llvm-svn: 363150
2019-06-12 12:03:24 +00:00
Sam McCall 25c6257ba0 [clangd] Revamp textDocument/onTypeFormatting.
Summary:
The existing implementation (which triggers on }) is fairly simple and
has flaws:
 - doesn't trigger frequently/regularly enough (particularly in editors that type the }
 for you)
 - often reformats too much code around the edit
 - has jarring cases that I don't have clear ideas for fixing

This implementation is designed to trigger on newline, which feels to me more
intuitive than } or ;.
It does have allow for reformatting after other characters - it has a
basic behavior and a model for adding specialized behavior for
particular characters. But at least initially I'd stick to advertising
\n in the capabilities.

This also handles comment splitting: when you insert a line break inside
a line comment, it will make the new line into an aligned line comment.

Working on tests, but want people to patch it in and try it - it's hard to
see if "feel" is right purely by looking at a test.

Reviewers: ilya-biryukov, hokein

Subscribers: mgorny, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D60605

llvm-svn: 362939
2019-06-10 14:26:21 +00:00
Ilya Biryukov a7a1147d4f [clangd] Return empty results on spurious completion triggers
Summary:
We currently return an error, this causes `coc.nvim` and VSCode to
show an error message in the logs.

Returning empty list of completions allows to avod the error message
without altering other user-visible behavior.

Reviewers: sammccall

Reviewed By: sammccall

Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D62999

llvm-svn: 362811
2019-06-07 16:24:38 +00:00
Simon Pilgrim 5f7c20e279 Fix Wshadow warning
llvm-svn: 362489
2019-06-04 11:11:51 +00:00
Ilya Biryukov 4ef0f82b71 [clangd] Support offsets for parameters in signatureHelp
Summary: Added to LSP in version 3.14

Reviewers: hokein

Reviewed By: hokein

Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D62476

llvm-svn: 362481
2019-06-04 09:36:59 +00:00
Ilya Biryukov f9169d0896 [clangd] Represent Hover result using FormattedString
Reviewers: sammccall, kadircet

Reviewed By: kadircet

Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D61601

llvm-svn: 361940
2019-05-29 10:01:00 +00:00
Kadir Cetinkaya c6578eefdd [clangd] Introduce a structured hover response
Summary:
Change ClangdServer layer to output a structured response for Hover,
which can be rendered by client according to their needs.

Reviewers: sammccall, ilya-biryukov

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D61497

llvm-svn: 361803
2019-05-28 10:29:58 +00:00
Sam McCall b9ec3e9370 [clangd] Oops, switchSourceHeader still needs to return a URI.
Reviewers: kadircet

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D61630

llvm-svn: 360121
2019-05-07 08:30:32 +00:00
Sam McCall 111fe84bbc [clangd] switchSourceHeader uses null not empty string as sentinel.
As far as I can see, only theia actually implements this, and it expects null.

llvm-svn: 360119
2019-05-07 07:55:35 +00:00
Sam McCall c9e4ee9ca9 [clangd] Support relatedInformation in diagnostics.
Summary: We already have the structure internally, we just need to expose it.

Reviewers: ilya-biryukov

Subscribers: ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D60267

llvm-svn: 358675
2019-04-18 15:17:07 +00:00
Ilya Biryukov d9c24dca73 [clangd] Return clangd::TextEdit in ClangdServer::rename. NFC
Summary:
Instead of tooling::Replacement. To avoid the need to have contents of
the file at the caller site. This also aligns better with other methods
in ClangdServer, majority of those already return LSP-specific data
types.

Reviewers: hokein, ioeric, sammccall

Reviewed By: sammccall

Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D60179

llvm-svn: 357561
2019-04-03 07:18:43 +00:00
Sam McCall a69698f45f [clangd] Support utf-8 offsets (rather than utf-16) as a protocol extension
Summary:
Still some pieces to go here: unit tests for new SourceCode functionality and
a command-line flag to force utf-8 mode. But wanted to get early feedback.

Reviewers: hokein

Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, kadircet, jdoerfert, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D58275

llvm-svn: 357102
2019-03-27 17:47:49 +00:00
Ilya Biryukov 49c1071394 [clangd] Send empty diagnostics when a file is closed
Summary:
The LSP clients cannot know clangd will not send diagnostic updates
for closed files, so we send them an empty list of diagnostics to
avoid showing stale diagnostics for closed files in the UI, e.g. in the
"Problems" pane of VSCode.

Fixes PR41217.

Reviewers: hokein

Reviewed By: hokein

Subscribers: ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D59757

llvm-svn: 356880
2019-03-25 10:15:11 +00:00
Kadir Cetinkaya 8665802202 [clangd] Add support for type hierarchy (super types only for now)
Summary:
Patch by Nathan Ridge(@nridge)!

This is an LSP extension proposed here:
https://github.com/Microsoft/vscode-languageserver-node/pull/426

An example client implementation can be found here:
https://github.com/theia-ide/theia/pull/3802

Reviewers: kadircet, sammccall

Reviewed By: kadircet

Subscribers: jdoerfert, sammccall, cfe-commits, mgorny, dschaefer, simark, ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, kadircet

Tags: #clang

Differential Revision: https://reviews.llvm.org/D56370

llvm-svn: 356445
2019-03-19 09:27:04 +00:00
Simon Pilgrim e9a136b58f Remove trailing semicolon. NFCI.
llvm-svn: 352990
2019-02-03 14:08:30 +00:00
Sam McCall 0dbab7feca [Clangd] textDocument/definition and textDocument/declaration "bounce" between definition and declaration location when they are distinct.
Summary:
This helps minimize the disruption of not returning declarations as part of
a find-definition response (r352864).

Reviewers: hokein

Subscribers: ioeric, MaskRay, jkorous, arphaman, kadircet, ilya-biryukov

Tags: #clang

Differential Revision: https://reviews.llvm.org/D57580

llvm-svn: 352953
2019-02-02 05:56:00 +00:00
Sam McCall 866ba2c924 [clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.

Language server changes:
 - textDocument/definition now returns a definition if one is found, otherwise
   the declaration. It no longer returns declaration + definition if they are
   distinct.
 - textDocument/declaration returns the best declaration we can find.
 - For macros, the active macro definition is returned for both methods.
 - For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.

C++ API changes:
 - findDefinitions is replaced by locateSymbolAt, which returns a
   vector<LocatedSymbol> - one for each symbol under the cursor.
 - this contains the preferred declaration, the definition (if found), and
   the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.

Reviewers: hokein

Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits

Differential Revision: https://reviews.llvm.org/D57388

llvm-svn: 352864
2019-02-01 11:26:13 +00:00
Ilya Biryukov c6ed77812b [clangd] Drop fixes if replying with tweaks resulted in an error
This should not happen in normal operation, as it implies that the diagnostics
with some available fixes were produced but the AST is invalid.
Moreover, the code had an error: always returned code actions ignoring the
SupportsCodeAction capability and writing a test for this is impossible,
since this can only happen due to programmer's error rather than invalid inputs.

llvm-svn: 352624
2019-01-30 14:24:17 +00:00
Ilya Biryukov c9409c6d86 [clangd] Fix a use after move
Introduced in r352494.

llvm-svn: 352612
2019-01-30 09:39:01 +00:00
Ilya Biryukov cce67a32cf [clangd] Interfaces for writing code tweaks
Summary:
The code tweaks are an implementation of mini-refactorings exposed
via the LSP code actions. They run in two stages:
  - Stage 1. Decides whether the action is available to the user and
    collects all the information required to finish the action.
    Should be cheap, since this will run over all the actions known to
    clangd on each textDocument/codeAction request from the client.

  - Stage 2. Uses information from stage 1 to produce the actual edits
    that the code action should perform. This stage can be expensive and
    will only run if the user chooses to perform the specified action in
    the UI.

One unfortunate consequence of this change is increased latency of
processing the textDocument/codeAction requests, which now wait for an
AST. However, we cannot avoid this with what we have available in the LSP
today.

Reviewers: kadircet, ioeric, hokein, sammccall

Reviewed By: sammccall

Subscribers: mgrang, mgorny, MaskRay, jkorous, arphaman, cfe-commits

Differential Revision: https://reviews.llvm.org/D56267

llvm-svn: 352494
2019-01-29 14:17:36 +00:00
Haojian Wu 1ca0c58c81 [clangd] Support clang-tidy configuration in clangd.
Summary:
This patch adds some basic supports for clang-tidy configurations in clangd:
      - clangd will respect .clang-tidy configurations for each file
      - we don't aim to support all clang-tidy options in clangd, only a
        small subset of condfigurations (options related to which checks will be
        enabled) are supported.
      - add a `clang-tidy-checks` CLI option that can override options from
        .clang-tidy file

Reviewers: ilya-biryukov, sammccall

Reviewed By: sammccall

Subscribers: javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits

Differential Revision: https://reviews.llvm.org/D55256

llvm-svn: 351792
2019-01-22 09:39:05 +00:00
Kadir Cetinkaya be6b35dac4 [clangd] Filter out plugin related flags and move all commandline manipulations into OverlayCDB.
Summary:
Some projects make use of clang plugins when building, but clangd is
not aware of those plugins therefore can't work with the same compile command
arguments.

There were multiple places clangd performed commandline manipulations,
 this one also moves them all into OverlayCDB.

Reviewers: ilya-biryukov

Subscribers: klimek, sammccall, ioeric, MaskRay, jkorous, arphaman, cfe-commits

Differential Revision: https://reviews.llvm.org/D56841

llvm-svn: 351788
2019-01-22 09:10:20 +00:00
Chandler Carruth 2946cd7010 Update the file headers across all of the LLVM projects in the monorepo
to reflect the new license.

We understand that people may be surprised that we're moving the header
entirely to discuss the new license. We checked this carefully with the
Foundation's lawyer and we believe this is the correct approach.

Essentially, all code in the project is now made available by the LLVM
project under our new license, so you will see that the license headers
include that license only. Some of our contributors have contributed
code under our old license, and accordingly, we have retained a copy of
our old license notice in the top-level files in each project and
repository.

llvm-svn: 351636
2019-01-19 08:50:56 +00:00
Haojian Wu c34f022bfe [clangd] Add Limit parameter for xref.
Reviewers: sammccall

Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits

Differential Revision: https://reviews.llvm.org/D56597

llvm-svn: 351081
2019-01-14 18:11:09 +00:00
Ilya Biryukov f2001aa743 [clangd] Remove 'using namespace llvm' from .cpp files. NFC
The new guideline is to qualify with 'llvm::' explicitly both in
'.h' and '.cpp' files. This simplifies moving the code between
header and source files and is easier to keep consistent.

llvm-svn: 350531
2019-01-07 15:45:19 +00:00